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:
016: package org.griphyn.vdl.toolkit;
017:
018: import java.io.*;
019: import java.util.Iterator;
020: import java.util.ArrayList;
021: import java.util.List;
022: import java.util.StringTokenizer;
023: import java.sql.SQLException;
024: import org.griphyn.common.util.Version;
025: import org.griphyn.common.util.Currently;
026: import org.griphyn.common.util.Separator;
027: import org.griphyn.vdl.parser.VDLxParser;
028: import org.griphyn.vdl.classes.*;
029: import org.griphyn.vdl.dbschema.*;
030: import org.griphyn.vdl.util.Logging;
031: import org.griphyn.vdl.util.ChimeraProperties;
032: import org.griphyn.vdl.directive.*;
033: import gnu.getopt.*;
034:
035: /**
036: * This class searches definitions that match the namespace, name,
037: * version triple, then prints the search results in one of the formats:
038: * vdlx, vdlt, or name. Alternatively, it permits to search from a list
039: * of inputs, either DVs or LFNs.
040: *
041: * @author Jens-S. Vöckler
042: * @author Yong Zhao
043: * @version $Revision: 50 $
044: *
045: * @see org.griphyn.vdl.parser.VDLxParser
046: */
047:
048: public class SearchVDC extends Toolkit {
049: /**
050: * Constructor
051: */
052: public SearchVDC(String appName) {
053: super (appName);
054: }
055:
056: /**
057: * Prints the usage string onto stdout.
058: */
059: public void showUsage() {
060: String linefeed = System.getProperty("line.separator", "\r\n");
061:
062: System.out
063: .println("$Id: SearchVDC.java 50 2007-05-19 00:48:32Z gmehta $"
064: + linefeed
065: + "VDS version "
066: + Version.instance().toString() + linefeed);
067:
068: System.out
069: .println("Usage: "
070: + this .m_application
071: + " [general] [-t tr|dv] [[-n ns] [-i id] [-v vs] | -D dv] [-L lod]"
072: + linefeed + " or: " + this .m_application
073: + " [general] [-t i|o|io] [-f lfn | -F lof]");
074:
075: System.out
076: .println(linefeed
077: + "General 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: + " -l|--list x|t|n print x:VDLx, t:VDLt or just a table of n:names."
086: + linefeed
087: + " -e|--error if present, return failure for a combined empty result set."
088: + linefeed
089: + " -E|--empty if present and bundling, raise an error for any empty match."
090: + linefeed
091: + " -o|--output fn put the output into the file fn, default is stdout."
092: + linefeed
093: + linefeed
094: + "Group 1: Search for definitions"
095: + linefeed
096: + " -t|--type tr|dv|all Search only for TR or DV, default is all (both)."
097: + linefeed
098: + " -n|--namespace ns Search for matches with namespace ns, default wildcard."
099: + linefeed
100: + " -i|--name id Search for matches with name id, default wildcard."
101: + linefeed
102: + " -v|--ver vs Search for matches with version vs, default wildcard."
103: + linefeed
104: + " -D|--def dv[,..] Search for matches of the complete FQDI (see manpage)."
105: + linefeed
106: + " -L|--deflist lodvs read definition FQDIs from file lodvs, one per line."
107: + linefeed
108: + linefeed
109: + "Group 2: Search for logical filenames"
110: + linefeed
111: + " -t|--type i|o|io Limit search to (i)n, (o)ut or (io) filenames."
112: + linefeed
113: + " -f|--lfn lfn Limit search to filename lfn, default wildcard."
114: + linefeed
115: + " -F|--filelist lof read the LFNs from file lof, one per line."
116: + linefeed
117: + linefeed
118: + "The following exit codes are produced:"
119: + linefeed
120: + " 0 :-) Success"
121: + linefeed
122: + " 1 :-| Runtime error detected, please read the message."
123: + linefeed
124: + " 2 :-? empty result detected, and escalation (-e, -E) requested."
125: + linefeed
126: + " 3 8-O Fatal error merits a program abortion. Please carefully check your"
127: + linefeed
128: + " configuration files and setup before filing a bug report."
129: + linefeed);
130: }
131:
132: /**
133: * Creates a set of options.
134: */
135: protected LongOpt[] generateValidOptions() {
136: LongOpt[] lo = new LongOpt[21];
137:
138: lo[0] = new LongOpt("dbase", LongOpt.REQUIRED_ARGUMENT, null,
139: 'd');
140: lo[1] = new LongOpt("version", LongOpt.NO_ARGUMENT, null, 'V');
141: lo[2] = new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'h');
142: lo[3] = new LongOpt("verbose", LongOpt.NO_ARGUMENT, null, 1);
143:
144: lo[4] = new LongOpt("list", LongOpt.REQUIRED_ARGUMENT, null,
145: 'l');
146: lo[5] = new LongOpt("error", LongOpt.NO_ARGUMENT, null, 'e');
147: lo[6] = new LongOpt("output", LongOpt.REQUIRED_ARGUMENT, null,
148: 'o');
149:
150: lo[7] = new LongOpt("type", LongOpt.REQUIRED_ARGUMENT, null,
151: 't');
152: lo[8] = new LongOpt("namespace", LongOpt.REQUIRED_ARGUMENT,
153: null, 'n');
154: lo[9] = new LongOpt("ns", LongOpt.REQUIRED_ARGUMENT, null, 'n');
155: lo[10] = new LongOpt("name", LongOpt.REQUIRED_ARGUMENT, null,
156: 'i');
157: lo[11] = new LongOpt("id", LongOpt.REQUIRED_ARGUMENT, null, 'i');
158: lo[12] = new LongOpt("ver", LongOpt.REQUIRED_ARGUMENT, null,
159: 'v');
160: lo[13] = new LongOpt("vs", LongOpt.REQUIRED_ARGUMENT, null, 'v');
161:
162: lo[14] = new LongOpt("file", LongOpt.REQUIRED_ARGUMENT, null,
163: 'f');
164: lo[15] = new LongOpt("lfn", LongOpt.REQUIRED_ARGUMENT, null,
165: 'f');
166:
167: lo[16] = new LongOpt("def", LongOpt.REQUIRED_ARGUMENT, null,
168: 'D');
169: lo[17] = new LongOpt("definition", LongOpt.REQUIRED_ARGUMENT,
170: null, 'D');
171: lo[18] = new LongOpt("deflist", LongOpt.REQUIRED_ARGUMENT,
172: null, 'L');
173: lo[19] = new LongOpt("filelist", LongOpt.REQUIRED_ARGUMENT,
174: null, 'F');
175: lo[20] = new LongOpt("empty", LongOpt.NO_ARGUMENT, null, 'E');
176:
177: return lo;
178: }
179:
180: /**
181: * search the database for specific TR's or DV's
182: */
183: public static void main(String[] args) {
184: String groupError = "different option groups cannot be combined";
185: boolean emptyFailure = false;
186: boolean emptyBundle = false;
187: boolean seenResults = false;
188: int result = 0;
189:
190: try {
191: SearchVDC me = new SearchVDC("searchvdc");
192:
193: // get the commandline options
194: Getopt opts = new Getopt(me.m_application, args,
195: "D:EL:F:Vd:ef:hi:l:n:o:t:v:", me
196: .generateValidOptions());
197: opts.setOpterr(false);
198:
199: int state = -1; // -1: undef, 0: dv(s), 1: lfn(s)
200: String dbase = null;
201: String ns = null;
202: String id = null;
203: String vs = null;
204: String arg;
205:
206: String outfn = null;
207: int classType = -1;
208: int linkage = -1;
209: int outputFormat = Search.FORMAT_FQDN;
210:
211: ArrayList definitions = new ArrayList();
212: ArrayList filenames = new ArrayList();
213: int option = 0;
214: while ((option = opts.getopt()) != -1) {
215: switch (option) {
216: case 1:
217: me.increaseVerbosity();
218: break;
219:
220: case 'V':
221: System.out
222: .println("$Id: SearchVDC.java 50 2007-05-19 00:48:32Z gmehta $");
223: System.out.println("VDS version "
224: + Version.instance().toString());
225: return;
226:
227: case 'D':
228: if (state != -1 && state != 0) {
229: me.showUsage();
230: throw new RuntimeException(groupError);
231: } else {
232: arg = opts.getOptarg();
233: if (arg != null) {
234: state = 0;
235: StringTokenizer st = new StringTokenizer(
236: arg, ",", false);
237: while (st.hasMoreTokens())
238: definitions.add(st.nextToken());
239: }
240: }
241: break;
242:
243: case 'E':
244: emptyBundle = true;
245: break;
246:
247: case 'F':
248: if (state != -1 && state != 1) {
249: me.showUsage();
250: throw new RuntimeException(groupError);
251: } else {
252: arg = opts.getOptarg();
253: if (arg != null) {
254: state = 1;
255: int nr = me.readFile(arg, filenames);
256: me.m_logger.log("app", 1, "read " + nr
257: + " LFNs from " + arg);
258: }
259: }
260: break;
261:
262: case 'L':
263: if (state != -1 && state != 0) {
264: me.showUsage();
265: throw new RuntimeException(groupError);
266: } else {
267: arg = opts.getOptarg();
268: if (arg != null) {
269: state = 0;
270: int nr = me.readFile(arg, definitions);
271: me.m_logger.log("app", 1, "read " + nr
272: + " DEF names from " + arg);
273: }
274: }
275: break;
276:
277: case 'd':
278: dbase = opts.getOptarg();
279: break;
280:
281: case 'e':
282: emptyFailure = true;
283: break;
284:
285: case 'f':
286: if (state != -1 && state != 1) {
287: me.showUsage();
288: throw new RuntimeException(groupError);
289: } else {
290: arg = opts.getOptarg();
291: if (arg != null) {
292: state = 1;
293: StringTokenizer st = new StringTokenizer(
294: arg, ",", false);
295: while (st.hasMoreTokens())
296: filenames.add(st.nextToken());
297: }
298: }
299: break;
300:
301: case 'i':
302: if (state != -1 && state != 0) {
303: me.showUsage();
304: throw new RuntimeException(groupError);
305: } else {
306: arg = opts.getOptarg();
307: if (arg != null) {
308: id = arg;
309: state = 0;
310: }
311: }
312: break;
313:
314: case 'n':
315: if (state != -1 && state != 0) {
316: me.showUsage();
317: throw new RuntimeException(groupError);
318: } else {
319: arg = opts.getOptarg();
320: if (arg != null) {
321: ns = arg;
322: state = 0;
323: }
324: }
325: break;
326:
327: case 'o':
328: arg = opts.getOptarg();
329: if (arg != null)
330: outfn = arg;
331: break;
332:
333: case 'v':
334: if (state != -1 && state != 0) {
335: me.showUsage();
336: throw new RuntimeException(groupError);
337: } else {
338: arg = opts.getOptarg();
339: if (arg != null) {
340: vs = arg;
341: state = 0;
342: }
343: }
344: break;
345:
346: case 'l':
347: arg = opts.getOptarg().toLowerCase();
348: if (arg != null) {
349: switch (arg.charAt(0)) {
350: case 'x':
351: outputFormat = Search.FORMAT_VDLX;
352: break;
353: case 't':
354: outputFormat = Search.FORMAT_VDLT;
355: break;
356: default:
357: outputFormat = Search.FORMAT_FQDN;
358: break;
359: }
360: }
361: break;
362:
363: case 't':
364: arg = opts.getOptarg().toLowerCase();
365: if (arg != null) {
366: switch (arg.charAt(0)) {
367: case 'a':
368: case 'b':
369: if (state != -1 && state != 0) {
370: me.showUsage();
371: throw new RuntimeException(groupError);
372: } else {
373: state = 0;
374: classType = -1; // both, all
375: }
376: break;
377: case 'd':
378: if (state != -1 && state != 0) {
379: me.showUsage();
380: throw new RuntimeException(groupError);
381: } else {
382: state = 0;
383: classType = Definition.DERIVATION;
384: }
385: break;
386: case 't':
387: if (state != -1 && state != 0) {
388: me.showUsage();
389: throw new RuntimeException(groupError);
390: } else {
391: state = 0;
392: classType = Definition.TRANSFORMATION;
393: }
394: break;
395: case 'i':
396: if (state != -1 && state != 1) {
397: me.showUsage();
398: throw new RuntimeException(groupError);
399: } else {
400: state = 1;
401: linkage = arg.equals("io") ? LFN.INOUT
402: : LFN.INPUT;
403: }
404: break;
405: case 'o':
406: if (state != -1 && state != 1) {
407: me.showUsage();
408: throw new RuntimeException(groupError);
409: } else {
410: state = 1;
411: linkage = arg.equals("oi") ? LFN.INOUT
412: : LFN.OUTPUT;
413: }
414: break;
415: default:
416: me.showUsage();
417: throw new RuntimeException(
418: "Invalid value \"" + arg
419: + "\" for option -t");
420: }
421: }
422: break;
423:
424: case 'h':
425: default:
426: me.showUsage();
427: return;
428: }
429: }
430:
431: // me.m_logger.log( "app", 3, filenames.size() + " LFNs and " +
432: // definitions.size() + " DEFs, state=" + state );
433:
434: // Connect the database.
435: String schemaName = ChimeraProperties.instance()
436: .getVDCSchemaName();
437:
438: Connect connect = new Connect();
439: DatabaseSchema dbschema = connect
440: .connectDatabase(schemaName);
441:
442: // Search the database.
443: me.m_logger.log("app", 2, "searching the database");
444: java.util.List resultList = new ArrayList();
445: Search search = new Search(dbschema);
446:
447: java.util.List bundle = null;
448: if (state == 1) {
449: // looking for LFNs
450: if (filenames.isEmpty()) {
451: // wildcard LFN search
452: me.m_logger.log("app", 3,
453: "wildcard search requested");
454: bundle = search.searchDefinition(null, linkage);
455: resultList.addAll(bundle);
456: } else {
457: for (Iterator i = filenames.iterator(); i.hasNext();) {
458: String lfn = (String) i.next();
459: bundle = search.searchDefinition(lfn, linkage);
460:
461: if (bundle.isEmpty() && emptyBundle) {
462: dbschema.close();
463: throw new FriendlyNudge(
464: "no definitions found for \"" + lfn
465: + "\"", 2);
466: } else {
467: // me.m_logger.log( "app", 3, "found " + bundle.size() +
468: // " matches for " + lfn );
469: resultList.addAll(bundle);
470: }
471: }
472: }
473: } else {
474: // looking for definitions
475: if (definitions.isEmpty()) {
476: // wildcard definition search
477: me.m_logger.log("app", 3,
478: "wildcard search requested");
479: if (dbschema instanceof Advanced)
480: bundle = search.searchDefinitionEx(ns, id, vs,
481: classType);
482: else
483: bundle = search.searchDefinition(ns, id, vs,
484: classType);
485: resultList.addAll(bundle);
486:
487: } else {
488: for (Iterator i = definitions.iterator(); i
489: .hasNext();) {
490: String def = (String) i.next();
491: // String[] d = Separator.split( def );
492: String[] d = Separator.splitFQDI(def);
493: if (dbschema instanceof Advanced)
494: bundle = search.searchDefinitionEx(
495: (d[0] == null ? ns : d[0]),
496: (d[1] == null ? id : d[1]),
497: (d[2] == null ? vs : d[2]),
498: classType);
499: else
500: bundle = search.searchDefinition(
501: (d[0] == null ? ns : d[0]),
502: (d[1] == null ? id : d[1]),
503: (d[2] == null ? vs : d[2]),
504: classType);
505:
506: if (bundle.isEmpty() && emptyBundle) {
507: dbschema.close();
508: throw new FriendlyNudge(
509: "no definitions found for \"" + def
510: + "\"", 2);
511: } else {
512: // me.m_logger.log( "app", 3, "found " + bundle.size() +
513: // " matches for " + def );
514: resultList.addAll(bundle);
515: }
516: }
517: }
518: }
519: me.m_logger.log("app", 1, "found " + resultList.size()
520: + " matches total");
521:
522: if (!resultList.isEmpty()) {
523: seenResults = true;
524: Writer writer;
525: if (outfn != null) {
526: // save to file
527: me.m_logger.log("app", 1, "Saving to the file "
528: + outfn);
529: writer = new BufferedWriter(new FileWriter(outfn));
530: } else {
531: writer = new PrintWriter(System.out);
532: }
533:
534: search.printDefinitionList(writer, resultList,
535: outputFormat);
536: writer.close();
537: } else {
538: me.m_logger.log("app", 1, "no results");
539: }
540:
541: // done
542: dbschema.close();
543: } catch (FriendlyNudge fn) {
544: System.err.println(fn.getMessage());
545: result = fn.getResult();
546: } catch (IOException ioe) {
547: System.err.println("ERROR: " + ioe.getMessage());
548: result = 1;
549: } catch (RuntimeException rte) {
550: System.err.println("ERROR: " + rte.getMessage());
551: result = 1;
552: } catch (Exception e) {
553: e.printStackTrace();
554: System.err.println("FATAL: " + e.getMessage());
555: result = 3;
556: }
557:
558: // fail on empty result set, if requested
559: if (emptyFailure & !seenResults)
560: result = 2;
561:
562: if (result != 0)
563: System.exit(result);
564: }
565: }
|