ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Nigel Magnay <Nigel.Mag...@Parsec.co.uk>
Subject RE: ? [Bug 7320] New: - Suggestion: new attribute in replace bu ilt-in-task
Date Mon, 25 Mar 2002 16:44:31 GMT
That's nearly there; taking the example

<filterset begintoken="%" endtoken="*">
    <filter token="DATE" value="${DATE}"/>
    <filtersfile file="${user.home}/dist.properties"/>
  </filterset>

There's a couple of problems

1) I have to specify each name/value pair that I want to 
replace that isn't in a property file - in this example, 
date. So If I need to add one to a template file, I have to 
potentially adjust umpteen build.xml files to reflect this
(I have a 'template' set of build.xml files - it's nice if
most projects don't need to customise them too heavily)

2) I have to specify each .properties file - again, this
can be a great number of them. Would be nicer if I just
imported them with <properties file=""> and the filter
used anything that it could see.

It's just makes life easier... If I could replace it with

<filterset begintoken="%" endtoken="*">
   <filterallproperties/>
</filterset>

it'd be great

> -----Original Message-----
> From: Erik Hatcher [mailto:jakarta-ant@ehatchersolutions.com]
> Sent: 25 March 2002 16:33
> To: Ant Developers List
> Subject: Re: ? [Bug 7320] New: - Suggestion: new attribute in replace
> built-in-task
> 
> 
> What's wrong with the filtersfile option of of the 
> <filterset> datatype?
> 
>     http://jakarta.apache.org/ant/manual/CoreTypes/filterset.html
> ----- Original Message -----
> From: "Nigel Magnay" <Nigel.Magnay@Parsec.co.uk>
> To: "'Ant Developers List'" <ant-dev@jakarta.apache.org>
> Sent: Monday, March 25, 2002 11:22 AM
> Subject: ? [Bug 7320] New: - Suggestion: new attribute in replace
> built-in-task
> 
> 
> >
> > This is interesting - I have a very similar requirement, but I'm not
> > sure this is the best way of doing it.
> >
> > I have a number of 'template' files that I use when building a
> > 'distribution'
> > for my product. These contain tags that I wish to have replaced. For
> > example,
> > I have something like
> >
> > sysConfig.ini
> > serverLdapHost=@config.ldapHost@
> >
> > The key things are that
> > 1) I don't want my build file knowing about which properties I may
> > want to replace. Just 'everything that is a valid property'. Thus
> > my programmers can know all they need to do is update the template
> > and, say, a properties file for that target.
> > 2) I want to build up some properties in my build file as a part
> > of other properties.
> > 3) I tend to do this 'en-masse'. I have a 'templates' directory
> > that I specialise all in one go.
> >
> > The way I have done it is to duplicate the 'Copy' task and called
> > it 'TranslateCopy'. Strikes me that a better way to do this would
> > be to have another filter definition, that you could tell it the
> > 'start' and 'end' tokens to treat as property delimiters in files,
> > and it would transform any properties it sees.
> >
> >
> > Is there another way? If not, I could write the patch..
> >
> >
> > Nigel
> >
> >
> > > -----Original Message-----
> > > From: bugzilla@apache.org [mailto:bugzilla@apache.org]
> > > Sent: 21 March 2002 13:33
> > > To: ant-dev@jakarta.apache.org
> > > Subject: DO NOT REPLY [Bug 7320] New: - Suggestion: new 
> attribute in
> > > replace built-in-task
> > >
> > >
> > > DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG
> > > RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
> > > <http://nagoya.apache.org/bugzilla/show_bug.cgi?id=7320>.
> > > ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND
> > > INSERTED IN THE BUG DATABASE.
> > >
> > > http://nagoya.apache.org/bugzilla/show_bug.cgi?id=7320
> > >
> > > Suggestion: new attribute in replace built-in-task
> > >
> > >            Summary: Suggestion: new attribute in replace 
> built-in-task
> > >            Product: Ant
> > >            Version: 1.4.1
> > >           Platform: Other
> > >         OS/Version: Other
> > >             Status: NEW
> > >           Severity: Enhancement
> > >           Priority: Other
> > >          Component: Core tasks
> > >         AssignedTo: ant-dev@jakarta.apache.org
> > >         ReportedBy: Wolfgang.Jakel@lutzwolf.de
> > >
> > >
> > > The ant 'replace' built-in-task supports multiple
> > > <replacefilters>, but I see
> > > no way to define the tokens outside the build.xml. Especially
> > > I have the task
> > > to read a property file with each key interpreted as token
> > > and replace the key
> > > with his value in a number of files.
> > > It is convenient to indroduce a new attribute
> > > 'replaceFilterFile' reading a
> > > valid property file and create for each key-value pair 
> internally a
> > > <replacefilter>.
> > > I modified the file
> > > /src/main/org/apache/tools/ant/taskdefs/Replace.java.
> > > See the code below and look at the variable replaceFilterFile
> > > to see what I
> > > did. I think this feature is of some general interest.
> > > Anyway, the modification works fine for my purposes.
> > >
> > >
> > > /*
> > >  * The Apache Software License, Version 1.1
> > >  *
> > >  * Copyright (c) 1999 The Apache Software Foundation.  All rights
> > >  * reserved.
> > >  *
> > >  * Redistribution and use in source and binary forms, 
> with or without
> > >  * modification, are permitted provided that the 
> following conditions
> > >  * are met:
> > >  *
> > >  * 1. Redistributions of source code must retain the 
> above copyright
> > >  *    notice, this list of conditions and the following 
> disclaimer.
> > >  *
> > >  * 2. Redistributions in binary form must reproduce the above
> > > copyright
> > >  *    notice, this list of conditions and the following 
> disclaimer in
> > >  *    the documentation and/or other materials provided with the
> > >  *    distribution.
> > >  *
> > >  * 3. The end-user documentation included with the 
> redistribution, if
> > >  *    any, must include the following acknowlegement:
> > >  *       "This product includes software developed by the
> > >  *        Apache Software Foundation (http://www.apache.org/)."
> > >  *    Alternately, this acknowlegement may appear in the
> > > software itself,
> > >  *    if and wherever such third-party acknowlegements
> > > normally appear.
> > >  *
> > >  * 4. The names "The Jakarta Project", "Ant", and "Apache Software
> > >  *    Foundation" must not be used to endorse or promote
> > > products derived
> > >  *    from this software without prior written permission.
> > > For written
> > >  *    permission, please contact apache@apache.org.
> > >  *
> > >  * 5. Products derived from this software may not be 
> called "Apache"
> > >  *    nor may "Apache" appear in their names without prior written
> > >  *    permission of the Apache Group.
> > >  *
> > >  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 
> OR IMPLIED
> > >  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
> WARRANTIES
> > >  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > >  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE 
> FOUNDATION OR
> > >  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
> INCIDENTAL,
> > >  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
> (INCLUDING, BUT NOT
> > >  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
> SERVICES; LOSS OF
> > >  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
> HOWEVER CAUSED AND
> > >  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
> STRICT LIABILITY,
> > >  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
> ANY WAY OUT
> > >  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
> POSSIBILITY OF
> > >  * SUCH DAMAGE.
> > >  *
> > > 
> ====================================================================
> > >  *
> > >  * This software consists of voluntary contributions made by many
> > >  * individuals on behalf of the Apache Software 
> Foundation.  For more
> > >  * information on the Apache Software Foundation, please see
> > >  * <http://www.apache.org/>.
> > >  */
> > >
> > > package org.apache.tools.ant.taskdefs;
> > >
> > > import org.apache.tools.ant.*;
> > > import org.apache.tools.ant.taskdefs.*;
> > > import java.io.*;
> > > import java.util.*;
> > >
> > > /**
> > >  * Replaces all occurrences of one or more string tokens 
> with given
> > >  * values in the indicated files. Each value can be 
> either a string
> > >  * or the value of a property available in a designated 
> property file.
> > >  *
> > >  * @author Stefano Mazzocchi <a
> > > href="mailto:stefano@apache.org">stefano@apache.org</a>
> > >  * @author <a href="mailto:erik@desknetinc.com">Erik 
> Langenbach</a>
> > >  */
> > > public class Replace extends MatchingTask {
> > >
> > >     private File src = null;
> > >     private NestedString token = null;
> > >     private NestedString value = new NestedString();
> > >
> > >     private File propertyFile = null;
> > >     private File replaceFilterFile = null;
> > >     private Properties properties = null;
> > >     private Vector replacefilters = new Vector();
> > >
> > >     private File dir = null;
> > >
> > >     private int fileCount;
> > >     private int replaceCount;
> > >     private boolean summary = false;
> > >
> > >     //Inner class
> > >     public class NestedString {
> > >
> > >         private StringBuffer buf = new StringBuffer();
> > >
> > >         public void addText(String val) {
> > >             buf.append(val);
> > >         }
> > >
> > >         public String getText() {
> > >             return buf.toString();
> > >         }
> > >     }
> > >
> > >     //Inner class
> > >     public class Replacefilter
> > >     {
> > >         private String token;
> > >         private String value;
> > >         private String property;
> > >
> > >         public void validate() throws BuildException {
> > >             //Validate mandatory attributes
> > >             if (token == null) {
> > >                 String message = "token is a mandatory
> > > attribute " + "of
> > > replacefilter.";
> > >                 throw new BuildException(message);
> > >             }
> > >
> > >             if ("".equals(token)) {
> > >                 String message ="The token attribute must not
> > > be an empty
> > > string.";
> > >                 throw new BuildException(message);
> > >             }
> > >
> > >             //value and property are mutually exclusive attributes
> > >             if ((value != null) && (property != null)) {
> > >                 String message = "Either value or property "
> > > + "can be
> > > specified, but a replacefilter " + "element cannot have both.";
> > >                 throw new BuildException(message);
> > >             }
> > >
> > >             if ((property != null)) {
> > >                 //the property attribute must have access to
> > > a property file
> > >                 if (propertyFile == null) {
> > >                     String message = "The replacefilter's
> > > property attribute "
> > > + "can only be used with the replacetask's " + "propertyFile
> > > attribute.";
> > >                     throw new BuildException(message);
> > >                 }
> > >
> > >                 //Make sure property exists in property file
> > >                 if (properties == null ||
> > >                         properties.getProperty(property) 
> == null) {
> > >                     String message = "property \"" + property
> > > + "\" was not
> > > found in " + propertyFile.getPath();
> > >                     throw new BuildException(message);
> > >                 }
> > >             }
> > >         }
> > >
> > >         public String getReplaceValue()
> > >         {
> > >             if (property != null) {
> > >                 return (String)properties.getProperty(property);
> > >             }
> > >             else if (value != null) {
> > >                 return value;
> > >             }
> > >             else if (Replace.this.value != null) {
> > >                 return Replace.this.value.getText();
> > >             }
> > >             else {
> > >                 //Default is empty string
> > >                 return new String("");
> > >             }
> > >         }
> > >
> > >         public void setToken(String token) {
> > >             this.token = token;
> > >         }
> > >
> > >         public String getToken() {
> > >             return token;
> > >         }
> > >
> > >         public void setValue(String value) {
> > >             this.value = value;
> > >         }
> > >
> > >         public String getValue() {
> > >             return value;
> > >         }
> > >
> > >         public void setProperty(String property) {
> > >             this.property = property;
> > >         }
> > >
> > >         public String getProperty() {
> > >             return property;
> > >         }
> > >     }
> > >
> > >     /**
> > >      * Do the execution.
> > >      */
> > >     public void execute() throws BuildException {
> > >
> > >         if (replaceFilterFile != null) {
> > >             Properties properties = 
> getProperties(replaceFilterFile);
> > >             Enumeration enum = properties.keys();
> > >             while(enum.hasMoreElements()){
> > >                String token =  enum.nextElement().toString();
> > >                Replacefilter replaceFilter = 
> createReplacefilter();
> > >                replaceFilter.setToken(token);
> > >                
> replaceFilter.setValue(properties.getProperty(token));
> > >             }
> > >         }
> > >
> > >         validateAttributes();
> > >
> > >         if (propertyFile != null) {
> > >             properties = getProperties(propertyFile);
> > >         }
> > >
> > >
> > >         validateReplacefilters();
> > >         fileCount = 0;
> > >         replaceCount = 0;
> > >
> > >         if (src != null) {
> > >             processFile(src);
> > >         }
> > >
> > >         if (dir != null) {
> > >             DirectoryScanner ds = super.getDirectoryScanner(dir);
> > >             String[] srcs = ds.getIncludedFiles();
> > >
> > >             for(int i=0; i<srcs.length; i++) {
> > >                 File file = new File(dir,srcs[i]);
> > >                 processFile(file);
> > >             }
> > >         }
> > >
> > >         if (summary) {
> > >             log("Replaced " + replaceCount + " occurrences in
> > > " + fileCount + "
> > > files.", Project.MSG_INFO);
> > >         }
> > >     }
> > >
> > >     /**
> > >      * Validate attributes provided for this task in .xml 
> build file.
> > >      *
> > >      * @exception BuildException if any supplied attribute is
> > > invalid or any
> > >      * mandatory attribute is missing
> > >      */
> > >     public void validateAttributes() throws BuildException {
> > >         if (src == null && dir == null) {
> > >             String message = "Either the file or the dir
> > > attribute " + "must be
> > > specified";
> > >             throw new BuildException(message, location);
> > >         }
> > >         if (propertyFile != null && !propertyFile.exists()) {
> > >             String message = "Property file " +
> > > propertyFile.getPath() + " does
> > > not exist.";
> > >             throw new BuildException(message, location);
> > >         }
> > >         if (token == null && replacefilters.size() == 0) {
> > >             String message = "Either token or a nested 
> replacefilter "
> > >                 + "must be specified";
> > >             throw new BuildException(message, location);
> > >         }
> > >         if (token != null && "".equals(token.getText())) {
> > >             String message ="The token attribute must not be
> > > an empty string.";
> > >             throw new BuildException(message, location);
> > >         }
> > >     }
> > >
> > >     /**
> > >      * Validate nested elements.
> > >      *
> > >      * @exception BuildException if any supplied attribute is
> > > invalid or any
> > >      * mandatory attribute is missing
> > >      */
> > >     public void validateReplacefilters()
> > >             throws BuildException {
> > >         for (int i = 0; i < replacefilters.size(); i++) {
> > >             Replacefilter element = (Replacefilter)
> > > replacefilters.elementAt(i);
> > >             element.validate();
> > >         }
> > >     }
> > >
> > >     public Properties getProperties(File propertyFile) throws
> > > BuildException {
> > >         Properties properties = new Properties();
> > >
> > >         try {
> > >             properties.load(new FileInputStream(propertyFile));
> > >         }
> > >         catch (FileNotFoundException e) {
> > >             String message = "Property file (" +
> > > propertyFile.getPath() + ")
> > > not found.";
> > >             throw new BuildException(message);
> > >         }
> > >         catch (IOException e) {
> > >             String message = "Property file (" +
> > > propertyFile.getPath() + ")
> > > cannot be loaded.";
> > >             throw new BuildException(message);
> > >         }
> > >
> > >         return properties;
> > >     }
> > >
> > >     /**
> > >      * Perform the replacement on the given file.
> > >      *
> > >      * The replacement is performed on a temporary file which then
> > >      * replaces the original file.
> > >      *
> > >      * @param src the source file
> > >      */
> > >     private void processFile(File src) throws BuildException {
> > >         if (!src.exists()) {
> > >             throw new BuildException("Replace: source file "
> > > + src.getPath()
> > > + " doesn't exist", location);
> > >         }
> > >
> > >         File temp = new File(src.getPath() + ".temp");
> > >
> > >         if (temp.exists()) {
> > >             throw new BuildException("Replace: temporary file
> > > " + temp.getPath
> > > () + " already exists", location);
> > >         }
> > >
> > >         try {
> > >             BufferedReader br = new BufferedReader(new
> > > FileReader(src));
> > >             BufferedWriter bw = new BufferedWriter(new
> > > FileWriter(temp));
> > >
> > >             // read the entire file into a StringBuffer
> > >             //   size of work buffer may be bigger than needed
> > >             //   when multibyte characters exist in the 
> source file
> > >             //   but then again, it might be smaller than 
> needed on
> > >             //   platforms like Windows where length 
> can't be trusted
> > >             int fileLengthInBytes = (int)(src.length());
> > >             StringBuffer tmpBuf = new 
> StringBuffer(fileLengthInBytes);
> > >             int readChar = 0;
> > >             int totread = 0;
> > >             while (true) {
> > >                 readChar = br.read();
> > >                 if (readChar < 0) { break; }
> > >                 tmpBuf.append((char)readChar);
> > >                 totread++;
> > >             }
> > >
> > >             // create a String so we can use indexOf
> > >             String buf = tmpBuf.toString();
> > >
> > >             //Preserve original string (buf) so we can
> > > compare the result
> > >             String newString = new String(buf);
> > >
> > >             if (token != null)
> > >             {
> > >                 // line separators in values and tokens are "\n"
> > >                 // in order to compare with the file
> > > contents, replace them
> > >                 // as needed
> > >                 String linesep = 
> System.getProperty("line.separator");
> > >                 String val = stringReplace(value.getText(),
> > > "\n", linesep);
> > >                 String tok = stringReplace(token.getText(),
> > > "\n", linesep);
> > >
> > >                 // for each found token, replace with value
> > >                 log("Replacing in " + src.getPath() + ": " +
> > > token.getText()
> > > + " --> " + value.getText(), Project.MSG_VERBOSE);
> > >                 newString = stringReplace(newString, tok, val);
> > >             }
> > >
> > >             if (replacefilters.size() > 0) {
> > >                 newString = processReplacefilters(newString,
> > > src.getPath());
> > >             }
> > >
> > >             boolean changes = !newString.equals(buf);
> > >             if (changes) {
> > >                 bw.write(newString,0,newString.length());
> > >                 bw.flush();
> > >             }
> > >
> > >             // cleanup
> > >             bw.close();
> > >             br.close();
> > >
> > >             // If there were changes, move the new one to 
> the old one;
> > >             // otherwise, delete the new one
> > >             if (changes) {
> > >                 ++fileCount;
> > >                 src.delete();
> > >                 temp.renameTo(src);
> > >             } else {
> > >                 temp.delete();
> > >             }
> > >         } catch (IOException ioe) {
> > >             ioe.printStackTrace();
> > >             throw new BuildException(ioe, location);
> > >         }
> > >     }
> > >
> > >     private String processReplacefilters(String buffer,
> > > String filename) {
> > >         String newString = new String(buffer);
> > >
> > >         for (int i = 0; i < replacefilters.size(); i++) {
> > >             Replacefilter filter = (Replacefilter)
> > > replacefilters.elementAt(i);
> > >
> > >             //for each found token, replace with value
> > >             log("Replacing in " + filename + ": " +
> > > filter.getToken() + " --> "
> > > + filter.getReplaceValue(), Project.MSG_VERBOSE);
> > >             newString = stringReplace(newString, 
> filter.getToken(),
> > > filter.getReplaceValue());
> > >         }
> > >
> > >         return newString;
> > >     }
> > >
> > >
> > >     /**
> > >      * Set the source file.
> > >      */
> > >     public void setFile(File file) {
> > >         this.src = file;
> > >     }
> > >
> > >     /**
> > >      * Request a summary
> > >      *
> > >      * @param summary true if you would like a summary logged
> > > of the replace
> > > operation
> > >      */
> > >     public void setSummary(boolean summary) {
> > >         this.summary = summary;
> > >     }
> > >
> > >
> > >     /**
> > >      * Set the source files path when using matching tasks.
> > >      */
> > >     public void setDir(File dir) {
> > >         this.dir = dir;
> > >     }
> > >
> > >     /**
> > >      * Set the string token to replace.
> > >      */
> > >     public void setToken(String token) {
> > >         createReplaceToken().addText(token);
> > >     }
> > >
> > >     /**
> > >      * Set the string value to use as token replacement.
> > >      */
> > >     public void setValue(String value) {
> > >         createReplaceValue().addText(value);
> > >     }
> > >
> > >     /**
> > >      * Nested <replacetoken> element.
> > >      */
> > >     public NestedString createReplaceToken() {
> > >         if (token == null) {
> > >             token = new NestedString();
> > >         }
> > >         return token;
> > >     }
> > >
> > >     /**
> > >      * Nested <replacevalue> element.
> > >      */
> > >     public NestedString createReplaceValue() {
> > >         return value;
> > >     }
> > >
> > >     /**
> > >      * Sets a file to be searched for property values.
> > >      */
> > >     public void setPropertyFile(File filename) {
> > >         propertyFile = filename;
> > >     }
> > >
> > >     /**
> > >      * Sets a file to be searched for property values.
> > >      */
> > >     public void setReplaceFilterFile(File filename) {
> > >         replaceFilterFile = filename;
> > >     }
> > >
> > >
> > >
> > >     /**
> > >      * Add nested <replacefilter> element.
> > >      */
> > >     public Replacefilter createReplacefilter() {
> > >         Replacefilter filter = new Replacefilter();
> > >         replacefilters.addElement(filter);
> > >         return filter;
> > >     }
> > >
> > >     /**
> > >      * Replace occurrences of str1 in string str with str2
> > >      */
> > >     private String stringReplace(String str, String str1,
> > > String str2) {
> > >         StringBuffer ret = new StringBuffer();
> > >         int start = 0;
> > >         int found = str.indexOf(str1);
> > >         while (found >= 0) {
> > >             // write everything up to the found str1
> > >             if (found > start) {
> > >                 ret.append(str.substring(start, found));
> > >             }
> > >
> > >             // write the replacement str2
> > >             if (str2 != null) {
> > >                 ret.append(str2);
> > >             }
> > >
> > >             // search again
> > >             start = found + str1.length();
> > >             found = str.indexOf(str1,start);
> > >             ++replaceCount;
> > >         }
> > >
> > >         // write the remaining characters
> > >         if (str.length() > start) {
> > >             ret.append(str.substring(start, str.length()));
> > >         }
> > >
> > >         return ret.toString();
> > >     }
> > >
> > > }
> > >
> > > --
> > > To unsubscribe, e-mail:
> > > <mailto:ant-dev-unsubscribe@jakarta.apache.org>
> > > For additional commands, e-mail:
> > > <mailto:ant-dev-help@jakarta.apache.org>
> > >
> >
> > --
> > To unsubscribe, e-mail:   
> <mailto:ant-dev-unsubscribe@jakarta.apache.org>
> > For additional commands, e-mail: 
> <mailto:ant-dev-help@jakarta.apache.org>
> >
> >
> 
> 
> --
> To unsubscribe, e-mail:   
> <mailto:ant-dev-unsubscribe@jakarta.apache.org>
> For additional commands, e-mail: 
> <mailto:ant-dev-help@jakarta.apache.org>
> 

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message