/*
* This file or a portion of this file is licensed under the terms of
* the Globus Toolkit Public License, found in file GTPL, or at
* http://www.globus.org/toolkit/download/license.html. This notice must
* appear in redistributions of this file, with or without modification.
*
* Redistributions of this Software, with or without modification, must
* reproduce the GTPL in: (1) the Software, or (2) the Documentation or
* some other similar material which is provided with the Software (if
* any).
*
* Copyright 1999-2004 University of Chicago and The University of
* Southern California. All rights reserved.
*/
package org.griphyn.vdl.toolkit;
import java.io.*;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.sql.SQLException;
import edu.isi.pegasus.common.util.Version;
import edu.isi.pegasus.common.util.Currently;
import edu.isi.pegasus.common.util.Separator;
import org.griphyn.vdl.parser.VDLxParser;
import org.griphyn.vdl.classes.*;
import org.griphyn.vdl.dbschema.*;
import org.griphyn.vdl.util.Logging;
import org.griphyn.vdl.util.ChimeraProperties;
import org.griphyn.vdl.directive.*;
import gnu.getopt.*;
/**
* This class searches definitions that match the namespace, name,
* version triple, then prints the search results in one of the formats:
* vdlx, vdlt, or name. Alternatively, it permits to search from a list
* of inputs, either DVs or LFNs.
*
* @author Jens-S. Vöckler
* @author Yong Zhao
* @version $Revision$
*
* @see org.griphyn.vdl.parser.VDLxParser
*/
public class SearchVDC extends Toolkit
{
/**
* Constructor
*/
public SearchVDC(String appName)
{
super(appName);
}
/**
* Prints the usage string onto stdout.
*/
public void showUsage()
{
String linefeed = System.getProperty( "line.separator", "\r\n" );
System.out.println(
"$Id$" + linefeed +
"VDS version " + Version.instance().toString() + linefeed );
System.out.println(
"Usage: " + this.m_application + " [general] [-t tr|dv] [[-n ns] [-i id] [-v vs] | -D dv] [-L lod]" + linefeed +
" or: " + this.m_application + " [general] [-t i|o|io] [-f lfn | -F lof]" );
System.out.println( linefeed +
"General options:" + linefeed +
" -V|--version print version information and exit." + linefeed +
" -d|--dbase dbx associates the dbname with the database, unused." + linefeed +
" --verbose increases the verbosity level." + linefeed +
" -l|--list x|t|n print x:VDLx, t:VDLt or just a table of n:names." + linefeed +
" -e|--error if present, return failure for a combined empty result set." + linefeed +
" -E|--empty if present and bundling, raise an error for any empty match." + linefeed +
" -o|--output fn put the output into the file fn, default is stdout." + linefeed +
linefeed +
"Group 1: Search for definitions" + linefeed +
" -t|--type tr|dv|all Search only for TR or DV, default is all (both)." + linefeed +
" -n|--namespace ns Search for matches with namespace ns, default wildcard." + linefeed +
" -i|--name id Search for matches with name id, default wildcard." + linefeed +
" -v|--ver vs Search for matches with version vs, default wildcard." + linefeed +
" -D|--def dv[,..] Search for matches of the complete FQDI (see manpage)." + linefeed +
" -L|--deflist lodvs read definition FQDIs from file lodvs, one per line." + linefeed +
linefeed +
"Group 2: Search for logical filenames" + linefeed +
" -t|--type i|o|io Limit search to (i)n, (o)ut or (io) filenames." + linefeed +
" -f|--lfn lfn Limit search to filename lfn, default wildcard." + linefeed +
" -F|--filelist lof read the LFNs from file lof, one per line." + linefeed +
linefeed +
"The following exit codes are produced:" + linefeed +
" 0 :-) Success" + linefeed +
" 1 :-| Runtime error detected, please read the message." + linefeed +
" 2 :-? empty result detected, and escalation (-e, -E) requested." + linefeed +
" 3 8-O Fatal error merits a program abortion. Please carefully check your" + linefeed +
" configuration files and setup before filing a bug report." + linefeed
);
}
/**
* Creates a set of options.
*/
protected LongOpt[] generateValidOptions()
{
LongOpt[] lo = new LongOpt[21];
lo[0] = new LongOpt( "dbase", LongOpt.REQUIRED_ARGUMENT, null, 'd' );
lo[1] = new LongOpt( "version", LongOpt.NO_ARGUMENT, null, 'V' );
lo[2] = new LongOpt( "help", LongOpt.NO_ARGUMENT, null, 'h' );
lo[3] = new LongOpt( "verbose", LongOpt.NO_ARGUMENT, null, 1 );
lo[4] = new LongOpt( "list", LongOpt.REQUIRED_ARGUMENT, null, 'l' );
lo[5] = new LongOpt( "error", LongOpt.NO_ARGUMENT, null, 'e' );
lo[6] = new LongOpt( "output", LongOpt.REQUIRED_ARGUMENT, null, 'o' );
lo[7] = new LongOpt( "type", LongOpt.REQUIRED_ARGUMENT, null, 't' );
lo[8] = new LongOpt( "namespace", LongOpt.REQUIRED_ARGUMENT, null, 'n' );
lo[9] = new LongOpt( "ns", LongOpt.REQUIRED_ARGUMENT, null, 'n' );
lo[10] = new LongOpt( "name", LongOpt.REQUIRED_ARGUMENT, null, 'i' );
lo[11] = new LongOpt( "id", LongOpt.REQUIRED_ARGUMENT, null, 'i' );
lo[12] = new LongOpt( "ver", LongOpt.REQUIRED_ARGUMENT, null, 'v' );
lo[13] = new LongOpt( "vs", LongOpt.REQUIRED_ARGUMENT, null, 'v' );
lo[14] = new LongOpt( "file", LongOpt.REQUIRED_ARGUMENT, null, 'f' );
lo[15] = new LongOpt( "lfn", LongOpt.REQUIRED_ARGUMENT, null, 'f' );
lo[16] = new LongOpt( "def", LongOpt.REQUIRED_ARGUMENT, null, 'D' );
lo[17] = new LongOpt( "definition", LongOpt.REQUIRED_ARGUMENT, null, 'D' );
lo[18] = new LongOpt( "deflist", LongOpt.REQUIRED_ARGUMENT, null, 'L' );
lo[19] = new LongOpt( "filelist", LongOpt.REQUIRED_ARGUMENT, null, 'F' );
lo[20] = new LongOpt( "empty", LongOpt.NO_ARGUMENT, null, 'E' );
return lo;
}
/**
* search the database for specific TR's or DV's
*/
public static void main(String[] args)
{
String groupError = "different option groups cannot be combined";
boolean emptyFailure = false;
boolean emptyBundle = false;
boolean seenResults = false;
int result = 0;
try {
SearchVDC me = new SearchVDC("searchvdc");
// get the commandline options
Getopt opts = new Getopt( me.m_application, args,
"D:EL:F:Vd:ef:hi:l:n:o:t:v:",
me.generateValidOptions() );
opts.setOpterr(false);
int state = -1; // -1: undef, 0: dv(s), 1: lfn(s)
String dbase = null;
String ns = null;
String id = null;
String vs = null;
String arg;
String outfn = null;
int classType = -1;
int linkage = -1;
int outputFormat = Search.FORMAT_FQDN;
ArrayList definitions = new ArrayList();
ArrayList filenames = new ArrayList();
int option = 0;
while ( (option = opts.getopt()) != -1 ) {
switch ( option ) {
case 1:
me.increaseVerbosity();
break;
case 'V':
System.out.println( "$Id$" );
System.out.println( "VDS version " + Version.instance().toString() );
return;
case 'D':
if ( state != -1 && state != 0 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
arg = opts.getOptarg();
if ( arg != null ) {
state = 0;
StringTokenizer st = new StringTokenizer( arg, ",", false );
while ( st.hasMoreTokens() ) definitions.add( st.nextToken() );
}
}
break;
case 'E':
emptyBundle = true;
break;
case 'F':
if ( state != -1 && state != 1 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
arg = opts.getOptarg();
if ( arg != null ) {
state = 1;
int nr = me.readFile( arg, filenames );
me.m_logger.log( "app", 1, "read " + nr + " LFNs from " + arg );
}
}
break;
case 'L':
if ( state != -1 && state != 0 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
arg = opts.getOptarg();
if ( arg != null ) {
state = 0;
int nr = me.readFile( arg, definitions );
me.m_logger.log( "app", 1, "read " + nr + " DEF names from " + arg );
}
}
break;
case 'd':
dbase = opts.getOptarg();
break;
case 'e':
emptyFailure = true;
break;
case 'f':
if ( state != -1 && state != 1 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
arg = opts.getOptarg();
if ( arg != null ) {
state = 1;
StringTokenizer st = new StringTokenizer( arg, ",", false );
while ( st.hasMoreTokens() ) filenames.add( st.nextToken() );
}
}
break;
case 'i':
if ( state != -1 && state != 0 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
arg = opts.getOptarg();
if ( arg != null ) {
id = arg;
state = 0;
}
}
break;
case 'n':
if ( state != -1 && state != 0 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
arg = opts.getOptarg();
if ( arg != null ) {
ns = arg;
state = 0;
}
}
break;
case 'o':
arg = opts.getOptarg();
if ( arg != null ) outfn = arg;
break;
case 'v':
if ( state != -1 && state != 0 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
arg = opts.getOptarg();
if ( arg != null ) {
vs = arg;
state = 0;
}
}
break;
case 'l':
arg = opts.getOptarg().toLowerCase();
if ( arg != null ) {
switch ( arg.charAt(0) ) {
case 'x':
outputFormat = Search.FORMAT_VDLX;
break;
case 't':
outputFormat = Search.FORMAT_VDLT;
break;
default:
outputFormat = Search.FORMAT_FQDN;
break;
}
}
break;
case 't':
arg = opts.getOptarg().toLowerCase();
if ( arg != null ) {
switch ( arg.charAt(0) ) {
case 'a':
case 'b':
if ( state != -1 && state != 0 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
state = 0;
classType = -1; // both, all
}
break;
case 'd':
if ( state != -1 && state != 0 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
state = 0;
classType = Definition.DERIVATION;
}
break;
case 't':
if ( state != -1 && state != 0 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
state = 0;
classType = Definition.TRANSFORMATION;
}
break;
case 'i':
if ( state != -1 && state != 1 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
state = 1;
linkage = arg.equals("io") ? LFN.INOUT : LFN.INPUT;
}
break;
case 'o':
if ( state != -1 && state != 1 ) {
me.showUsage();
throw new RuntimeException( groupError );
} else {
state = 1;
linkage = arg.equals("oi") ? LFN.INOUT : LFN.OUTPUT;
}
break;
default:
me.showUsage();
throw new RuntimeException( "Invalid value \"" + arg + "\" for option -t" );
}
}
break;
case 'h':
default:
me.showUsage();
return;
}
}
// me.m_logger.log( "app", 3, filenames.size() + " LFNs and " +
// definitions.size() + " DEFs, state=" + state );
// Connect the database.
String schemaName = ChimeraProperties.instance().getVDCSchemaName();
Connect connect = new Connect();
DatabaseSchema dbschema = connect.connectDatabase(schemaName);
// Search the database.
me.m_logger.log( "app", 2, "searching the database" );
java.util.List resultList = new ArrayList();
Search search = new Search(dbschema);
java.util.List bundle = null;
if ( state == 1 ) {
// looking for LFNs
if ( filenames.isEmpty() ) {
// wildcard LFN search
me.m_logger.log( "app", 3, "wildcard search requested" );
bundle = search.searchDefinition( null, linkage );
resultList.addAll( bundle );
} else {
for ( Iterator i=filenames.iterator(); i.hasNext(); ) {
String lfn = (String) i.next();
bundle = search.searchDefinition( lfn, linkage );
if ( bundle.isEmpty() && emptyBundle ) {
dbschema.close();
throw new FriendlyNudge( "no definitions found for \"" + lfn + "\"", 2 );
} else {
// me.m_logger.log( "app", 3, "found " + bundle.size() +
// " matches for " + lfn );
resultList.addAll( bundle );
}
}
}
} else {
// looking for definitions
if ( definitions.isEmpty() ) {
// wildcard definition search
me.m_logger.log( "app", 3, "wildcard search requested" );
if ( dbschema instanceof Advanced )
bundle = search.searchDefinitionEx( ns, id, vs, classType );
else
bundle = search.searchDefinition( ns, id, vs, classType );
resultList.addAll( bundle );
} else {
for ( Iterator i=definitions.iterator(); i.hasNext(); ) {
String def = (String) i.next();
// String[] d = Separator.split( def );
String[] d = Separator.splitFQDI( def );
if ( dbschema instanceof Advanced )
bundle = search.searchDefinitionEx( (d[0]==null ? ns : d[0]),
(d[1]==null ? id : d[1]),
(d[2]==null ? vs : d[2]),
classType );
else
bundle = search.searchDefinition( (d[0]==null ? ns : d[0]),
(d[1]==null ? id : d[1]),
(d[2]==null ? vs : d[2]),
classType );
if ( bundle.isEmpty() && emptyBundle ) {
dbschema.close();
throw new FriendlyNudge( "no definitions found for \"" + def + "\"", 2 );
} else {
// me.m_logger.log( "app", 3, "found " + bundle.size() +
// " matches for " + def );
resultList.addAll( bundle );
}
}
}
}
me.m_logger.log( "app", 1, "found " + resultList.size() + " matches total" );
if ( ! resultList.isEmpty() ) {
seenResults = true;
Writer writer;
if ( outfn != null ) {
// save to file
me.m_logger.log("app", 1, "Saving to the file " + outfn );
writer = new BufferedWriter(new FileWriter(outfn));
} else {
writer = new PrintWriter(System.out);
}
search.printDefinitionList( writer, resultList, outputFormat );
writer.close();
} else {
me.m_logger.log( "app", 1, "no results" );
}
// done
dbschema.close();
} catch ( FriendlyNudge fn ) {
System.err.println( fn.getMessage() );
result = fn.getResult();
} catch ( IOException ioe ) {
System.err.println( "ERROR: " + ioe.getMessage() );
result = 1;
} catch ( RuntimeException rte ) {
System.err.println( "ERROR: " + rte.getMessage() );
result = 1;
} catch ( Exception e ) {
e.printStackTrace();
System.err.println( "FATAL: " + e.getMessage() );
result = 3;
}
// fail on empty result set, if requested
if ( emptyFailure & ! seenResults ) result = 2;
if ( result != 0 ) System.exit(result);
}
}