Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simulating the Maven2 filter mechanism using Ant

I have a properties file, let say my-file.properties. In addition to that, I have several configuration files for my application where some information must be filled regarding the content of my-file.properties file.

my-file.properties:

application.version=1.0
application.build=42
user.name=foo
user.password=bar

Thus, in my configuration files, I will find some ${application.version}, ${user.name} that will be replaced by their value taken in the properties file...

When I build my application using Maven2, I only need to specify the properties file and say that my resources files are filtered (as in this answer to another problem). However, I need to achieve the same thing by using only Ant.

I've seen that Ant offers a filter task. However, it forces me to use the pattern @property.key@ (i.e. @user.name@ instead of #{user.name}) in my configuration files, which is not acceptable in my case.

How can I solve my problem?

like image 677
Romain Linsolas Avatar asked Aug 05 '09 11:08

Romain Linsolas


2 Answers

I think expandproperties is what you are looking for. This acts just like Maven2's resource filters.


INPUT

For instance, if you have src directory (one of many files):

<link href="${css.files.remote}/css1.css"/>

src/test.txt


PROCESS

And in my ANT build file we have this:

<project default="default">
   <!-- The remote location of any CSS files -->
   <property name="css.files.remote" value="/css/theCSSFiles" />     
   ...
   <target name="ExpandPropertiesTest">

      <mkdir dir="./filtered"/>

      <copy todir="./filtered">
         <filterchain>
            <expandproperties/>
         </filterchain>     

         <fileset dir="./src" />
      </copy>
   </target>
</project>

build.xml


OUTPUT

*When you run the ExpandPropertiesTest target you will have the following in your filtered directory: *

    <link href="/css/theCSSFiles/css1.css"/>

filtered/test.txt

like image 62
leeand00 Avatar answered Oct 13 '22 10:10

leeand00


You can define a custom FilterReader. So you have a couple of choices:

  1. Extend/copy the org.apache.tools.ant.filters.ReplaceTokens class and define a Map property that references another properties file containing all the replacements. This is still a bit of a chore as you have to define all the replacements.
  2. Extend/copy the org.apache.tools.ant.filters.ReplaceTokens class with additional processing that just substitutes the matched token with a version with the correct garnish. Of course you'd have to be really careful where you use this type as it will match anything with the begin and end token.

So in the read() method of ReplaceTokens, replace:

final String replaceWith = (String) hash.get(key.toString());

with a call to a getReplacement() method:

...
final String replaceWith = getReplacement(key.toString);
...

private String getReplacement(String key) {
    //first check if we have a replacement defined
    if(has.containsKey(key)) {
        return (String)hash.get(key);
    }

    //now use our built in rule, use a StringBuilder if you want to be tidy
    return "$" + key + "}";
}

To use this, you'd ensure your class is packaged and on Ant's path and modify your filter:

<filterreader classname="my.custom.filters.ReplaceTokens">
    <!-- Define the begin and end tokens -->
    <param type="tokenchar" name="begintoken" value="$"/>
    <param type="tokenchar" name="endtoken" value="}"/>
    <!--Can still define explicit tokens, any not
    defined explicitly will be replaced by the generic rule -->
</filterreader>
like image 33
Rich Seller Avatar answered Oct 13 '22 11:10

Rich Seller