/**
* Copyright 2007-2008 University Of Southern California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.isi.pegasus.planner.client;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import edu.isi.pegasus.common.logging.LogManager;
import edu.isi.pegasus.common.logging.LogManagerFactory;
import edu.isi.pegasus.common.util.FactoryException;
import edu.isi.pegasus.planner.catalog.SiteCatalog;
import edu.isi.pegasus.planner.catalog.site.SiteFactory;
import edu.isi.pegasus.planner.catalog.site.classes.SiteDataVisitor;
import edu.isi.pegasus.planner.catalog.site.classes.SiteStore;
import edu.isi.pegasus.planner.catalog.site.classes.XML3PrintVisitor;
import edu.isi.pegasus.planner.catalog.site.classes.XML4PrintVisitor;
import gnu.getopt.Getopt;
import gnu.getopt.LongOpt;
/**
* A client to convert site catalog between different formats.
*
* @author Karan Vahi
* @author Gaurang Mehta gmehta@isi.edu
*
* @version $Revision$
*/
public class SCClient
extends Executable {
/**
* The input files.
*/
private List<String> mInputFiles;
/**
* The output file that is written out.
*/
private String mOutputFile;
/**
* The output format for the site catalog.
*/
private String mOutputFormat;
/**
* The input format for the site catalog.
*/
private String mInputFormat;
/**
* Denotes the logging level that is to be used for logging the messages.
*/
private int mLoggingLevel;
/**
* The default constructor.
*/
public SCClient() {
super();
}
public void initialize(String[] opts){
super.initialize(opts);
//the output format is whatever user specified in the properties
mOutputFormat = mProps.getPoolMode();
mInputFormat = "XML";
mLoggingLevel = LogManager.WARNING_MESSAGE_LEVEL;
//mText = false;
mInputFiles = null;
mOutputFile = null;
}
/**
* Sets up the logging options for this class. Looking at the properties
* file, sets up the appropriate writers for output and stderr.
*/
protected void setupLogging(){
//setup the logger for the default streams.
mLogger = LogManagerFactory.loadSingletonInstance( mProps );
mLogger.logEventStart( "event.pegasus.pegasus-sc-converter", "pegasus.version", mVersion );
}
/**
* Loads all the properties
* that would be needed
* by the Toolkit classes
*/
public void loadProperties() {
}
public LongOpt[] generateValidOptions() {
LongOpt[] longopts = new LongOpt[ 9 ];
longopts[ 0 ] = new LongOpt( "files", LongOpt.REQUIRED_ARGUMENT, null, 'f' );
longopts[ 1 ] = new LongOpt( "input", LongOpt.REQUIRED_ARGUMENT, null, 'i' );
longopts[ 2 ] = new LongOpt( "output", LongOpt.REQUIRED_ARGUMENT, null, 'o' );
longopts[ 3 ] = new LongOpt( "oformat", LongOpt.REQUIRED_ARGUMENT, null, 'O' );
longopts[ 4 ] = new LongOpt( "help", LongOpt.NO_ARGUMENT, null, 'h' );
longopts[ 5 ] = new LongOpt( "version", LongOpt.NO_ARGUMENT, null, 'V' );
longopts[ 6 ] = new LongOpt( "verbose", LongOpt.NO_ARGUMENT, null, 'v' );
longopts[ 7 ] = new LongOpt( "quiet", LongOpt.NO_ARGUMENT, null, 'q' );
longopts[ 8 ] = new LongOpt( "conf", LongOpt.REQUIRED_ARGUMENT, null, 'c' );
return longopts;
}
/**
* Call the correct commands depending on options.
* @param opts Command options
*/
public void executeCommand() throws IOException {
LongOpt[] longOptions = generateValidOptions();
Getopt g = new Getopt( "SCClient", getCommandLineOptions(), "lhvqVi:o:O:f:c:",
longOptions, false );
int option = 0;
while ( ( option = g.getopt() ) != -1 ) {
switch ( option ) {
case 'f': //files
StringTokenizer st = new StringTokenizer( g.getOptarg(), "," );
mInputFiles = new ArrayList<String>( st.countTokens() );
while ( st.hasMoreTokens() ) {
mInputFiles.add( st.nextToken() );
}
break;
case 'i': //input
StringTokenizer str = new StringTokenizer( g.getOptarg(), "," );
mInputFiles = new ArrayList<String>( str.countTokens() );
while ( str.hasMoreTokens() ) {
mInputFiles.add( str.nextToken() );
}
break;
case 'o': //output
mOutputFile = g.getOptarg();
break;
case 'O': //oformat
mOutputFormat = g.getOptarg();
break;
case 'h': //help
printLongVersion();
System.exit( 0 );
break;
case 'V': //version
System.out.println(getGVDSVersion());
System.exit( 0 );
break;
/*
case 'l': // Precedence for local or remote
mLocalPrec = true;
break;
*/
case 'v': //Verbose mode
incrementLogging();
break;
case 'q': //Quiet mode
decrementLogging();
break;
case 'c': // conf
//do nothing
break;
default:
mLogger.log( "Unrecognized option or Invalid argument to option : " + (char)g.getOptopt(),
LogManager.FATAL_MESSAGE_LEVEL );
printShortVersion();
System.exit( 1 );
}
}
if(getLoggingLevel() >= 0){
//set the logging level only if -v was specified
//else bank upon the the default logging level
mLogger.setLevel(getLoggingLevel());
}
else{
//set log level to FATAL only
mLogger.setLevel( LogManager.FATAL_MESSAGE_LEVEL );
}
if(mInputFiles==null || mInputFiles.isEmpty()|| mOutputFile==null || mOutputFile.isEmpty()){
mLogger.log("Please provide the input and the output file", LogManager.ERROR_MESSAGE_LEVEL);
this.printShortVersion();
System.exit(1);
}
String result = this.parseInputFiles( mInputFiles, mInputFormat, mOutputFormat );
//write out the result to the output file
this.toFile( mOutputFile, result );
}
/**
* Increments the logging level by 1.
*/
public void incrementLogging(){
mLoggingLevel++;
}
/**
* Decrements the logging level by 1.
*/
public void decrementLogging(){
mLoggingLevel--;
}
/**
* Returns the logging level.
*
* @return the logging level.
*/
public int getLoggingLevel(){
return mLoggingLevel;
}
/**
* Parses the input files in the input format and returns a String in the
* output format.
*
* @param inputFiles list of input files that need to be converted
* @param inputFormat input format of the input files
* @param outputFormat output format of the output file
*
* @return String in output format
*
* @throws java.io.IOException
*/
public String parseInputFiles( List<String> inputFiles, String inputFormat, String outputFormat ) throws IOException{
//sanity check
if ( inputFiles == null || inputFiles.isEmpty() ){
throw new IOException( "Input files not specified. Specify the --input option" );
}
//mLogger.log( "Input format detected is " + inputFormat , LogManager.DEBUG_MESSAGE_LEVEL );
mLogger.log( "Output format detected is " + outputFormat , LogManager.DEBUG_MESSAGE_LEVEL );
SiteStore result = new SiteStore();
for( String inputFile : inputFiles ){
//switch on input format.
if( inputFormat.equals( "XML" ) ){
SiteCatalog catalog = null;
/* load the catalog using the factory */
try{
mProps.setProperty( "pegasus.catalog.site.file", inputFile );
mProps.setProperty( SiteCatalog.c_prefix, mInputFormat );
catalog = SiteFactory.loadInstance( mProps );
/* load all sites in site catalog */
List<String> s = new ArrayList<String>(1);
s.add( "*" );
mLogger.log( "Loaded " + catalog.load( s ) + " number of sites ", LogManager.DEBUG_MESSAGE_LEVEL );
/* query for the sites, and print them out */
mLogger.log( "Sites loaded are " + catalog.list( ) , LogManager.DEBUG_MESSAGE_LEVEL );
for( String site : catalog.list() ){
result.addEntry( catalog.lookup( site ) );
}
SiteDataVisitor xml = null;
StringWriter writer = new StringWriter();
if ( outputFormat.equals ( "XML3" ) ) {
xml = new XML3PrintVisitor ( );
} else {
xml = new XML4PrintVisitor ( );
}
xml.initialize ( writer );
result.accept ( xml );
return writer.toString();
}
finally{
/* close the connection */
try{
catalog.close();
}catch( Exception e ){}
}
} else {
throw new IOException( "Invalid input format. Only input format supported in XML. The client will auto-detect if the input is in version 3 or 4." );
}//end of input format xml
}//end of iteration through input files.
return null;
}
/**
* Returns the short help.
*
*
*/
public void printShortVersion() {
String text =
"\n $Id$ " +
"\n " + getGVDSVersion() +
"\n Usage: pegasus-sc-converter [-Dprop [..]] -i <list of input files> -o <output file to write> " +
"\n [-O <output format>] [-c <path to property file>] [-v] [-q] [-V] [-h]\n" ;
System.out.print(text);
}
public void printLongVersion() {
String text =
"\n $Id$ " +
"\n " + getGVDSVersion() +
"\n pegasus-sc-converter - Parses the site catalogs in old format ( XML3 ) and generates site catalog in new format ( XML4 )" +
"\n " +
"\n Usage: pegasus-sc-converter [-Dprop [..]] --input <list of input files> --output <output file to write> " +
"\n [--iformat input format] [--oformat <output format>] [--conf <path to property file>] [--verbose] [--quiet] [--Version] [--help]" +
"\n" +
"\n" +
"\n Mandatory Options " +
"\n" +
"\n -i |--input comma separated list of input files to convert " +
"\n -o |--output the output file to which the output needs to be written to." +
"\n" +
"\n" +
"\n Other Options " +
"\n" +
//"\n -I |--iformat the input format for the files . Can be [XML , Text] " +
"\n -O |--oformat the output format of the file. Usually [XML4] " +
"\n -c |--conf path to property file" +
"\n -v |--verbose increases the verbosity of messages about what is going on" +
"\n -q |--quiet decreases the verbosity of messages about what is going on" +
"\n -V |--version displays the version of the Pegasus Workflow Planner" +
"\n -h |--help generates this help." +
"\n" +
"\n" +
"\n Deprecated Options " +
"\n" +
//"\n --text | -t To convert an xml site catalog file to the multiline site catalog file." +
//"\n Use --iformat instead " +
//"\n" +
"\n --files | -f The local text site catalog file|files to be converted to " +
"\n xml or text. This file needs to be in multiline textual " +
"\n format not the single line or in xml format if converting " +
"\n to text format. See $PEGASUS_HOME/etc/sample.sites.txt. " +
"\n" +
"\n" +
"\n Example Usage " +
"\n" +
"\n pegasus-sc-converter -i sites.xml -o sites.xml.new -O XML3 -vvvvv\n";
System.out.print(text);
}
/**
* Writes out to a file, a string.
*
* @param filename the fully qualified path name to the file.
* @param output the text that needs to be written to the file.
*
* @throws IOException
*/
public void toFile( String filename, String output ) throws IOException {
if( filename == null ){
throw new IOException( "Please specify a file to write the output to using --output option ");
}
File outfile = new File( filename );
PrintWriter pw = new PrintWriter( new BufferedWriter( new FileWriter(
outfile ) ) );
pw.println( output );
pw.close();
mLogger.log( "Written out the converted file to " + filename, LogManager.CONSOLE_MESSAGE_LEVEL );
}
public static void main( String[] args ) throws Exception {
SCClient me = new SCClient();
int result = 0;
double starttime = new Date().getTime();
double execTime = -1;
try{
me.initialize(args);
me.executeCommand( );
}
catch ( IOException ioe ){
me.log( convertException(ioe,me.getLoggingLevel()), LogManager.FATAL_MESSAGE_LEVEL);
result = 1;
}
catch ( FactoryException fe){
me.log( convertException(fe, me.getLoggingLevel()) , LogManager.FATAL_MESSAGE_LEVEL);
result = 2;
}
catch ( Exception e ) {
//unaccounted for exceptions
me.log(convertException(e,me.getLoggingLevel()),
LogManager.FATAL_MESSAGE_LEVEL );
result = 3;
} finally {
double endtime = new Date().getTime();
execTime = (endtime - starttime)/1000;
}
// warn about non zero exit code
if ( result != 0 ) {
me.log("Non-zero exit-code " + result,
LogManager.WARNING_MESSAGE_LEVEL );
}
else{
//log the time taken to execute
me.log("Time taken to execute is " + execTime + " seconds",
LogManager.INFO_MESSAGE_LEVEL);
}
me.log( "Exiting with exitcode " + result, LogManager.DEBUG_MESSAGE_LEVEL );
me.mLogger.logEventCompletion();
System.exit(result);
}
}