git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@806154 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -857,6 +857,8 @@ Other changes: | |||||
| * It is now possible to suppress the "FAILED" lines sent to Ant's | * It is now possible to suppress the "FAILED" lines sent to Ant's | ||||
| logging system via <junit>'s new logFailedTests attribute. | logging system via <junit>'s new logFailedTests attribute. | ||||
| Bugzilla Report 35073. | Bugzilla Report 35073. | ||||
| * <propertyfile> now can delete entries. | |||||
| Changes from Ant 1.7.0 TO Ant 1.7.1 | Changes from Ant 1.7.0 TO Ant 1.7.1 | ||||
| ============================================= | ============================================= | ||||
| @@ -24,26 +24,12 @@ | |||||
| <body> | <body> | ||||
| <h1>PropertyFile</h1> | <h1>PropertyFile</h1> | ||||
| <p>by</p> | |||||
| <!-- Names are in alphabetical order, on last name --> | |||||
| <ul> | |||||
| <li>Thomas Christen (<a href="mailto:chr@active.ch">chr@active.ch</a>)</li> | |||||
| <li>Jeremy Mawson (<a href="mailto:jem@loftinspace.com.au">jem@loftinspace.com/au</a>)</li> | |||||
| </ul> | |||||
| <hr> | |||||
| <h2>Table of Contents</h2> | |||||
| <ul> | |||||
| <li><a href="#introduction">Introduction</a></li> | |||||
| <li><a href="#proptask">PropertyFile Task</a></li> | |||||
| <li><a href="#entryElement">Entry Task</a></li> | |||||
| </ul> | |||||
| <hr> | <hr> | ||||
| <h2><a name="introduction">Introduction</a></h2> | <h2><a name="introduction">Introduction</a></h2> | ||||
| <p>Ant provides an optional task for editing property files. This is very useful | |||||
| <p>Ant provides an optional task for editing property files. This is very useful | |||||
| when wanting to make unattended modifications to configuration files for application | when wanting to make unattended modifications to configuration files for application | ||||
| servers and applications. Currently, the task maintains a working property file with | |||||
| servers and applications. Currently, the task maintains a working property file with | |||||
| the ability to add properties or make changes to existing ones. Comments and layout | the ability to add properties or make changes to existing ones. Comments and layout | ||||
| of the original properties file are preserved.</p> | of the original properties file are preserved.</p> | ||||
| @@ -93,7 +79,7 @@ elements to specify actual modifications to the property file itself.</p> | |||||
| <tr> | <tr> | ||||
| <td valign="top">value</td> | <td valign="top">value</td> | ||||
| <td valign="top">Value to set (=), to add (+) or subtract (-)</td> | <td valign="top">Value to set (=), to add (+) or subtract (-)</td> | ||||
| <td valign="top" align="center" rowspan="2">At least one must be specified</td> | |||||
| <td valign="top" align="center" rowspan="2">At least one must be specified, if <i>operation</i> is not <i>delete</i></td> | |||||
| </tr> | </tr> | ||||
| <tr> | <tr> | ||||
| <td valign="top">default</td> | <td valign="top">default</td> | ||||
| @@ -108,7 +94,14 @@ elements to specify actual modifications to the property file itself.</p> | |||||
| </tr> | </tr> | ||||
| <tr> | <tr> | ||||
| <td valign="top">operation</td> | <td valign="top">operation</td> | ||||
| <td valign="top">"+" or "=" (default) for all datatypes<br>"-" (for date and int only).<br> | |||||
| <td valign="top">One of the following operations:<br><br> | |||||
| <b>for all datatypes:</b><ul> | |||||
| <li>"del" : deletes an entry</li> | |||||
| <li>"+" : adds a value to the existing value</li> | |||||
| <li>"=" : sets a value instead of the existing value (default)</li> | |||||
| </ul><br><b>for date and int only:</b><ul> | |||||
| <li>"-" : subtracts a value from the existing value</li> | |||||
| </ul> | |||||
| </td> | </td> | ||||
| <td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
| </tr> | </tr> | ||||
| @@ -38,7 +38,15 @@ | |||||
| <entry key="age" default="${age}" type="int"/> | <entry key="age" default="${age}" type="int"/> | ||||
| <entry key="date" default="${date}" type="date"/> | <entry key="date" default="${date}" type="date"/> | ||||
| </propertyfile> | </propertyfile> | ||||
| </target> | |||||
| <target name="delete-properties"> | |||||
| <echoproperties/> | |||||
| <propertyfile | |||||
| file="${test.propertyfile}" | |||||
| comment="unit test for the property file task..." > | |||||
| <entry key="firstname" operation="del" /> | |||||
| </propertyfile> | |||||
| </target> | </target> | ||||
| <target name="exercise"> | <target name="exercise"> | ||||
| @@ -85,15 +93,19 @@ | |||||
| </propertyfile> | </propertyfile> | ||||
| <property file="${test.propertyfile}"/> | <property file="${test.propertyfile}"/> | ||||
| </target> | </target> | ||||
| <target name="createfile"> | <target name="createfile"> | ||||
| <echo file="${overwrite.test.propertyfile}"> | <echo file="${overwrite.test.propertyfile}"> | ||||
| foo=3 | foo=3 | ||||
| </echo> | </echo> | ||||
| </target> | </target> | ||||
| <target name="bugDemo1" depends="createfile,bugDemoInit"/> | <target name="bugDemo1" depends="createfile,bugDemoInit"/> | ||||
| <target name="bugDemo2" depends="bugDemoInit"> | <target name="bugDemo2" depends="bugDemoInit"> | ||||
| <property file="${overwrite.test.propertyfile}"/> | <property file="${overwrite.test.propertyfile}"/> | ||||
| </target> | </target> | ||||
| <target name="bugDemoInit"> | <target name="bugDemoInit"> | ||||
| <propertyfile file="${overwrite.test.propertyfile}"> | <propertyfile file="${overwrite.test.propertyfile}"> | ||||
| <entry key="foo" default="0" value="1" operation="+" type="int"/> | <entry key="foo" default="0" value="1" operation="+" type="int"/> | ||||
| @@ -347,6 +347,11 @@ public class PropertyFile extends Task { | |||||
| */ | */ | ||||
| protected void executeOn(Properties props) throws BuildException { | protected void executeOn(Properties props) throws BuildException { | ||||
| checkParameters(); | checkParameters(); | ||||
| if (operation == Operation.DELETE_OPER) { | |||||
| props.remove(key); | |||||
| return; | |||||
| } | |||||
| // type may be null because it wasn't set | // type may be null because it wasn't set | ||||
| String oldValue = (String) props.get(key); | String oldValue = (String) props.get(key); | ||||
| @@ -508,7 +513,7 @@ public class PropertyFile extends Task { | |||||
| throw new BuildException("- is not supported for string " | throw new BuildException("- is not supported for string " | ||||
| + "properties (key:" + key + ")"); | + "properties (key:" + key + ")"); | ||||
| } | } | ||||
| if (value == null && defaultValue == null) { | |||||
| if (value == null && defaultValue == null && operation != Operation.DELETE_OPER) { | |||||
| throw new BuildException("\"value\" and/or \"default\" " | throw new BuildException("\"value\" and/or \"default\" " | ||||
| + "attribute must be specified (key:" + key + ")"); | + "attribute must be specified (key:" + key + ")"); | ||||
| } | } | ||||
| @@ -574,10 +579,12 @@ public class PropertyFile extends Task { | |||||
| public static final int DECREMENT_OPER = 1; | public static final int DECREMENT_OPER = 1; | ||||
| /** = */ | /** = */ | ||||
| public static final int EQUALS_OPER = 2; | public static final int EQUALS_OPER = 2; | ||||
| /** del */ | |||||
| public static final int DELETE_OPER = 3; | |||||
| /** {@inheritDoc}. */ | /** {@inheritDoc}. */ | ||||
| public String[] getValues() { | public String[] getValues() { | ||||
| return new String[] {"+", "-", "="}; | |||||
| return new String[] {"+", "-", "=", "del"}; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -590,6 +597,8 @@ public class PropertyFile extends Task { | |||||
| return INCREMENT_OPER; | return INCREMENT_OPER; | ||||
| } else if ("-".equals(oper)) { | } else if ("-".equals(oper)) { | ||||
| return DECREMENT_OPER; | return DECREMENT_OPER; | ||||
| } else if ("del".equals(oper)) { | |||||
| return DELETE_OPER; | |||||
| } | } | ||||
| return EQUALS_OPER; | return EQUALS_OPER; | ||||
| } | } | ||||
| @@ -93,6 +93,22 @@ public class PropertyFileTest extends BuildFileTest { | |||||
| assertEquals(NEW_AGE, afterUpdate.getProperty(AGE_KEY)); | assertEquals(NEW_AGE, afterUpdate.getProperty(AGE_KEY)); | ||||
| assertEquals(NEW_DATE, afterUpdate.getProperty(DATE_KEY)); | assertEquals(NEW_DATE, afterUpdate.getProperty(DATE_KEY)); | ||||
| } | } | ||||
| public void testDeleteProperties() throws Exception { | |||||
| Properties beforeUpdate = getTestProperties(); | |||||
| assertEquals("Property '" + FNAME_KEY + "' should exist before deleting", | |||||
| FNAME, beforeUpdate.getProperty(FNAME_KEY)); | |||||
| assertEquals("Property '" + LNAME_KEY + "' should exist before deleting", | |||||
| LNAME, beforeUpdate.getProperty(LNAME_KEY)); | |||||
| executeTarget("delete-properties"); | |||||
| Properties afterUpdate = getTestProperties(); | |||||
| assertEquals("Property '" + LNAME_KEY + "' should exist after deleting", | |||||
| LNAME, afterUpdate.getProperty(LNAME_KEY)); | |||||
| assertNull("Property '" + FNAME_KEY + "' should be deleted", | |||||
| afterUpdate.getProperty(FNAME_KEY)); | |||||
| } | |||||
| public void testExerciseDefaultAndIncrement() throws Exception { | public void testExerciseDefaultAndIncrement() throws Exception { | ||||
| executeTarget("exercise"); | executeTarget("exercise"); | ||||