/* * 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.sql.SQLException; import java.util.Iterator; import java.util.List; import java.util.ArrayList; import java.util.Set; import java.util.TreeSet; import edu.isi.pegasus.common.util.Version; import edu.isi.pegasus.common.util.Currently; import org.griphyn.vdl.parser.*; import org.griphyn.vdl.dbdriver.*; import org.griphyn.vdl.dbschema.*; import org.griphyn.vdl.classes.Definitions; import org.griphyn.vdl.classes.Definition; import org.griphyn.vdl.util.Logging; import org.griphyn.vdl.util.ChimeraProperties; import org.griphyn.vdl.directive.*; import org.xml.sax.InputSource; import gnu.getopt.*; /** * This class uses the <code>VDLxParser</code> to parse VDLx specifications * and add them to the database backend. If a definition already exists * in the database, it is updated in overwrite mode, or rejected in * insert mode. * * @author Jens-S. Vöckler * @author Yong Zhao * @version $Revision$ * * @see org.griphyn.vdl.parser.VDLxParser */ public class UpdateVDC extends VDLHelper { /** * writer to output rejected definitions */ private Writer m_reject = null; /** * This initializies the class to handle inserts and updates, and * optionally store the rejects for later availability. * * @param appName is the true name of the application * @param reject is a writer to output rejected inserts. * @param level is the verbosity level for the "app" logging queue. */ public UpdateVDC( String appName, Writer reject, int level ) throws IOException { super(appName,level); m_reject = reject; } /** * Closes the rejects file, if still open. */ protected void finalize() throws Throwable { if ( m_reject != null ) m_reject.close(); super.finalize(); } /** * Prints the usage string. * * @param ow is the overwrite mode to distinguish between insert and update. */ static public void showUsage( boolean ow ) { String linefeed = System.getProperty( "line.separator", "\r\n" ); System.out.println( "$Id$" + linefeed + "VDS version " + Version.instance().toString() + linefeed ); System.out.println( "Usage: " + ( ow ? "update" : "insert" ) + "vdc [general] [-r fn] vdlx|vdlt [vdlt|vdlx [..]]" ); System.out.println( 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 + " -r|--rejects fn gathers the rejected definitions into file fn." + linefeed ); } public void showUsage() { showUsage( m_application != null && m_application.charAt(0) == 'i' ); } /** * Creates a set of options. */ protected static LongOpt[] generateValidOptions() { LongOpt[] lo = new LongOpt[6]; lo[0] = new LongOpt( "help", LongOpt.NO_ARGUMENT, null, 'h' ); lo[1] = new LongOpt( "dbase", LongOpt.REQUIRED_ARGUMENT, null, 'd' ); lo[2] = new LongOpt( "version", LongOpt.NO_ARGUMENT, null, 'V' ); lo[3] = new LongOpt( "verbose", LongOpt.NO_ARGUMENT, null, 1 ); lo[4] = new LongOpt( "rejects", LongOpt.REQUIRED_ARGUMENT, null, 'r' ); lo[5] = new LongOpt( "force", LongOpt.NO_ARGUMENT, null, 'f' ); return lo; } /** * Add or update definition's from VDLx documents into the database. */ public static void main( String[] args ) { int result = 0; try { Getopt opts = new Getopt( "(undef)", args, "Vhd:fr:", generateValidOptions() ); opts.setOpterr(false); Writer reject = null; String dbase = null; // unused option boolean overwrite = false; // --force String filename = null; // reject file int verbose = 0; int option = 0; while ( (option = opts.getopt()) != -1 ) { switch ( option ) { case 1: ++verbose; break; case 'V': System.out.println( "$Id$" ); System.out.println( "VDS version " + Version.instance().toString() ); return; case 'd': dbase = opts.getOptarg(); break; case 'f': // if force is not true, the program acts in insert mode, // i.e. definition's already exist will not be overwritten. overwrite = true; break; case 'r': filename = opts.getOptarg(); break; case 'h': default: showUsage( overwrite ); return; } } if ( filename != null && filename.length() > 0 ) reject = new BufferedWriter( new FileWriter(filename) ); UpdateVDC me = new UpdateVDC( overwrite ? "updatevdc" : "insertvdc", reject, verbose ); if ( opts.getOptind() >= args.length ) { // nothing to process -- what is this? showUsage(overwrite); throw new RuntimeException("You must specify at least one input file" ); } // Connect the database. String schemaName = ChimeraProperties.instance().getVDCSchemaName(); Connect connect = new Connect(); DatabaseSchema dbschema = connect.connectDatabase(schemaName); Define define = new Define(dbschema); // if ( derivations.isEmpty() ) define.setDerivationMemory( true ); // Add definitions to the database backend while parsing Set badfile = me.addFilesToVDC( args, opts.getOptind(), define, reject, overwrite ); int errcount = badfile.size(); if ( errcount > 0 ) { // previous section saw one or more errors, better give up. for ( Iterator i=badfile.iterator(); i.hasNext() ; ) { System.err.println( "errors in " + ((String)i.next()) ); } throw new RuntimeException( "Detected " + errcount + " error" + ( errcount==1 ? " " : "s " ) + "while parsing VDL" ); } if (reject != null) reject.close(); int count = define.getNumberSaved(); int rejected = define.getNumberRejected(); me.m_logger.log( "app", 1, "modified " + count + " definition" + (count==1?"":"s") ); me.m_logger.log( "app", 1, "rejected " + rejected + " definition" + (rejected==1?"":"s") ); define.close(); } catch ( RuntimeException rte ) { System.err.println( "ERROR: " + rte.getMessage() ); result = 1; } catch( Exception e ) { System.err.println( "FATAL: " + e.getMessage() ); e.printStackTrace(); result = 2; } // Java will return with 0 unless exit is used. Unfortunately, using // System.exit sometimes has some unwanted side-effects on d'tors, // thus avoid using it unless strictly necessary. if ( result != 0 ) System.exit(result); } }