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.Enumeration;
020: import java.util.ArrayList;
021: import java.util.StringTokenizer;
022: import java.util.Iterator;
023: import org.griphyn.common.util.Version;
024: import org.griphyn.common.util.Separator;
025: import org.griphyn.vdl.parser.VDLxParser;
026: import org.griphyn.vdl.classes.*;
027: import org.griphyn.vdl.router.*;
028: import org.griphyn.vdl.dbschema.*;
029: import org.griphyn.vdl.util.Logging;
030: import org.griphyn.vdl.util.ChimeraProperties;
031: import org.griphyn.vdl.directive.*;
032: import gnu.getopt.*;
033:
034: /**
035: * This class generates the DAX per the request for an lfn or a derivation.
036: *
037: * @author Jens-S. Vöckler
038: * @author Yong Zhao
039: * @version $Revision: 50 $
040: *
041: * @see org.griphyn.vdl.router.Route
042: * @see org.griphyn.vdl.router.BookKeeper
043: */
044: public class GetDAX extends Toolkit {
045: /**
046: * ctor: Constructs a new instance object with the given application name.
047: */
048: public GetDAX(String appName) {
049: super (appName);
050: }
051:
052: /**
053: * Implements printing the usage string onto stdout.
054: */
055: public void showUsage() {
056: String linefeed = System.getProperty("line.separator", "\r\n");
057:
058: System.out
059: .println("$Id: GetDAX.java 50 2007-05-19 00:48:32Z gmehta $"
060: + linefeed
061: + "VDS version "
062: + Version.instance().toString() + linefeed);
063:
064: System.out
065: .println("Usage: "
066: + this .m_application
067: + ' '
068: + "[-d dbx] [-l label] [-m max] [-o DAX] -n ns -i id -v ver"
069: + linefeed
070: + " or: "
071: + this .m_application
072: + ' '
073: + "[-d dbx] [-l label] [-m max] [-o DAX] -f f1[,..] -F lof"
074: + linefeed + " -D d1[,..] -L lod");
075:
076: System.out
077: .println(linefeed
078: + "Generic options: "
079: + linefeed
080: + " -V|--version print version information and exit."
081: + linefeed
082: + " -d|--dbase dbx associates the dbname with the database, unused."
083: + linefeed
084: + " --verbose increases the verbosity level."
085: + linefeed
086: + " -l|--label label uses the specified label for the output DAX, default \"test\"."
087: + linefeed
088: + " -o|--output DAX writes the generated results into outfn, default is stdout."
089: + linefeed
090: + " -m|--maxdepth max only search up to the specified depth, default is "
091: + Route.MAXIMUM_DEPTH
092: + "."
093: + linefeed
094: + " For complex or large graphs, you may want to increase this."
095: + linefeed
096: + " -X|--xmlns prefix uses an XML namespace prefix for the generated DAX document."
097: + linefeed
098: + linefeed
099: + "Group 1: At least one of these must be used, but none of group 2 below:"
100: + linefeed
101: + " -n|--namespace ns uses namespace ns to search for matching DVs, default null."
102: + linefeed
103: + " -i|--name name uses the specified DV name to search for it, required."
104: + linefeed
105: + " -v|--ver vs uses the specified version to narrow DVs, default null."
106: + linefeed
107: + linefeed
108: + "Group 2: All of these may be mixed, but not used with group 1 above:"
109: + linefeed
110: + " -f|--file fn[,..] requests LFN or a list of LFNs to be materialized."
111: + linefeed
112: + " -f|--lfn is a synonym for the --file option."
113: + linefeed
114: + " -F|--filelist lof read the LFNs from file lolfn, one per line."
115: + linefeed
116: + " -D|--dv dv[,..] requests the DV or list of DVs to be produced. Each argument"
117: + linefeed
118: + " is a fully-qualified derivation name namespace::name:version"
119: + linefeed
120: + " with the usual omission rules applying."
121: + linefeed
122: + " -D|--derivation is a synonym for the --dv option."
123: + linefeed
124: + " -L|--dvlist lodvs read the DVs from file lodvs, one per line."
125: + linefeed);
126:
127: System.out
128: .println("The following exit codes are produced:"
129: + linefeed
130: + " 0 :-) Success"
131: + linefeed
132: + " 1 :-| Empty result while "
133: + m_application
134: + " still ran successfully."
135: + linefeed
136: + " 2 :-( Runtime error detected by "
137: + m_application
138: + ", please read the message."
139: + linefeed
140: + " 3 8-O Fatal error merits a program abortion. Please carefully check your"
141: + linefeed
142: + " configuration files and setup before filing a bug report."
143: + linefeed);
144: }
145:
146: /**
147: * Creates a set of options.
148: */
149: protected LongOpt[] generateValidOptions() {
150: LongOpt[] lo = new LongOpt[20];
151:
152: lo[0] = new LongOpt("dbase", LongOpt.REQUIRED_ARGUMENT, null,
153: 'd');
154: lo[1] = new LongOpt("version", LongOpt.NO_ARGUMENT, null, 'V');
155: lo[2] = new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'h');
156: lo[3] = new LongOpt("verbose", LongOpt.NO_ARGUMENT, null, 1);
157:
158: lo[4] = new LongOpt("label", LongOpt.REQUIRED_ARGUMENT, null,
159: 'l');
160: lo[5] = new LongOpt("output", LongOpt.REQUIRED_ARGUMENT, null,
161: 'o');
162: lo[6] = new LongOpt("maxdepth", LongOpt.REQUIRED_ARGUMENT,
163: null, 'm');
164: lo[7] = new LongOpt("xmlns", LongOpt.REQUIRED_ARGUMENT, null,
165: 'X');
166:
167: lo[8] = new LongOpt("namespace", LongOpt.REQUIRED_ARGUMENT,
168: null, 'n');
169: lo[9] = new LongOpt("ns", LongOpt.REQUIRED_ARGUMENT, null, 'n');
170: lo[10] = new LongOpt("name", LongOpt.REQUIRED_ARGUMENT, null,
171: 'i');
172: lo[11] = new LongOpt("id", LongOpt.REQUIRED_ARGUMENT, null, 'i');
173: lo[12] = new LongOpt("ver", LongOpt.REQUIRED_ARGUMENT, null,
174: 'v');
175: lo[13] = new LongOpt("vs", LongOpt.REQUIRED_ARGUMENT, null, 'v');
176:
177: lo[14] = new LongOpt("file", LongOpt.REQUIRED_ARGUMENT, null,
178: 'f');
179: lo[15] = new LongOpt("lfn", LongOpt.REQUIRED_ARGUMENT, null,
180: 'f');
181: lo[16] = new LongOpt("filelist", LongOpt.REQUIRED_ARGUMENT,
182: null, 'F');
183: lo[17] = new LongOpt("derivation", LongOpt.REQUIRED_ARGUMENT,
184: null, 'D');
185: lo[18] = new LongOpt("dv", LongOpt.REQUIRED_ARGUMENT, null, 'D');
186: lo[19] = new LongOpt("dvlist", LongOpt.REQUIRED_ARGUMENT, null,
187: 'L');
188:
189: return lo;
190: }
191:
192: /**
193: * Get the request for a dv or an lfn and generate the corresponding
194: * DAX.
195: */
196: public static void main(String[] args) {
197: int result = 0;
198: int verbose = 0;
199: Writer bw = null;
200: DatabaseSchema dbschema = null;
201: GetDAX me = null;
202:
203: try {
204: me = new GetDAX("gendax");
205: if (args.length == 0) {
206: me.showUsage();
207: return;
208: }
209:
210: // get the commandline options
211: Getopt opts = new Getopt(me.m_application, args,
212: "hd:m:n:i:v:o:f:l:D:F:L:VX:", me
213: .generateValidOptions());
214: opts.setOpterr(false);
215:
216: boolean flag = false;
217: String xmlns = null;
218: String arg = null;
219: String label = null;
220: String dbase = null;
221: String ns = null;
222: String id = null;
223: String vs = null;
224: String fn = null;
225: int maxdepth = -1;
226: ArrayList derivations = new ArrayList();
227: ArrayList filenames = new ArrayList();
228:
229: int option = 0;
230: while ((option = opts.getopt()) != -1) {
231: switch (option) {
232: case 1:
233: verbose++;
234: me.increaseVerbosity();
235: break;
236:
237: case 'V':
238: System.out
239: .println("$Id: GetDAX.java 50 2007-05-19 00:48:32Z gmehta $");
240: System.out.println("VDS version "
241: + Version.instance().toString());
242: return;
243:
244: case 'X':
245: xmlns = opts.getOptarg();
246: break;
247:
248: case 'D':
249: arg = opts.getOptarg();
250: if (arg != null) {
251: StringTokenizer st = new StringTokenizer(arg,
252: ",", false);
253: while (st.hasMoreTokens())
254: derivations.add(st.nextToken());
255: }
256: break;
257:
258: case 'd':
259: dbase = opts.getOptarg();
260: break;
261:
262: case 'F':
263: arg = opts.getOptarg();
264: if (arg != null) {
265: int nr = me.readFile(arg, filenames);
266: me.m_logger.log("app", 1, "read " + nr
267: + " LFNs from " + arg);
268: }
269: break;
270:
271: case 'f':
272: arg = opts.getOptarg();
273: if (arg != null) {
274: StringTokenizer st = new StringTokenizer(arg,
275: ",", false);
276: while (st.hasMoreTokens())
277: filenames.add(st.nextToken());
278: }
279: break;
280:
281: case 'L':
282: arg = opts.getOptarg();
283: if (arg != null) {
284: int nr = me.readFile(arg, derivations);
285: me.m_logger.log("app", 1, "read " + nr
286: + " DV names from " + arg);
287: }
288: break;
289:
290: case 'l':
291: arg = opts.getOptarg();
292: if (arg != null)
293: label = arg;
294: break;
295:
296: case 'm':
297: arg = opts.getOptarg();
298: if (arg != null)
299: maxdepth = Integer.valueOf(arg).intValue();
300: break;
301:
302: case 'n':
303: arg = opts.getOptarg();
304: if (arg != null) {
305: ns = arg;
306: flag = true;
307: }
308: break;
309:
310: case 'i':
311: arg = opts.getOptarg();
312: if (arg != null) {
313: id = arg;
314: flag = true;
315: }
316: break;
317:
318: case 'v':
319: arg = opts.getOptarg();
320: if (arg != null) {
321: vs = arg;
322: flag = true;
323: }
324: break;
325:
326: case 'o':
327: arg = opts.getOptarg();
328: if (arg != null)
329: fn = arg;
330: break;
331:
332: case 'h':
333: me.showUsage();
334: return;
335:
336: default:
337: me.showUsage();
338: throw new RuntimeException(
339: "Incorrect option or option usage");
340: }
341: }
342:
343: // you can use either the pattern match, or -D and -f
344: int group2 = derivations.size() + filenames.size();
345: if (!flag && group2 == 0) {
346: me.showUsage();
347: throw new RuntimeException(
348: "You must specify either group 1 (-n -i -v) or group 2 (-f -F -L -D) options!");
349: }
350:
351: // bug#90/91: warn about mixing options groups
352: if (flag && group2 > 0) {
353: me.m_logger
354: .log("default", 0,
355: "Warning: You are mixing group 1 and group 2 options!");
356: }
357:
358: // bug#90/91: require name in group1 options.
359: if (flag && (id == null || id.length() == 0)) {
360: throw new RuntimeException(
361: "Group 1 options require -i|--name");
362: }
363:
364: // Connect the database.
365: String schemaName = ChimeraProperties.instance()
366: .getVDCSchemaName();
367:
368: Connect connect = new Connect();
369: dbschema = connect.connectDatabase(schemaName);
370: Explain explain = new Explain(dbschema);
371:
372: // constraint on search
373: if (maxdepth >= 0)
374: explain.setMaximumDepth(maxdepth);
375:
376: // Make the request.
377: if (flag)
378: explain.requestDerivation(ns, id, vs);
379: if (filenames.size() > 0)
380: explain.requestLFN(filenames);
381: if (derivations.size() > 0) {
382: int size = derivations.size();
383: int count = 1;
384: for (Iterator i = derivations.iterator(); i.hasNext(); count++) {
385: String what = (String) i.next();
386: me.m_logger.log("app", 2, "requesting " + what
387: + " (" + count + "/" + size + ")");
388: explain.requestDerivation(what);
389: }
390: }
391:
392: // show the DAX
393: if (fn != null) {
394: // save to file
395: me.m_logger.log("app", 1, "saving output to " + fn);
396: bw = new BufferedWriter(new FileWriter(fn));
397: } else {
398: // somebody may have redirected stdout, thus buffer!
399: bw = new BufferedWriter(new PrintWriter(System.out));
400: }
401:
402: // write resulting DAX
403: explain.writeDAX(bw, label, xmlns);
404: bw.flush();
405: bw.close();
406:
407: // fail on empty requested?
408: if (explain.isEmpty()) {
409: System.err.println("ERROR: The resulting DAX is empty");
410: result = 1;
411: }
412:
413: dbschema.close();
414: } catch (IOException ioe) {
415: System.err.println("IO ERROR: " + ioe.getMessage());
416: if (verbose > 0)
417: ioe.printStackTrace(System.err);
418: result = 2;
419: } catch (RuntimeException rte) {
420: System.err.println("RT ERROR: " + rte.getMessage());
421: if (verbose > 0)
422: rte.printStackTrace(System.err);
423: result = 2;
424: } catch (Exception e) {
425: e.printStackTrace(System.err);
426: System.err.println("FATAL: " + e.getMessage());
427: result = 3;
428: }
429: if (result != 0)
430: System.exit(result);
431: }
432: }
|