/*
* Name: Jostraca
* Authors: Richard Rodger
*
* Copyright (c) 2000-2006 Richard Rodger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
// package
package org.jostraca;
// import
import org.jostraca.util.CommandLineUserMessageHandler;
import org.jostraca.util.FileUtil;
import org.jostraca.util.ErrorUtil;
import org.jostraca.util.PropertySet;
import org.jostraca.util.Standard;
import org.jostraca.util.StandardException;
import org.jostraca.util.UserMessageHandler;
import org.jostraca.util.TextUtil;
import org.jostraca.util.ArgUtil;
import org.jostraca.comp.gnu.getopt.Getopt;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
/** Command line user interface to the Jostraca system.
*/
public class Jostraca {
// public static
public static final String CN = Jostraca.class.getName();
// Command Line Options
// ...
// REVIEW: -S for do not save code writer
public static final char ARG_CONFIG = 'f'; // primary configuration file
public static final char ARG_ADD_CONFIG = 'F'; // additional configuration files
public static final char ARG_WRITER_FORMAT = 'W'; // writer format file
public static final char ARG_TEMPLATE_LIST = 't'; // text file listing templates one per line
public static final char ARG_OUTPUT_FOLDER = 'o'; // output folder for generated files
public static final char ARG_WORK_FOLDER = 'w'; // work folder for code writer programs
public static final char ARG_ARGUMENT = 'a'; // argument for code writer
public static final char ARG_DUMP = 'd'; // dump internal state
public static final char ARG_DEFINE = 'D'; // define a setting on the command line
public static final char ARG_BACKUP_FOLDER = 'b'; // backup folder for previously generated files
public static final char ARG_ALL_TEMPLATES = 'l'; // everything on the command line is a template
public static final char ARG_NO_BACKUP = 'B'; // do not make backups of previously generated files
public static final char ARG_LOW_VERBOSE = 'V'; // display lots of debugging info
public static final char ARG_HIGH_VERBOSE = 'v'; // display minimal info
public static final char ARG_COMPILE = 'c'; // force template compilation
public static final char ARG_NO_COMPILE = 'C'; // prevent template compilation
public static final char ARG_GENERATE = 'g'; // force generation
public static final char ARG_NO_GENERATE = 'G'; // prevent generation
public static final char ARG_TEMPLATE_DOC = 'h'; // display template documentation, if any
public static final char ARG_NON_STANDARD = 'X'; // specify a non standard option
public static final char ARG_META_FOLDER = 'm'; // specify meta folder
public static final char ARG_NO_META = 'M'; // specify meta folder
public static final String SPECIAL_ARG_CHECK = "check"; // check installation
public static final String SPECIAL_ARG_VERSION = "version"; // display version info
public static final String SPECIAL_ARG_HELP = "help"; // display help
// non standard options
public static final String NSA_old = "old"; // use old template processing
public static final String NSA_noexit = "noexit"; // do not exit JVM after running
public static final String NSA_track = "track:"; // enable and set tracking file with syntax track:filepath
public static final String DEFAULT_ConfigPath = "conf/system.conf"; // relative to jostraca folder
// private static
private static final String JOSTRACA_TEMPLATE_SUFFIX = ".jtm";
private static final String CMD_NAME = "Jostraca";
// options spec string - colon => has args
private static final String CMD_SPEC_Options
= ARG_CONFIG + Standard.COLON
+ ARG_ADD_CONFIG + Standard.COLON
+ ARG_WRITER_FORMAT + Standard.COLON
+ ARG_TEMPLATE_LIST + Standard.COLON
+ ARG_OUTPUT_FOLDER + Standard.COLON
+ ARG_WORK_FOLDER + Standard.COLON
+ ARG_ARGUMENT + Standard.COLON
+ ARG_DUMP + Standard.COLON
+ ARG_DEFINE + Standard.COLON
+ ARG_BACKUP_FOLDER + Standard.COLON
+ ARG_META_FOLDER + Standard.COLON
+ ARG_ALL_TEMPLATES
+ ARG_NO_BACKUP
+ ARG_LOW_VERBOSE
+ ARG_HIGH_VERBOSE
+ ARG_NO_COMPILE
+ ARG_COMPILE
+ ARG_NO_GENERATE
+ ARG_GENERATE
+ ARG_NO_META
+ ARG_TEMPLATE_DOC
+ ARG_NON_STANDARD + Standard.COLON
;
private static final boolean DEFAULT_CheckInstallation = false;
// relays messages to user
private static CommandLineUserMessageHandler sUserMessageHandler
= new CommandLineUserMessageHandler();
private static boolean sExitProgram = true; // by default, terminate the JVM on completion
// private instance
//private String iConfigPath = DEFAULT_ConfigPath; // path to system config file
//private PropertySet iConfig = new PropertySet(); // PropertySet representing config file data
//private PropertySet iCmdLine = new PropertySet(); // PropertySet representing cmd line options
//private Vector iTemplatePaths = new Vector(); // list of template paths
//private Vector iAdditionalConfigPaths = new Vector(); // additional config file paths
private boolean iCheckInstallation = DEFAULT_CheckInstallation; // check installation valid flag
// public methods
/** Set path to configuration file.
* @param pConfigPath file path
*/
/*
public void setConfigPath( String pConfigPath ) {
if( ErrorUtil.not_null( pConfigPath, "pConfigPath" ) ) {
iConfigPath = pConfigPath;
}
}
*/
/** Get path to config file. */
/*
public String getConfigPath() {
return iConfigPath;
}
*/
/** Add an additional config path.
* These are applied in order of presentation on command line to the
* system config file before other config settings are applied.
* @param pAdditionalConfigPath additional configuration file path
*/
/*
public void addAdditionalConfigPath( String pAdditionalConfigPath ) {
if( ErrorUtil.not_null( pAdditionalConfigPath, "pAdditionalConfigPath" ) ) {
iAdditionalConfigPaths.addElement( pAdditionalConfigPath );
}
}
*/
/** Set system config PropertySet.
* @param pConfig PropertySet of config data
*/
/*
public void setSystemConfig( PropertySet pConfig ) {
if( ErrorUtil.not_null( pConfig, "pConfig" ) ) {
iConfig = pConfig;
}
}
*/
/** Get system config PropertySet. */
/*
public PropertySet getSystemConfig() {
return iConfig;
}
*/
/** Get UserMessageHandler that recieves a series of plain
* text messages for the user.
*/
public UserMessageHandler getUserMessageHandler() {
return sUserMessageHandler;
}
/** Set CheckInstallation mode.
* true => just check install and don't try to generate anything
* @param pCheckInstallation boolean
*/
public void setCheckInstallation( boolean pCheckInstallation ) {
iCheckInstallation = pCheckInstallation;
}
/** Get CheckInstallation mode. */
public boolean getCheckInstallation() {
return iCheckInstallation;
}
/** Set command line PropertySet.
* @param pCmdLine PropertySet
*/
/*
public void setCmdLinePropertySet( PropertySet pCmdLine ) {
if( ErrorUtil.not_null( pCmdLine, "pCmdLine" ) ) {
iCmdLine = pCmdLine;
}
}
*/
/** Get command line PropertySet. */
/*
public PropertySet getCmdLinePropertySet() {
return iCmdLine;
}
*/
/** Clear paths to template files. */
/*
public void clearTemplatePaths() {
iTemplatePaths.removeAllElements();
}
*/
/** Add paths to template files using a List of Strings or TemplatePath objects.
* @param pTemplates list of templates to modify
* @param pTemplatePathsToAdd paths to template files
*/
public static void addTemplatePaths( List pTemplates, List pTemplatePathsToAdd ) throws TemplateException {
if( ErrorUtil.is_null( pTemplatePathsToAdd, "pTemplatePaths" ) ) {
// REVIEW: need to determine a standard behaviour in Jostraca object for bad args
return; // do not accept null value
}
Object o = null;
String templatePath = null;
int numTemplates = pTemplatePathsToAdd.size();
for( int templateI = 0; templateI < numTemplates; templateI++ ) {
o = (Object) pTemplatePathsToAdd.get( templateI );
if( null == o ) {
continue;
}
else if( o instanceof String ) {
templatePath = String.valueOf(o).trim();
BasicTemplatePath btp = new BasicTemplatePath( templatePath );
pTemplates.add( btp );
}
else if( o instanceof TemplatePath ) {
pTemplates.add( o );
}
}
}
/** Get paths to template files. */
/*
public List getTemplatePaths() {
return iTemplatePaths;
}
*/
/** Send informational text message to user.
* @param pMessage text
*/
public void displayInfo( String pMessage ) {
sUserMessageHandler.info( pMessage );
}
/** Send error text message to user.
* @param pMessage text
*/
public static void displayErr( String pMessage ) {
sUserMessageHandler.error( "PROBLEM: ", pMessage );
}
/** Send exception description to user.
* @param pException exception
*/
public static void displayErr( Exception pException ) {
sUserMessageHandler.error( "PROBLEM: ", pException );
}
// REVIEW: kill
/** Display user error messages.
* @param pUserErrors list of String text messages
*/
/*
public static void displayUserErrors( Vector pUserErrors ) {
try {
int numErr = pUserErrors.size();
if( 0 < numErr ) {
sUserMessageHandler.error("Generation failed for some templates due to the following errors:");
for(int errI = 0; errI < numErr; errI++) {
sUserMessageHandler.error( String.valueOf( pUserErrors.elementAt(errI) ) );
}
}
}
catch( Exception e ) {
sUserMessageHandler.error( "Generation failed; internal error: org.jostraca.Jostraca(@line:342).", e );
}
}
*/
/** Display installation ok message. */
public static final void displayInstallationOKMessage( String pHomeFolder ) {
String homeFolder = pHomeFolder;
File homeFolderFile = new File( pHomeFolder );
try {
homeFolder = homeFolderFile.getCanonicalPath();
}
catch( IOException ioe ) {
homeFolder = homeFolderFile.getAbsolutePath();
}
sUserMessageHandler.info( "Jostraca Installation OK." );
sUserMessageHandler.info( "Home folder: '"+homeFolder+"'." );
}
/** Display version information. */
public static final void displayVersion() {
sUserMessageHandler.info
(
"\n"
+"Jostraca, version "+Service.VERSION_NUMBER+" (release "+Service.RELEASE_NAME+")\n"
+"\n"
+"Jostraca may be distributed only under the terms and \n"
+"conditions of the GNU General Public License.\n"
+"(see http://www.gnu.org/copyleft/gpl.html or LICENSE.txt)\n"
+"\n"
+"Documentation can be found in the doc folder of the\n"
+"distribution or at: http://www.jostraca.org.\n"
+"\n"
+"Enter jostraca -help for a list of command line options.\n"
);
}
/** Display usage. */
private static final void displayUsage() {
sUserMessageHandler.info
(
"usage: \n"
+"jostraca [OPTIONS] template[.jtm] [TEMPLATE_OPTIONS]\n"
+"jostraca -l [OPTIONS] template1[.jtm] template2[.jtm] ...\n"
+"\n"
+"options: \n"
+" -" + ARG_OUTPUT_FOLDER + " output-folder output folder\n"
+" -" + ARG_WORK_FOLDER + " work-folder work folder\n"
+" -" + ARG_ALL_TEMPLATES + " all arguments are templates\n"
+" -" + ARG_ARGUMENT + " \"TEMPLATE_OPTIONS\" code writer options\n"
+" -" + ARG_TEMPLATE_LIST + " file template list file\n"
+"\n"
+" -" + ARG_BACKUP_FOLDER + " folder backup folder\n"
+" -" + ARG_NO_BACKUP + " don't backup\n"
+" -" + ARG_META_FOLDER + " folder metadata folder\n"
+" -" + ARG_NO_META + " don't store metadata\n"
+"\n"
+" -" + ARG_COMPILE + " compile template\n"
+" -" + ARG_NO_COMPILE + " don't compile template\n"
+" -" + ARG_GENERATE + " generate output files\n"
+" -" + ARG_NO_GENERATE + " don't generate output files\n"
+"\n"
+" -" + ARG_WRITER_FORMAT + " file writer format file\n"
+" -" + ARG_ADD_CONFIG + " file additional configuration files\n"
+" -" + ARG_CONFIG + " file configuration file\n"
+" -" + ARG_DEFINE + "some.Option=value set an option explicitly\n"
+" -" + ARG_NON_STANDARD + " option-list non-standard options\n"
+" " + " old : use old template processor\n"
+"\n"
+" -" + ARG_HIGH_VERBOSE + " verbose\n"
+" -" + ARG_LOW_VERBOSE + " quiet\n"
+" -" + ARG_DUMP + " settings,template dump template and/or settings\n"
+" -" + ARG_TEMPLATE_DOC + " template[.jtm] show template documentation\n"
+"\n"
+"jostraca -" + SPECIAL_ARG_VERSION + " display version information\n"
+"jostraca -" + SPECIAL_ARG_HELP + " display usage information\n"
+"jostraca -" + SPECIAL_ARG_CHECK + " check installation"
);
}
private static final void displayQuickUsage() {
sUserMessageHandler.info( "\n(jostraca -help gives a list of command line options)" );
}
// private methods
private void handleCommandLineOptions( PropertySet pCmdLineOptions ) throws Exception {
try {
String msgLevel = pCmdLineOptions.get( Property.main_MessageLevel );
if( "".equals( msgLevel ) ) {
sUserMessageHandler.setThreshold( UserMessageHandler.INFO );
}
else {
sUserMessageHandler.setThreshold( UserMessageHandler.TypeNameUtil.getTypeForName( msgLevel ) );
}
}
catch( TemplateException te ) {
if( StandardException.Code.CAT_user == te.getCat() ) {
displayErr( te.getMessage() );
exitProgram(1);
}
else {
throw te;
}
}
}
public static PropertySet parseCommandLine( String pArgString, ArrayList pTemplates, ArrayList pAdditionalConfig ) throws Exception {
String[] args = ArgUtil.splitQuoted( pArgString );
return parseCommandLine( args, pTemplates, pAdditionalConfig );
}
/** Parse cmd line used to invoke Jostraca.
* @param pArgs array of command line arguments
*/
public static PropertySet parseCommandLine( String[] pArgs, ArrayList pTemplates, ArrayList pAdditionalConfig ) throws Exception {
boolean argumentsAreTemplateNames = false;
boolean usingTemplateListFile = false;
StringBuffer codeWriterOptions = new StringBuffer();
boolean usingDefaultConf = true; // unless -f is found
PropertySet cmdLineOptions = new PropertySet();
String configPath = null;
ArrayList additionalConfigFiles = new ArrayList();
ArrayList cmdlinetemplates = new ArrayList();
// parse command line
Getopt g = new Getopt( CMD_NAME, pArgs, ":"+CMD_SPEC_Options );
g.setOpterr( false ); // handle errors manually
int c;
String arg;
while( -1 != ( c = g.getopt() ) ) {
switch( c ) {
case ARG_CONFIG : // configuration file
configPath = g.getOptarg();
usingDefaultConf = false;
break;
case ARG_ADD_CONFIG : // additional configuration file
String addConfigPath = g.getOptarg();
pAdditionalConfig.add( addConfigPath );
break;
case ARG_WRITER_FORMAT : // writer format
String writerFormatPath = g.getOptarg().trim();
checkDataFile( "WriterFormat", writerFormatPath );
cmdLineOptions.set( Property.main_CodeWriterFormat, writerFormatPath );
break;
case ARG_TEMPLATE_DOC : // show documentation
cmdLineOptions.set( Property.main_ShowDocumentation, Standard.YES );
break;
case ARG_OUTPUT_FOLDER : // output folder
String outputFolder = g.getOptarg().trim();
checkFolder( "Output", outputFolder );
cmdLineOptions.set( Property.main_OutputFolder, outputFolder );
break;
case ARG_WORK_FOLDER : // work folder
String workFolder = g.getOptarg().trim();
checkFolder( "Work", workFolder );
cmdLineOptions.set( Property.main_WorkFolder, workFolder );
break;
case ARG_TEMPLATE_LIST : // templates listed in separate file
String templateList = g.getOptarg().trim();
checkDataFile( "Template list", templateList );
addTemplatesFromFile( new File( templateList ), cmdlinetemplates );
usingTemplateListFile = true;
break;
case ARG_ARGUMENT : // template arguments
codeWriterOptions.append( g.getOptarg() );
codeWriterOptions.append( Standard.SPACE );
break;
case ARG_ALL_TEMPLATES : // all arguments are templates
argumentsAreTemplateNames = true;
break;
case ARG_BACKUP_FOLDER : // set backup folder and make backups
String backupFolder = g.getOptarg().trim();
cmdLineOptions.set( Property.main_BackupFolder, backupFolder );
cmdLineOptions.set( Property.main_MakeBackup, Standard.YES );
break;
case ARG_NO_BACKUP : // don't backup
cmdLineOptions.set( Property.main_MakeBackup, Standard.NO );
break;
case ARG_META_FOLDER : // set meta folder and store metadata
String metaFolder = g.getOptarg().trim();
cmdLineOptions.set( Property.main_MetaFolder, metaFolder );
cmdLineOptions.set( Property.main_EnableMeta, Standard.YES );
break;
case ARG_NO_META : // don't store metadata
cmdLineOptions.set( Property.main_EnableMeta, Standard.NO );
break;
case ARG_COMPILE : // compile code writer
cmdLineOptions.set( Property.main_CompileCodeWriter, Standard.YES );
break;
case ARG_NO_COMPILE : // don't compile code writer
cmdLineOptions.set( Property.main_CompileCodeWriter, Standard.NO );
break;
case ARG_GENERATE : // execute code writer, that is, generate output files
cmdLineOptions.set( Property.main_ExecuteCodeWriter, Standard.YES );
break;
case ARG_NO_GENERATE : // don't execute code writer, that is, don't generate output files
cmdLineOptions.set( Property.main_ExecuteCodeWriter, Standard.NO );
break;
case ARG_DUMP : // dump template, settings, etc
String dumpSpec = g.getOptarg().trim();
Service.parseDumpSpec( dumpSpec, cmdLineOptions );
break;
case ARG_DEFINE : // config setting
// REVIEW: this parsing should be somewhere else, probably TextUtil
String nameValue = g.getOptarg().trim();
int equalsPos = nameValue.indexOf("=");
if( -1 != equalsPos ) {
cmdLineOptions.set
( nameValue.substring(0, equalsPos).trim(),
nameValue.substring(equalsPos + 1).trim()
);
}
break;
case ARG_NON_STANDARD : // non-standard options
String nsOptions = g.getOptarg();
parseNonStandardOptions( nsOptions, cmdLineOptions, sUserMessageHandler );
break;
case ARG_LOW_VERBOSE : // low verbosity
cmdLineOptions.set( Property.main_MessageLevel, UserMessageHandler.TypeNameUtil.getNameForType( UserMessageHandler.WARN ) );
break;
case ARG_HIGH_VERBOSE : // high verbosity
cmdLineOptions.set( Property.main_MessageLevel, UserMessageHandler.TypeNameUtil.getNameForType( UserMessageHandler.DEBUG ) );
break;
case ':': // missing argument to option
throw new JostracaException( "Option " + (char)g.getOptopt() + " requires an argument." );
default: // everything else is a template or a template srgument
break;
}
}
// get template path specifiers and arguments
int start = g.getOptind();
int numArgs = pArgs.length;
for( int tpsI = start; tpsI < numArgs; tpsI++ ) {
String argument = pArgs[tpsI].trim();
if( ( ( !usingTemplateListFile && start == tpsI )
|| argumentsAreTemplateNames
|| argument.toLowerCase().endsWith( JOSTRACA_TEMPLATE_SUFFIX ) ) )
{
cmdlinetemplates.add( argument );
}
else {
codeWriterOptions.append( TextUtil.quoteSpaces( argument ) );
codeWriterOptions.append( Standard.SPACE );
}
}
addTemplatePaths( pTemplates, cmdlinetemplates );
cmdLineOptions.set( Property.main_CodeWriterOptions, codeWriterOptions.toString() );
cmdLineOptions.set( Property.jostraca_ConfigFile, configPath );
cmdLineOptions.set( Property.jostraca_ConfigFolder, resolveConfigFolder( configPath ) );
return cmdLineOptions;
}
/** Handle non-standard options.
* @param pNSA non-standard options list
* @param pCmdLineOptions settings placed here
* @param pUserMessageHandler user messages concerning non-standard option sent here
*/
private static void parseNonStandardOptions( String pNSA,
PropertySet pCmdLineOptions,
UserMessageHandler pUserMessageHandler )
{
if( null == pNSA ) {
displayErr( "Please specify an option-list for -"+ARG_NON_STANDARD+"." );
}
if( -1 != pNSA.indexOf( NSA_old ) ) {
pCmdLineOptions.set( Property.jostraca_old, Standard.YES );
pUserMessageHandler.info( "Using old template processor." );
}
if( -1 != pNSA.indexOf( NSA_noexit ) ) {
pCmdLineOptions.set( Property.jostraca_noexit, Standard.YES );
sExitProgram = false;
}
if( pNSA.startsWith( NSA_track ) ) {
String filepath = pNSA.substring( NSA_track.length() );
File trackF = new File( filepath );
Service.activateTracking( trackF );
pCmdLineOptions.set( Property.jostraca_TrackFile, trackF.getAbsolutePath() );
}
}
/** Validate file path:
* 1. Check file exists.
* 2. Check file is readable
* @param pFileDescription user friendly name for file
* @param pDataFilePath data file path to check
*/
private static void checkDataFile( String pFileDescription, String pDataFilePath ) {
File dataFilePath = new File( pDataFilePath );
if( ! dataFilePath.exists() ) {
displayErr( pFileDescription + " file '"+pDataFilePath+"' does not exist." );
displayQuickUsage();
exitProgram(1);
}
if( ! dataFilePath.canRead() ) {
displayErr( pFileDescription + " file '"+pDataFilePath+"' permissions prevent reading." );
displayQuickUsage();
exitProgram(1);
}
}
/** Validate folder for output:
* 1. Check folder exists.
* 2. Check folder is writable
* @param pFolderDescription user friendly name for folder
* @param pFolderPath folder path to check
*/
private static void checkFolder( String pFolderDescription, String pFolderPath ) {
File folderPath = new File( pFolderPath );
if( ! folderPath.exists() ) {
displayErr( pFolderDescription + " folder '"+pFolderPath+"' does not exist." );
displayQuickUsage();
exitProgram(1);
}
if( ! folderPath.canWrite() ) {
displayErr( pFolderDescription + " folder '"+pFolderPath+"' permissions prevent writing." );
displayQuickUsage();
exitProgram(1);
}
}
/** Add templates from file.
* @param pFile path to file containing template name list
*/
private static void addTemplatesFromFile( File pFile, ArrayList pTemplates ) {
addTemplatePaths( pTemplates, Service.buildTemplateListFromFile( pFile ) );
}
// REVIEW: this should be done in Service
// REVIEW: how to handle main.Location
/** Load base config files: system.conf and local.conf.
* @param pUseDefaultConf true => try to use default if config path is not specified
*/
/*
private PropertySet loadBaseConfigFiles( String pConfigPath, boolean pUseDefaultConf ) throws Exception {
// load system config file - use default if -f was not specified
String configPath = pConfigPath
File configFile = new File( configPath );
if( !pUseDefaultConf ) {
checkDataFile( "System Configuration", configPath );
}
PropertySet system = new PropertySet();
try {
system.load( configFile );
Tools.produceJostracaLocation( system, configFile );
}
catch( Exception e ) {
system = DefaultPropertySets.makeSystemPropertySet();
}
PropertySet local = new PropertySet();
File localConfigFile = new File( getConfigFolder(), system.get( Property.jostraca_LocalConfigFileName ) );
if( localConfigFile.exists() && !localConfigFile.isDirectory() ) {
local.load( localConfigFile );
system.overrideWith( local );
}
else {
// if local.conf does not exist, ignore
}
return system;
}
*/
/** Validate config file
* @param pConfig configuration to validate
* REVIEW: what relation to Service.validateMergedPropertySet?
*/
private void validateConfig( PropertySet pConfig ) {
// this expression defaults to yes unless it actually evaluates to no
// Above comment written in 2000; ROFL in 2010 - RR
// (the conditional is still correct)
if( ! pConfig.isNo( Property.jostraca_strict_version ) ) {
// check version number
// this may change as time progresses to something more useful
String version = pConfig.get( Property.jostraca_version );
if( ! version.startsWith( Service.VERSION_NUMBER ) ) {
if( version.startsWith( "0.3" )
|| version.startsWith( "0.2" )
|| version.startsWith( "0.1" )
) {
// compatible
}
else {
displayErr("Jostraca version "+Service.VERSION_NUMBER+" configuration file required.");
displayQuickUsage();
exitProgram(1);
}
}
}
}
/** If version info or help requested, display and exit.
* @param pArgs command line args
*/
private final void handleSpecialArgs( String[] pArgs ) {
// WARNING: Hack
// The standard distribution uses a script to run
// Jostraca. This script places -f path as the first
// two arguments. Hence the -version or -help args
// can be the first or third arguments.
if( 0 < pArgs.length ) {
String firstArg = pArgs[0];
String checkArg = firstArg;
if( (Standard.MINUS+ARG_CONFIG).equals( firstArg ) && 3 == pArgs.length ) {
checkArg = pArgs[2];
}
if( (Standard.MINUS+SPECIAL_ARG_VERSION).equalsIgnoreCase( checkArg )
|| (Standard.MINUS+Standard.MINUS+SPECIAL_ARG_VERSION).equalsIgnoreCase( checkArg )
) {
displayVersion();
exitProgram(0);
}
else if( (Standard.MINUS+SPECIAL_ARG_HELP).equalsIgnoreCase( checkArg )
|| (Standard.MINUS+Standard.MINUS+SPECIAL_ARG_HELP).equalsIgnoreCase( checkArg )
) {
displayUsage();
exitProgram(0);
}
else if( (Standard.MINUS+SPECIAL_ARG_CHECK).equalsIgnoreCase( checkArg )
|| (Standard.MINUS+Standard.MINUS+SPECIAL_ARG_CHECK).equalsIgnoreCase( checkArg )
) {
setCheckInstallation( true );
}
}
}
/** Get path to config folder. */
private static String resolveConfigFolder( String pConfigPath ) {
return FileUtil.getParent( pConfigPath );
}
/* Private Methods >> */
/* Main << */
/** Main entry point to command line Jostraca application.
* @param pArgs command line arguments
*/
public static void main( String[] pArgs ) {
Throwable t = null;
try {
try {
execute( pArgs );
}
catch( StandardException se ) {
displayErr( se );
}
}
catch( Throwable tt ) {
t = tt;
}
// something is terribly wrong if we get here
// assume everything is broken and only use standard java
if( null != t ) {
System.out.println( "Jostraca Internal Error:" );
t.printStackTrace();
}
}
/** Main execution point.
* @param pArgs command line arguments
*/
public static void execute( String[] pArgs ) throws Exception {
// create new cmd line app and parse cmd line args
Jostraca js = new Jostraca();
js.handleSpecialArgs( pArgs );
ArrayList templatePaths = new ArrayList();
ArrayList additionalConfig = new ArrayList();
PropertySet cmdLineOptions = js.parseCommandLine( pArgs, templatePaths, additionalConfig );
js.handleCommandLineOptions( cmdLineOptions );
String configFolder = cmdLineOptions.get( Property.jostraca_ConfigFolder );
// create new service object and set templates
Service s = new Service();
s.loadConfigFromFolder( new File( configFolder ), additionalConfig );
// are we just checking the install
if( js.getCheckInstallation() ) {
displayVersion();
displayInstallationOKMessage( s.getCurrentConfig().get(Property.jostraca_Location) );
// REVIEW: program exit codes should be defined in Standard
exitProgram(0);
}
// at least one template must be specified
if( 0 == templatePaths.size() ) {
displayErr("No templates specified.");
displayQuickUsage();
exitProgram(1);
}
s.setTemplatePaths( templatePaths );
// set standard properties
s.addPropertySet( Service.CONF_cmdline, cmdLineOptions );
s.setUserMessageHandler( js.getUserMessageHandler() );
// generate output files from templates
s.build();
}
/** Exit the JVM.
* @param pExitCode numerical exit code
*/
private static final void exitProgram( int pExitCode ) {
if( sExitProgram ) {
System.exit( pExitCode );
}
else {
// REVIEW: store exit code and allow retreival?
}
}
}