开发者

Using Ant to merge two different properties files

开发者 https://www.devze.com 2023-02-02 05:52 出处:网络
I have a default properties file, and some deployment specific properties files that override certain settings from the default, based on deployment environme开发者_StackOverflow中文版nt. I would like

I have a default properties file, and some deployment specific properties files that override certain settings from the default, based on deployment environme开发者_StackOverflow中文版nt. I would like my Ant build script to merge the two properties files (overwriting default values with deployment specific values), and then output the resulting properties to a new file.

I tried doing it like so but I was unsuccessful:

<target depends="init" name="configure-target-environment">
    <filterset id="application-properties-filterset">
        <filtersfile file="${build.config.path}/${target.environment}/application.properties" />
    </filterset>

    <copy todir="${web-inf.path}/conf" file="${build.config.path}/application.properties" overwrite="true" failonerror="true" >
        <filterset refid="application-properties-filterset" />
    </copy>
</target>


I did it like this:

<property prefix="app.properties" file="custom.application.properties" />
<property prefix="app.properties" file="default.application.properties" />
<echoproperties destfile="application.properties">
   <propertyset>
      <propertyref prefix="app.properties"/>
      <mapper type="glob" from="app.properties.*" to="*"/>
   </propertyset>
</echoproperties>


Perhaps you should look at the concat task of ant for this.


I figured this one out. There needs to be an extra properties file created, with each key/value in the following format: mail.server.host=@mail.server.host@ etc...

Then specify this "template" file to the "file" attribute of the task. Also in the filterset, specify multiple with the least important one listed first.

So it would look like this:

<copy todir="${web-inf.path}/conf" file="${build.config.path}/template.application.properties" overwrite="true" failonerror="true" >
    <filterset refid="application-properties-filterset" />
</copy>


I personally use this:

<copy todir="${web-inf.path}/conf" filtering="true">
  <fileset dir="${build.config.path}" includes="*.properties" /> 
  <filterset>
    <filtersfile file="application-properties-filterset" /> 
  </filterset>
</copy>


The other answers are okay, but I needed one without these limitations:

  • The need for all properties to be specified as templates with @tokens@ (first answer)
  • Property expansion - e.g. I have properties defined as prop2=${prop1} which will get expanded by any solution that loads and echos properties
  • EchoProperties (@user2500146) escapes characters like colons which is annoying for URL properties (not Ant's fault, that's standard Java Properties, which allow : in place of =)
  • Repeated properties from concat-based solutions (this works, because the 2nd definition is ignored, but I didn't want repeats

In the end I had to resort to javascript in a filter, but my solution brings in default properties if and only if they are not defined in the main properties file. It works by loading the main properties with an obscure prefix, then copying it to the destination, then concat'ing the default properties while filtering out any default properties that were loaded in the first step.

You can use this verbatim but will probably want to take out the log statements or change them to debug level, once you're convinced

<!-- merge the main.properties.file with the default.properties.file
     into the output.properties.file (make sure these are defined) -->
<target name="merge">
    <!--Obscure enough prefix to ensure the right props are handled-->
    <property name="prefix" value="__MY_PREFIX__"/>
    <!--Load the main properties so we can tell if the default is needed-->
    <property prefix="${prefix}" file="${main.properties.file}"/>

    <!--Copy the main properties, then append the defaults selectively-->
    <copy file="${main.properties.file}" tofile="${output.properties.file}" overwrite="true"/>
    <concat destfile="${output.properties.file}" append="true">
        <fileset file="${default.properties.file}"/>
        <filterchain>
            <!--Filter out lines with properties that were already in the main properties -->
            <scriptfilter language="javascript"> <![CDATA[
            var line = self.getToken();
            project.log("line: " + line);
            var skipLine = false;
            // lines that do not define properties are concatenated
            if (line.indexOf("=") != -1) {
                // get the property name from the line
                var propName = line.substr(0, line.indexOf('='));
                project.log("line prop: " + propName);
                var loadedPropName = "__MY_PREFIX__" + propName;
                if (project.getProperty(loadedPropName) != null) {
                    project.log("prop has original: " + project.getProperty(loadedPropName));
                   // skip this line, the property is defined
                   skipLine = true;
                }
            }

            if (skipLine) {
                project.log("skipping line: " + line);
                self.setToken(null);
            }
            else {
                // else leave the line in as it was
                project.log("adding default line: " + line);
                self.setToken(line);
            }

]]> </scriptfilter>
        </filterchain>
    </concat>
</target>
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号