/*
* Name: JostracaTask
* Authors: Lars Grammel, Richard Rodger
*
* Copyright (c) 2002-2005 Lars Grammel, 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.Standard;
import org.jostraca.util.ErrorUtil;
import org.jostraca.util.ArgUtil;
import org.jostraca.util.FileUtil;
import org.jostraca.util.BooleanParser;
import org.jostraca.util.RegExp;
import org.jostraca.util.RegExpException;
import org.jostraca.util.PropertySet;
import org.jostraca.util.UserMessageHandler;
import org.jostraca.util.CommandLineUserMessageHandler;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import java.io.File;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Hashtable;
/**
* <a href="http://jakarta.apache.org" target="_blank">Jakarta Ant</a> task for
* Jostraca.
* <p>
* Example:
* <pre>
* <taskdef name="jostraca"
* classname="org.jostraca.JostracaTask" >
* <classpath refid="class-path-ref" />
* </taskdef>
*
* <target name="generate" >
* <jostraca outputFolder = "..\src\java\de\lgsoftware\la\proxy"
* workFolder = "..\src\generators"
* configFile = "conf\system.conf"
* template = "..\src\template\BusinessLogicProxyLayer.jtm"
* templateOptions = "bl_proxy_list.txt" />
* </target>
* </pre>
* </p>
* <p>The attribute <code>configFile</code> is not required.</p>
*
*/
public class JostracaTask extends Task {
// private static
private static final String TRUE = "true";
private static final String FALSE = "false";
private static final String RE_UNDEF_PROP = "\\${.*?}";
private static final String JOSTRACA_PROPERTY_PREFIX = "jostraca.";
private static RegExp sFixUndefProps = null;
// private instance
private String iTemplate;
private String iTemplateListStr;
private File iTemplateListFile;
private String iTemplateOptions;
private File iOutputFolder;
private File iWorkFolder;
private File iBackupFolder;
private File iHomeFolder;
private File iConfigFile;
private File iAdditionalConfigFile;
private boolean iBackup = true;
private boolean iCompile = true;
private boolean iGenerate = true;
private boolean iVerbose = false;
private boolean iQuiet = false;
private String iEnable = TRUE;
private String iDisable = FALSE;
// compile and generate are tri-state: on (-c), off (-C), not set
// REVIEW: find a better way to do this
private boolean iCompileSet = false;
private boolean iGenerateSet = false;
private String iWriterFormat;
private String iDefine;
private String iDump;
private String iClassPath;
private String iClassPathPrefix;
private String iClassPathSuffix;
private ArrayList iTemplateList = new ArrayList();
// text inside jostraca element
private String iText = Standard.EMPTY;
private File iTrackFile = null;
// static
static {
try {
// deal with undefined Ant properties - consider them false
sFixUndefProps = RegExp.make( RE_UNDEF_PROP, FALSE );
}
catch( RegExpException ree ) {
// REVIEW: this is probably not right
System.err.println( "Unable to create regular expression: '"+RE_UNDEF_PROP+"' :"+ree );
}
}
// public methods
/** Creates a new JostracaTask. */
public JostracaTask() {
// does nothing
}
/** The template used to generate code.
* @param pTemplate template file or reference
* @see #getTemplate()
*/
public void setTemplate( String pTemplate ) {
iTemplate = pTemplate;
}
/** @see #setTemplate( String ) */
public String getTemplate() {
return iTemplate;
}
/** Specifies a list of templates, comma or space separated
* @param pTemplateList template list
* @see #getTemplateList()
* @see #getTemplateListAsArray()
*/
public void setTemplateList( String pTemplateList ) {
iTemplateListStr = pTemplateList;
}
/** @see #setTemplateList( String ) */
public String getTemplateList() {
return iTemplateListStr;
}
/** Returns the template list as a String[]. The template
* options are seperated by a space (or comma), and each token is added to the array,
* so the order is preserved.
* <p>
* If there are no templates, a String[] with the length 0 is returned.</p>
*/
public String[] getTemplateListAsArray() {
return makeStringArray( getTemplateList() );
}
/** A file containing a list of templates to use, one per line.
* @param pTemplateListFile file containing template list
* @see #getTemplateListFile()
*/
public void setTemplateListFile( File pTemplateListFile ) {
iTemplateListFile = pTemplateListFile;
}
/** @see #setTemplateListFile( File ) */
public File getTemplateListFile() {
return iTemplateListFile;
}
/** Specifies the template options, comma or space separated
* @param pTemplateOptions template options
* @see #getTemplateOptions()
* @see #getTemplateOptionsAsArray()
*/
public void setTemplateOptions( String pTemplateOptions ) {
iTemplateOptions = pTemplateOptions;
}
/** @see #setTemplateOptions( String ) */
public String getTemplateOptions() {
return iTemplateOptions;
}
/** Returns the template options as a String[]. The template
* options are seperated by a space (or comma), and each token is added to the array,
* so the order is preserved.
* <p>
* If there are no template options, a String[] with the length 0 is returned.</p>
*/
public String[] getTemplateOptionsAsArray() {
String[] options = makeStringArray( getTemplateOptions() );
int numOptions = options.length;
for( int oI = 0; oI < numOptions; oI++ ) {
options[oI] = Standard.MINUS + Jostraca.ARG_ARGUMENT + Standard.SPACE + options[oI];
}
return options;
}
/** Specifies the output folder where the generated code will be saved. It
* is passed to Jostraca using the option "-o outputFolder". If no output
* folder is specified, the option "-o" is not passed to Jostraca.
* @param pOutputFolder output folder for generated code
* @see #getOutputFolder()
*/
public void setOutputFolder( File pOutputFolder ) {
iOutputFolder = pOutputFolder;
}
/** @see #setOutputFolder( File ) */
public File getOutputFolder() {
return iOutputFolder;
}
/** @deprecated
* @see #setOutputFolder( File )
*/
public File getOutputDirectory() {
return getOutputFolder();
}
/** @deprecated
* @see #getOutputFolder()
*/
public void setOutputDirectory( File pOutputFolder ) {
setOutputFolder( pOutputFolder );
}
/** Specifies the work folder where the CodeWriter will be saved. It
* is passed to Jostraca using the option "-w workFolder". If no output
* folder is specified, the option "-w" is not passed to Jostraca.
* @param pWorkFolder output folder for CodeWriter
* @see #getWorkFolder()
*/
public void setWorkFolder( File pWorkFolder ) {
iWorkFolder = pWorkFolder;
}
/** @see #setWorkFolder( File ) */
public File getWorkFolder() {
return iWorkFolder;
}
/** @deprecated
* @see #getWorkFolder()
*/
public File getWorkingDirectory() {
return getWorkingDirectory();
}
/** @deprecated
* @see #setWorkFolder( File )
*/
public void setWorkingDirectory( File pWorkFolder ) {
setWorkingDirectory( pWorkFolder );
}
/** Specifies the backup folder where the existing versions of generated files will be saved.
* It is passed to Jostraca using the option "-b backupFolder". If no output
* folder is specified, the option "-b" is not passed to Jostraca.
*
* @param pBackupFolder backup folder for generated code
* @see #getBackupFolder()
*/
public void setBackupFolder( File pBackupFolder ) {
iBackupFolder = pBackupFolder;
}
/** @see #setBackupFolder( File ) */
public File getBackupFolder() {
return iBackupFolder;
}
/** Sets the home folder of the Jostraca installation.
* This option may be using instead of setConfigFile.
*
* @param pHomeFolder output folder where the generated code will be saved
* @see #getHomeFolder()
*/
public void setHomeFolder( File pHomeFolder ) {
iHomeFolder = pHomeFolder;
}
/** @see #setHomeFolder( File ) */
public File getHomeFolder() {
return iHomeFolder;
}
/** Specifies the configuration file for Jostraca. It is passed to Jostraca using
* the option "-f configFile". If no config file is specified, the option
* "-f" is not passed to Jostraca.
* <p>An internal standard configuration is used if this attribute is not supplied.</p>
* @param pConfigFile configuration file
* @see #getConfigFile()
* @see #setHomeFolder( File )
*/
public void setConfigFile( File pConfigFile ) {
iConfigFile = pConfigFile;
}
/** @see #setConfigFile( File ) */
public File getConfigFile() {
return iConfigFile;
}
/** Specifies an additional configuration file for Jostraca. It is passed to Jostraca
* using the option "-F configFile". If no config file is specified, the option
* "-F" is not passed to Jostraca.
* @param pAdditionalConfigFile configuration file
* @see #getAdditionalConfigFile()
*/
public void setAdditionalConfigFile( File pAdditionalConfigFile ) {
iAdditionalConfigFile = pAdditionalConfigFile;
}
/** @see #setAdditionalConfigFile( File ) */
public File getAdditionalConfigFile() {
return iAdditionalConfigFile;
}
/** True => make backups.
* @param pBackup
*/
public void setBackup( boolean pBackup ) {
iBackup = pBackup;
}
/** @see #setBackup( boolean ) */
public boolean getBackup() {
return iBackup;
}
/** True => compile templates
* @param pCompile
*/
public void setCompile( boolean pCompile ) {
iCompile = pCompile;
iCompileSet = true;
}
/** @see #setCompile( boolean ) */
public boolean getCompile() {
return iCompile;
}
/** True => generate code
* @param pGenerate
*/
public void setGenerate( boolean pGenerate ) {
iGenerate = pGenerate;
iGenerateSet = true;
}
/** @see #setGenerate( boolean ) */
public boolean getGenerate() {
return iGenerate;
}
/** True => verbose mode - more output to console
* @param pVerbose
*/
public void setVerbose( boolean pVerbose ) {
iVerbose = pVerbose;
}
/** @see #setVerbose( boolean ) */
public boolean getVerbose() {
return iVerbose;
}
/** True => quiet mode - no console ouput
* @param pQuiet
*/
public void setQuiet( boolean pQuiet ) {
iQuiet = pQuiet;
}
/** @see #setQuiet( boolean ) */
public boolean getQuiet() {
return iQuiet;
}
/** True => actually perform generation
* @see #setDisable( String )
* @param pEnable boolean expression
*/
public void setEnable( String pEnable ) {
iEnable = pEnable;
}
/** @see #setEnable( String ) */
public String getEnable() {
return iEnable;
}
/** Get boolean value.
* @see #getEnable()
*/
public boolean getEnableValue() {
return parseBooleanExpression( "enable", getEnable() );
}
/** True => do not perform generation
* @see #setEnable( String )
* @param pDisable boolean expression
*/
public void setDisable( String pDisable ) {
iDisable = pDisable;
}
/** @see #setDisable( String ) */
public String getDisable() {
return iDisable;
}
/** Get boolean value.
* @see #getEnable()
*/
public boolean getDisableValue() {
return parseBooleanExpression( "disable", getDisable() );
}
/** Specify WriterFormat.
* @param pWriterFormat writer format
*/
public void setWriterFormat( String pWriterFormat ) {
iWriterFormat = pWriterFormat;
}
/** @see #setWriterFormat( String ) */
public String getWriterFormat() {
return iWriterFormat;
}
/** Define a configuration setting using Name=Value syntax
* Separate multiple defines with commas or spaces
* @param pDefine name=value pair(s)
* @see #getDefine()
*/
public void setDefine( String pDefine ) {
iDefine = pDefine;
}
/** @see #setDefine( String ) */
public String getDefine() {
return iDefine;
}
/** Returns the settings as a String[]. */
public String[] getDefineAsArray() {
return makeStringArray( getDefine() );
}
/** Dump template or settings to a file.
* Use the keywords settings,template.
* @param pDump dump keywords
*/
public void setDump( String pDump ) {
iDump = pDump;
}
/** @see #setDump( String ) */
public String getDump() {
return iDump;
}
/** Set the classpath for compiling and executing the CodeWriter.
* Both : or ; function as element separator.
* @see #setClassPathPrefix( String )
* @see #setClassPathSuffix( String )
* @param pClassPathRef java classpath reference
*/
public void setClassPathRef( Reference pClassPathRef ) {
Path p = new Path( getProject() );
p.setRefid( pClassPathRef );
iClassPath = p.toString();
}
/** @see #setClassPathRef( Reference ) */
public String getClassPath() {
return iClassPath;
}
/** Get define option.
* @see #getClassPath()
*/
public String getClassPathDefine() {
return Standard.MINUS + Jostraca.ARG_DEFINE + PropertyJava.ClassPath + Standard.EQUALS + getClassPath();
}
/** Set the prefix to the classpath for compiling and executing the CodeWriter.
* Both : or ; function as element separator.
* @see #setClassPathPrefix( String )
* @see #setClassPathSuffix( String )
* @param pClassPathPrefix java classpath
*/
public void setClassPathPrefix( String pClassPathPrefix ) {
iClassPathPrefix = pClassPathPrefix;
}
/** @see #setClassPathPrefix( String ) */
public String getClassPathPrefix() {
return iClassPathPrefix;
}
/** Get define option.
* @see #getClassPathPrefix()
*/
public String getClassPathPrefixDefine() {
return Standard.MINUS + Jostraca.ARG_DEFINE + PropertyJava.ClassPathPrefix + Standard.EQUALS + getClassPathPrefix();
}
/** Set the prefix to the classpath for compiling and executing the CodeWriter.
* Both : or ; function as element separator.
* @see #setClassPathSuffix( String )
* @see #setClassPathSuffix( String )
* @param pClassPathSuffix java classpath
*/
public void setClassPathSuffix( String pClassPathSuffix ) {
iClassPathSuffix = pClassPathSuffix;
}
/** @see #setClassPathSuffix( String ) */
public String getClassPathSuffix() {
return iClassPathSuffix;
}
/** Get define option.
* @see #getClassPathSuffix()
*/
public String getClassPathSuffixDefine() {
return Standard.MINUS + Jostraca.ARG_DEFINE + PropertyJava.ClassPathSuffix + Standard.EQUALS + getClassPathSuffix();
}
public void addText( String pText ) {
iText = pText;
}
public String getText() {
return iText;
}
public void addTemplate( Template pTemplate ) {
iTemplateList.add( pTemplate );
}
/** Set a tracking file to record detailed debugging information.
* @param pTrackFile tracking file
* @see #getTrackFile
*/
public void setTrackFile( File pTrackFile ) {
iTrackFile = pTrackFile;
}
/** @see #setTrackFile(File) */
public File getTrackFile() {
return iTrackFile;
}
/** Calls Jostraca.main( String[] ) with the specified arguments.
* @throws BuildException no jostraca template was specified
*/
public void execute() throws BuildException {
// REVIEW: rewrite to use Service class directly
if( !getEnableValue() || getDisableValue() ) {
return;
}
// check for required settings
if( null == getTemplate()
&& null == getTemplateList()
&& null == getTemplateListFile()
&& 0 == iTemplateList.size() ) {
throw new BuildException("template must be specified");
}
try {
// need a UMH for Ant
UserMessageHandler umh = new CommandLineUserMessageHandler();
if( getVerbose() ) {
umh.setThreshold( UserMessageHandler.DEBUG );
}
else {
umh.setThreshold( UserMessageHandler.INFO );
}
if( getQuiet() ) {
umh.setThreshold( UserMessageHandler.WARN );
}
PropertySet cmdps = makeCmdPropertySet();
// attribute trackFile overrides property jostraca.TrackFile
File trackF = getTrackFile();
if( null == trackF ) {
if( cmdps.has( Property.jostraca_TrackFile ) ) {
trackF = new File( cmdps.get( Property.jostraca_TrackFile ) );
}
}
if( null != trackF ) {
Service.activateTracking( trackF );
}
List tplist = makeTemplatePaths();
Generator g = null;
File configFolder = null;
if( null != getConfigFile() ) {
configFolder = new File( FileUtil.getParent( getConfigFile() ) );
}
else if( null != getHomeFolder() ) {
configFolder = new File( getHomeFolder(), Service.FOLDER_conf );
}
if( null == configFolder ) {
g = new Generator();
}
else {
g = new Generator( configFolder );
}
g.setAlwaysGenerate( false );
g.setCmdPropertySet( cmdps );
g.generate( tplist, umh );
}
catch( Throwable t ) {
// FIX: should use ant log()
// umh.error( t );
throw new BuildException( t );
}
}
public List makeTemplatePaths() {
ArrayList templatepaths = new ArrayList();
if( null != getTemplate() ) {
templatepaths.add( new BasicTemplatePath( getTemplate() ) );
}
if( null != getTemplateList() ) {
String[] tA = getTemplateListAsArray();
int numT = tA.length;
for( int tI = 0; tI < numT; tI++ ) {
templatepaths.add( new BasicTemplatePath( tA[tI] ) );
}
}
File tlf = getTemplateListFile();
if( null != tlf ) {
templatepaths.add( Service.buildTemplateListFromFile( tlf ) );
}
for( Iterator tmIt = iTemplateList.iterator(); tmIt.hasNext(); ) {
templatepaths.add( ((Template) tmIt.next()).makeTemplatePath( tlf ) );
}
return templatepaths;
}
public PropertySet makeCmdPropertySet() {
PropertySet ps = new PropertySet();
ps.set( Property.jostraca_noexit, Standard.YES );
// read globals
Hashtable globals = project.getProperties();
for( Iterator gIt = globals.keySet().iterator(); gIt.hasNext(); ) {
String name = String.valueOf( gIt.next() );
if( name.startsWith( JOSTRACA_PROPERTY_PREFIX ) ) {
// set properties both with and without prefix
// this allows jostraca.Location instead of jostraca.jostraca.Location
// but requires jostraca.main.OutputFolder
String value = project.getProperty( name );
String rootName = name.substring( JOSTRACA_PROPERTY_PREFIX.length() );
ps.set( name, value );
ps.set( rootName, value );
}
}
Object val = null;
if( null != ( val = getTemplateOptions() ) ) {
ps.set( Property.main_CodeWriterOptions, val );
}
if( null != getOutputFolder() ) {
ps.set( Property.main_OutputFolder, getOutputFolder().toString() );
}
if( null != getWorkFolder() ) {
ps.set( Property.main_WorkFolder, getWorkFolder().toString() );
}
if( null != getBackupFolder() ) {
ps.set( Property.main_BackupFolder, getBackupFolder().toString() );
}
if( !getBackup() ) {
ps.set( Property.main_MakeBackup, Standard.NO );
}
if( iCompileSet && getCompile() ) {
ps.set( Property.main_CompileCodeWriter, Standard.YES );
}
else if( iCompileSet && !getCompile() ) {
ps.set( Property.main_CompileCodeWriter, Standard.NO );
}
if( iGenerateSet && getGenerate() ) {
ps.set( Property.main_ExecuteCodeWriter, Standard.YES );
}
else if( iGenerateSet && !getGenerate() ) {
ps.set( Property.main_ExecuteCodeWriter, Standard.NO );
}
// misc options
// ...
if( null != ( val = getWriterFormat() ) ) {
ps.set( Property.main_CodeWriterFormat, val );
}
// FIX: there should be a utility method for this as also done in Jostraca.java
if( null != getDefine() ) {
String[] defines = getDefineAsArray();
int numDefines = defines.length;
for( int defI = 0; defI < numDefines; defI++ ) {
String define = defines[defI];
int equalsIndex = define.indexOf( Standard.EQUALS );
if( -1 != equalsIndex ) {
try {
ps.set( define.substring(0,equalsIndex), define.substring(equalsIndex+1) );
}
catch( Exception e ) {
ErrorUtil.nonFatalMsg( e );
}
}
}
}
if( null != ( val = getDump() ) ) {
Service.parseDumpSpec( (String) val, ps );
}
if( null != getClassPath() ) {
ps.set( PropertyJava.ClassPath, getClassPathDefine() );
}
if( null != getClassPathPrefix() ) {
ps.set( PropertyJava.ClassPathPrefix, getClassPathPrefixDefine() );
}
if( null != getClassPathSuffix() ) {
ps.set( PropertyJava.ClassPathSuffix, getClassPathSuffixDefine() );
}
PropertySet jostracaTextPS = new PropertySet();
jostracaTextPS.parse( getText() );
ps.inheritFrom( jostracaTextPS );
return ps;
}
// public classes
public static class Template {
private String iName = null;
private String iText = null;
public void setName( String pName ) {
iName = pName;
}
public void addText( String pText ) {
iText = pText;
}
public String getName() {
return iName;
}
public String toString() {
return iName+":"+iText;
}
public TemplatePath makeTemplatePath( File pTemplateListFile ) {
BasicTemplatePath btp = null;
if( null == pTemplateListFile ) {
btp = new BasicTemplatePath( iName );
}
else {
btp = new BasicTemplatePath( iName, pTemplateListFile.getAbsolutePath() );
}
if( null != iText ) {
PropertySet ps = new PropertySet();
ps.parse( iText );
btp.setPropertySet( ps );
}
return btp;
}
}
// private methods
private String[] makeStringArray( String pList ) {
String[] items;
if( null == pList ) {
items = new String[] {};
}
else {
String spaceSeparatedList = pList.replace( ',', ' ' );
items = ArgUtil.splitQuoted( spaceSeparatedList );
}
return items;
}
private boolean parseBooleanExpression( String pAttribute, String pExpression ) {
String expr = pExpression;
try {
expr = sFixUndefProps.replaceAll( expr );
boolean result = BooleanParser.parse( expr );
return result;
}
catch( Exception e ) {
log( "Unable to parse boolean expression in attribute "+pAttribute+": '"+expr+"'" );
return false;
}
}
}