ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andre Cesta <aace...@yahoo.com>
Subject Replace task not suitable for my needs, wrote Ant extension to address problems.
Date Wed, 16 Apr 2003 06:10:59 GMT

The Replace task was not suitable for my needs, so I ended up
writing my own "replace" Ant extension.

Would the more active developers on the list please consider my case?

------------------------------------

Use case 1:  Performing token replacements ala those performed via Unix m4 utility.
             Man page for m4 utility: http://www.unidata.ucar.edu/cgi-bin/man-cgi?m4+1

Use case 1 details:  

Given source file called java.properties.j4,; Given list of tokens and their values;
Process java.properties.j4, generating on the same directory java.properties with the
token substitutions.

Given directory, scan the directory; Given list of tokens and their values;
Scan the directory, perfoming the operations above on every individual .j4 file.

Benefits: the original is not lost (it is lost on the replace task).
          the original is kept on version control.
          the end result requires less ant lines (copy file, filter, etc).

Now some particularities of my extension: I don't allow specification of a token file,
instead I consider the list of Ant properties to be my set of tokens.  This can be VERY
convenient, but I would like to improve the task to be able to receive a list of tokens
as well.

I have forced the .j4 extension for these files.  I believe this should be the recommended
extension, but not the only one possible.

I am pasting my extension class code in line on this email, but first some usage examples
on
a build.xml file:

----------------8<-----------------------
<!-- Define the extension tasks. -->
<taskdef name="renameext" classname="org.apache.tools.ant.taskdefs.optional.RenameExtensions"
/>
<taskdef name="j4" classname="ji.ant.base.JIJ4" />

<!-- Scan directory for .j4 files, and process them using ant properties as tokens! -->
<j4 dir="../webapps/main/WEB-INF/classes" includes="**" initialExtension=".j4" finalExtension=""
replace="true" />

<!-- Undo the work of the previous j4 call.  Clean generated files. -->
<j4 dir="../webapps/main/WEB-INF/classes" includes="**" initialExtension=".j4" finalExtension=""
clean="true" />

----------------8<-----------------------

Now the code for the extension, contained in one single class.  Notice that
it allows for conditional processing of .j4 file parts based on the value of
Ant properties as well (extra feature that you might want to remove).

Here is an example of a .j4 conditional and token:

token=@ji.build.project@
token=@ji.build.project@
token=@ji.build.project@

ifelse(@ji.build.env@, dev, `
       dev only.
',`dnl')

ifelse(@ji.build.env@, prd, `
       production environment.
',`dnl')

Now the code for the extension:

----------------8<-----------------------

package ji.ant.base;

import java.io.*;
import java.util.*;
import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;

/**
 * This class performs token replacements on files automatically.
 * It is an Ant Task.
 *
 * You can escape back-quotes and quotes within conditionals by having two in a row
 * e.g. to escape `hello' put ``hello''
 *
 * @author  Andre Cesta
 */
public class JIJ4 extends MatchingTask {

    /** Directory where the file filtering operations will take place. */
    private File dir;

    /** Flat that tells whether we are generating filtered files or not. */
    private boolean replace = false;
    
    /** Flat that tells if we are cleaning filtered files or not. */
    private boolean clean = false;
    
    /** Initial extension of files being filtered. */
    private String initialExtension = "";
    
    /** . */
    private String finalExtension = "";
    
    
    /** Empty constructor. */
    public JIJ4() {
        super();
    }
    
    /**
     * Sets replace flag that will cause it to replace the final/target file.
     */
    public void setReplace(String pReplaceStr) {
        replace = Project.toBoolean(pReplaceStr);
    }
    
    /**
     * Sets the clean attribute
     */
    public void setClean(String cleanString) {
        clean = Project.toBoolean(cleanString);
        if ( clean ) {
            // Force directory scan to report all files
            replace = true;
        }
    }
    
    /** Set initialExtension. **/
    public void setInitialExtension(String pInitialExt) {
        initialExtension = pInitialExt;
    }
    
    /** Set finalExtension. **/
    public void setFinalExtension(String pFinalExt) {
        finalExtension = pFinalExt;
    }
    
    /**
     * Set the source dir to find the files to be renamed.
     */
    public void setDir(String pSrcDir) {
        dir = project.resolveFile(pSrcDir);
    }
    
    /**
     * Executes the task, i.e. does the actual compiler call
     */
    public void execute() throws BuildException {
        // first off, make sure that we've got a from and to extension
        if (initialExtension == null || finalExtension == null || dir == null)
            throw new BuildException("dir, initialExtension and finalExtension attributes
not
provided!");
	
        // scan source and dest dirs to build up rename list
        DirectoryScanner vDs = getDirectoryScanner(dir);
	
        String[] vFiles = vDs.getIncludedFiles();

        Hashtable vFilterList = scanDir(dir, vFiles);

        Enumeration e = vFilterList.keys();
        File vInitialFile = null;
        File vFinalFile = null;
        while (e.hasMoreElements()) {
            vInitialFile = (File)e.nextElement();
            vFinalFile = (File)vFilterList.get(vInitialFile);
            if ( clean ) {
		System.out.println("J4 file deletion:" + vFinalFile);
                vFinalFile.delete();
            } else {
		System.out.println("J4 file generation:" + vFinalFile);
                try {
                    this.copyFile(vInitialFile, vFinalFile );
                } catch ( java.io.IOException io ) {
                    throw new BuildException( io.getMessage() );
                }
            }

        }

    }
    
    
    /** Just copies a file applying the filtering. */
    public void copyFile(File pInitialFile, File pDestFile ) throws IOException {
	
        if ( pDestFile.lastModified() < pInitialFile.lastModified()) {
            log("Generating: " + pInitialFile.getAbsolutePath() + " > "
		+ pDestFile.getAbsolutePath(), Project.MSG_VERBOSE);
	    
            // ensure that parent dir of dest file exists!
            // not using getParentFile method to stay 1.1 compat
            File vParent = new File(pDestFile.getParent());
            if (!vParent.exists()) 
                vParent.mkdirs();
	    
            BufferedReader in = new BufferedReader(new FileReader(pInitialFile));
            BufferedWriter out = new BufferedWriter(new FileWriter(pDestFile));
	    
            boolean inConditional = false;
            boolean inElseConditional = false;
            boolean includeConditional = false;
            String conditional = "";
	    
            int length;
            String newline = null;
            String line = in.readLine();
            while (line != null) {
		if (line.length() == 0) {
		    out.newLine();
		} else {
                    // create a Map containing both filters and properties
                    java.util.Map tokens =  (java.util.Map)(project.getFilters().clone());
                    tokens.putAll(project.getProperties());
		    
                    newline = replace( line, tokens );
		    
                    if ( inConditional ) {
                        if ( newline.indexOf( "`dnl'" ) != -1 ) { // 'else' conditional is
empty
			    
                            inConditional = false;
			    
                            if ( includeConditional ) {
                                out.write( conditional );
                                includeConditional = false;
                            }
			    
                            conditional = "";
			    
                        } else if ( ( newline.indexOf( "`" ) != -1 ) &&
                                    ( newline.indexOf( "``" ) == -1 ) ) { // 'else' conditional
does something
			    
                            inConditional = false;
                            inElseConditional = true;
			    
                            if ( includeConditional ) 
                                out.write( conditional );
			    
                            conditional = "";
			    
                        } else {
                            conditional += newline + "\n";
                        }
			
                    } else if ( inElseConditional ) {
			
			if ( newline.startsWith( "'" ) && !newline.startsWith( "''" ) ) {
			    
                            inElseConditional = false;
			    
                            if ( !includeConditional ) {
				
                                out.write( conditional );
                                out.newLine();
				
                            }
			    
                            includeConditional= false;
                            conditional = "";
			    
                        } else {
                            conditional += newline + "\n";
                        }
			
                    } else if ( newline.indexOf( "ifelse" ) != -1 ) {
                        inConditional = true;
                        String variable = newline.substring( newline.indexOf( "(" ) + 1 ,
newline.indexOf( "," ) );
                        String value = newline.substring( newline.indexOf( "," ) + 1 ,
newline.lastIndexOf( "," ) );
                        variable = variable.trim();
                        value = value.trim();
			
                        //Logic, ORs: '|'
                        java.util.StringTokenizer valueTokenizer = new java.util.StringTokenizer(
value );
                        while ( valueTokenizer.hasMoreTokens() ) {
                            if ( variable.equals( valueTokenizer.nextToken( "|" ).trim() )
) {
                                includeConditional = true;
                            }
                        }
			
                    } else {
                        out.write(newline);
                        out.newLine();
                    }
                }
                line = in.readLine();
            }
	    
            out.close();
            in.close();

        }
    }
    
    
    /** Replace tokens in string. */
    private String replace(String s, java.util.Map tokens) {
        int index = s.indexOf(Project.TOKEN_START);

        if (index > -1) {
            try {
                StringBuffer b = new StringBuffer();
                int i = 0;
                String token = null;
                String value = null;

                do {
                    token = s.substring(index + Project.TOKEN_START.length(),
s.indexOf(Project.TOKEN_END, index + Project.TOKEN_START.length() + 1));
                    b.append(s.substring(i, index));
                    if (tokens.containsKey(token)) {
                        value = (String) tokens.get(token);
                        log("Replacing: " + Project.TOKEN_START + token + Project.TOKEN_END
+ " ->
" + value, Project.MSG_VERBOSE);
                        b.append(value);
                    } else {
                        b.append(Project.TOKEN_START);
                        b.append(token);
                        b.append(Project.TOKEN_END);
                    }
                    i = index + Project.TOKEN_START.length() + token.length() +
Project.TOKEN_END.length();
                } while ((index = s.indexOf(Project.TOKEN_START, i)) > -1);

                b.append(s.substring(i));
                return b.toString();
            } catch (StringIndexOutOfBoundsException e) {
                return s;
            }
        } else {
            return s;
        }
    }

    
    /** Scans directory for files. */
    private Hashtable scanDir(File dir, String[] files) {
//System.out.println( "dir = " + dir );
        Hashtable list = new Hashtable();
        for (int i = 0; i < files.length; i++) {
            File srcFile = new File(dir, files[i]);
            String filename = files[i];
            // if it's a file that ends in the initialExtension, copy to the rename list
            if (filename.toLowerCase().endsWith(initialExtension)) {
                File pDestFile = new File(dir, filename.substring(0,
filename.lastIndexOf(initialExtension)) + finalExtension);
                if (replace || !pDestFile.exists()) {
                    list.put(srcFile, pDestFile);
                } else {
                    log("Rejecting file: '" + srcFile + "' for rename as replace is false
and file
exists", Project.MSG_VERBOSE);
                }
            } else {
                log("File '"+ filename + "' doesn't match initialExtension: '" + initialExtension
+ "'", Project.MSG_VERBOSE);
            }
        }
        return list;
    }
    
}


=====
---------------------------------------------------
 Andre Cesta
 +64 9 4895311 home
 +64 9 9125644 work
 +64 21646975 mobile
http://geocities.com/aacesta
---------------------------------------------------

http://mobile.yahoo.com.au - Yahoo! Mobile
- Check & compose your email via SMS on your Telstra or Vodafone mobile.

Mime
View raw message