PR: 3955 Submitted by: Erik Hatcher <jakarta-ant@ehatchersolutions.com> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269802 13f79535-47bb-0310-9956-ffa450edef68master
@@ -56,7 +56,7 @@ are lost. Work is being done to make this task a bit more "human friendly& | |||||
<h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
<h4><a name="entryElement">Entry</a></h4> | <h4><a name="entryElement">Entry</a></h4> | ||||
<p>Use nested <code><entry></code> | <p>Use nested <code><entry></code> | ||||
elements to specify actual modifcations to the property file itself</p> | |||||
elements to specify actual modifcations to the property file itself.</p> | |||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
<td valign="top"><b>Attribute</b></td> | <td valign="top"><b>Attribute</b></td> | ||||
@@ -71,8 +71,14 @@ elements to specify actual modifcations 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">Yes</td> | |||||
<td valign="top" align="center" rowspan="2">At least one must be specified</td> | |||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">default</td> | |||||
<td valign="top">Initial value to set for a property if it is not | |||||
already defined in the property file.<br> | |||||
For type date, two additional keywords are allowed: "now" or "never".</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">type</td> | <td valign="top">type</td> | ||||
<td valign="top">Regard the value as : int, date or string (default)</td> | <td valign="top">Regard the value as : int, date or string (default)</td> | ||||
@@ -84,13 +90,6 @@ elements to specify actual modifcations to the property file itself</p> | |||||
</td> | </td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">default</td> | |||||
<td valign="top">Initial value to set for a property if it is not | |||||
already defined in the property file.<br> | |||||
For type date, two additional keywords are allowed: "now" or "never".</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">pattern</td> | <td valign="top">pattern</td> | ||||
<td valign="top">For int and date type only. If present, Values will | <td valign="top">For int and date type only. If present, Values will | ||||
@@ -98,6 +97,23 @@ elements to specify actual modifcations to the property file itself</p> | |||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
</table> | </table> | ||||
<p>The rules used when setting a property value are shown below. The | |||||
operation occurs <b>after</b> these rules are considered.</p> | |||||
<ul> | |||||
<li>If only value is specified, the property is set to it regardless of its | |||||
previous value.</li> | |||||
<li>If only default is specified and the property previously existed in the | |||||
property file, it is unchanged.</li> | |||||
<li>If only default is specified and the property did not exist in the | |||||
property file, the property is set to default.</li> | |||||
<li>If value and default are both specified and the property previously | |||||
existed in the property file, the property is set to value.</li> | |||||
<li>If value and default are both specified and the property did not exist in | |||||
the property file, the property is set to default.</li> | |||||
</ul> | |||||
<p> </p> | |||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<p>The following changes the my.properties file. Assume my.properties look like:</p> | <p>The following changes the my.properties file. Assume my.properties look like:</p> | ||||
@@ -153,4 +169,4 @@ Concatenation of strings :</p> | |||||
<p>Each time called, a "." will be appended to "progress" | <p>Each time called, a "." will be appended to "progress" | ||||
</p> | </p> | ||||
</body> | </body> | ||||
</html> | |||||
</html> |
@@ -18,6 +18,9 @@ | |||||
<entry key="firstname" value="${firstname}" /> | <entry key="firstname" value="${firstname}" /> | ||||
<entry key="lastname" value="${lastname}" /> | <entry key="lastname" value="${lastname}" /> | ||||
<entry key="email" value="${email}" /> | <entry key="email" value="${email}" /> | ||||
<entry key="phone" default="${phone}" /> | |||||
<entry key="age" default="${age}" type="int"/> | |||||
<entry key="date" default="${date}" type="date"/> | |||||
</propertyfile> | </propertyfile> | ||||
</target> | </target> |
@@ -307,7 +307,7 @@ public class PropertyFile extends Task | |||||
private String m_key = null; | private String m_key = null; | ||||
private int m_type = Type.STRING_TYPE; | private int m_type = Type.STRING_TYPE; | ||||
private int m_operation = Operation.EQUALS_OPER; | private int m_operation = Operation.EQUALS_OPER; | ||||
private String m_value ="1"; | |||||
private String m_value = ""; | |||||
private String m_default = null; | private String m_default = null; | ||||
private String m_pattern = null; | private String m_pattern = null; | ||||
@@ -394,6 +394,21 @@ public class PropertyFile extends Task | |||||
if (m_pattern == null) m_pattern = "yyyy/MM/dd HH:mm"; | if (m_pattern == null) m_pattern = "yyyy/MM/dd HH:mm"; | ||||
DateFormat fmt = new SimpleDateFormat(m_pattern); | DateFormat fmt = new SimpleDateFormat(m_pattern); | ||||
// special case | |||||
if (m_default != null && | |||||
NOW_VALUE_.equals(m_default.toLowerCase()) && | |||||
(m_operation == Operation.INCREMENT_OPER || | |||||
m_operation == Operation.DECREMENT_OPER) ) { | |||||
oldValue = null; | |||||
} | |||||
if (oldValue != null) { | |||||
try { | |||||
value.setTime(fmt.parse(oldValue)); | |||||
} | |||||
catch (ParseException pe) { /* swollow */ } | |||||
} | |||||
if (m_value != null) { | if (m_value != null) { | ||||
if (NOW_VALUE_.equals(m_value.toLowerCase())) { | if (NOW_VALUE_.equals(m_value.toLowerCase())) { | ||||
value.setTime(new Date()); | value.setTime(new Date()); | ||||
@@ -421,37 +436,22 @@ public class PropertyFile extends Task | |||||
} | } | ||||
} | } | ||||
// special case | |||||
if (m_default != null && | |||||
NOW_VALUE_.equals(m_default.toLowerCase()) && | |||||
(m_operation == Operation.INCREMENT_OPER || | |||||
m_operation == Operation.DECREMENT_OPER) ) { | |||||
oldValue = null; | |||||
} | |||||
if (oldValue != null) { | |||||
try { | |||||
newValue.setTime(fmt.parse(oldValue)); | |||||
if (m_default != null && oldValue == null) { | |||||
if (NOW_VALUE_.equals(m_default.toLowerCase())) { | |||||
value.setTime(new Date()); | |||||
} | } | ||||
catch (ParseException pe) { /* swollow */ } | |||||
} | |||||
else { | |||||
if (m_default != null) { | |||||
if (NOW_VALUE_.equals(m_default.toLowerCase())) { | |||||
newValue.setTime(new Date()); | |||||
} | |||||
else if (NULL_VALUE_.equals(m_default.toLowerCase())) { | |||||
newValue = null; | |||||
} | |||||
else { | |||||
try { | |||||
newValue.setTime(fmt.parse(m_default)); | |||||
} | |||||
catch (ParseException pe) { /* swollow */ } | |||||
else if (NULL_VALUE_.equals(m_default.toLowerCase())) { | |||||
value = null; | |||||
} | |||||
else { | |||||
try { | |||||
value.setTime(fmt.parse(m_default)); | |||||
} | } | ||||
catch (ParseException pe) { /* swollow */ } | |||||
} | } | ||||
} | } | ||||
if (m_operation == Operation.EQUALS_OPER) { | if (m_operation == Operation.EQUALS_OPER) { | ||||
newValue = value; | newValue = value; | ||||
} | } | ||||
@@ -491,23 +491,23 @@ public class PropertyFile extends Task | |||||
DecimalFormat fmt = (m_pattern != null) ? new DecimalFormat(m_pattern) | DecimalFormat fmt = (m_pattern != null) ? new DecimalFormat(m_pattern) | ||||
: new DecimalFormat(); | : new DecimalFormat(); | ||||
if (m_value != null) { | |||||
if (oldValue != null) { | |||||
try { | try { | ||||
value = fmt.parse(m_value).intValue(); | |||||
value = fmt.parse(oldValue).intValue(); | |||||
} | } | ||||
catch (NumberFormatException nfe) { /* swollow */ } | catch (NumberFormatException nfe) { /* swollow */ } | ||||
catch (ParseException pe) { /* swollow */ } | catch (ParseException pe) { /* swollow */ } | ||||
} | } | ||||
if (oldValue != null) { | |||||
if (m_value != null) { | |||||
try { | try { | ||||
newValue = fmt.parse(oldValue).intValue(); | |||||
value = fmt.parse(m_value).intValue(); | |||||
} | } | ||||
catch (NumberFormatException nfe) { /* swollow */ } | catch (NumberFormatException nfe) { /* swollow */ } | ||||
catch (ParseException pe) { /* swollow */ } | catch (ParseException pe) { /* swollow */ } | ||||
} | } | ||||
else if (m_default != null) { | |||||
if (m_default != null && oldValue == null) { | |||||
try { | try { | ||||
newValue = fmt.parse(m_default).intValue(); | |||||
value = fmt.parse(m_default).intValue(); | |||||
} | } | ||||
catch (NumberFormatException nfe) { /* swollow */ } | catch (NumberFormatException nfe) { /* swollow */ } | ||||
catch (ParseException pe) { /* swollow */ } | catch (ParseException pe) { /* swollow */ } | ||||
@@ -537,16 +537,21 @@ public class PropertyFile extends Task | |||||
String value = ""; | String value = ""; | ||||
String newValue = ""; | String newValue = ""; | ||||
// the order of events is, of course, very important here | |||||
// default initially to the old value | |||||
if (oldValue != null) { | |||||
value = oldValue; | |||||
} | |||||
// but if a value is specified, use it | |||||
if (m_value != null) { | if (m_value != null) { | ||||
value = m_value; | value = m_value; | ||||
} | } | ||||
if (oldValue != null) { | |||||
newValue = oldValue; | |||||
} | |||||
else if (m_default != null) { | |||||
newValue = m_default; | |||||
// even if value is specified, ignore it and set to the default | |||||
// value if it is specified and there is no previous value | |||||
if (m_default != null && oldValue == null) { | |||||
value = m_default; | |||||
} | } | ||||
if (m_operation == Operation.EQUALS_OPER) { | if (m_operation == Operation.EQUALS_OPER) { | ||||
newValue = value; | newValue = value; | ||||
} | } | ||||
@@ -555,7 +560,7 @@ public class PropertyFile extends Task | |||||
} | } | ||||
m_value = newValue; | m_value = newValue; | ||||
} | } | ||||
/** | /** | ||||
* Check if parameter combinations can be supported | * Check if parameter combinations can be supported | ||||
*/ | */ | ||||
@@ -564,8 +569,8 @@ public class PropertyFile extends Task | |||||
m_operation == Operation.DECREMENT_OPER) { | m_operation == Operation.DECREMENT_OPER) { | ||||
throw new BuildException("- is not suported for string properties (key:" + m_key + ")"); | throw new BuildException("- is not suported for string properties (key:" + m_key + ")"); | ||||
} | } | ||||
if (m_value == null) { | |||||
throw new BuildException("value is mandatory (key:" + m_key + ")"); | |||||
if (m_value == null && m_default == null) { | |||||
throw new BuildException("value and/or default must be specified (key:" + m_key + ")"); | |||||
} | } | ||||
if (m_key == null) { | if (m_key == null) { | ||||
throw new BuildException("key is mandatory"); | throw new BuildException("key is mandatory"); | ||||
@@ -101,27 +101,33 @@ public class PropertyFileTest extends TaskdefsTest { | |||||
* update properties that are already defined- | * update properties that are already defined- | ||||
*/ | */ | ||||
public void testUpdatesExistingProperties() throws Exception { | public void testUpdatesExistingProperties() throws Exception { | ||||
FileInputStream beforeUpdateFile = new FileInputStream(testPropsFilePath); | |||||
Properties beforeUpdate = new Properties(); | |||||
beforeUpdate.load(beforeUpdateFile); | |||||
Properties beforeUpdate = getTestProperties(); | |||||
assertEquals(FNAME, beforeUpdate.getProperty(FNAME_KEY)); | assertEquals(FNAME, beforeUpdate.getProperty(FNAME_KEY)); | ||||
assertEquals(LNAME, beforeUpdate.getProperty(LNAME_KEY)); | assertEquals(LNAME, beforeUpdate.getProperty(LNAME_KEY)); | ||||
assertEquals(EMAIL, beforeUpdate.getProperty(EMAIL_KEY)); | assertEquals(EMAIL, beforeUpdate.getProperty(EMAIL_KEY)); | ||||
beforeUpdateFile.close(); | |||||
assertEquals(null, beforeUpdate.getProperty(PHONE_KEY)); | |||||
assertEquals(null, beforeUpdate.getProperty(AGE_KEY)); | |||||
assertEquals(null, beforeUpdate.getProperty(DATE_KEY)); | |||||
// ask ant to update the properties... | // ask ant to update the properties... | ||||
executeTarget("update-existing-properties"); | executeTarget("update-existing-properties"); | ||||
FileInputStream afterUpdateFile = new FileInputStream(testPropsFilePath); | |||||
Properties afterUpdate = new Properties(); | |||||
afterUpdate.load(afterUpdateFile); | |||||
Properties afterUpdate = getTestProperties(); | |||||
assertEquals(NEW_FNAME, afterUpdate.getProperty(FNAME_KEY)); | assertEquals(NEW_FNAME, afterUpdate.getProperty(FNAME_KEY)); | ||||
assertEquals(NEW_LNAME, afterUpdate.getProperty(LNAME_KEY)); | assertEquals(NEW_LNAME, afterUpdate.getProperty(LNAME_KEY)); | ||||
assertEquals(NEW_EMAIL, afterUpdate.getProperty(EMAIL_KEY)); | assertEquals(NEW_EMAIL, afterUpdate.getProperty(EMAIL_KEY)); | ||||
afterUpdateFile.close(); | |||||
assertEquals(NEW_PHONE, afterUpdate.getProperty(PHONE_KEY)); | |||||
assertEquals(NEW_AGE, afterUpdate.getProperty(AGE_KEY)); | |||||
assertEquals(NEW_DATE, afterUpdate.getProperty(DATE_KEY)); | |||||
} | } | ||||
private Properties getTestProperties() throws Exception { | |||||
Properties testProps = new Properties(); | |||||
FileInputStream propsFile = new FileInputStream(testPropsFilePath); | |||||
testProps.load(propsFile); | |||||
propsFile.close(); | |||||
return testProps; | |||||
} | |||||
private void initTestPropFile() throws Exception { | private void initTestPropFile() throws Exception { | ||||
@@ -142,6 +148,9 @@ public class PropertyFileTest extends TaskdefsTest { | |||||
buildProps.put(FNAME_KEY, NEW_FNAME); | buildProps.put(FNAME_KEY, NEW_FNAME); | ||||
buildProps.put(LNAME_KEY, NEW_LNAME); | buildProps.put(LNAME_KEY, NEW_LNAME); | ||||
buildProps.put(EMAIL_KEY, NEW_EMAIL); | buildProps.put(EMAIL_KEY, NEW_EMAIL); | ||||
buildProps.put(PHONE_KEY, NEW_PHONE); | |||||
buildProps.put(AGE_KEY, NEW_AGE); | |||||
buildProps.put(DATE_KEY, NEW_DATE); | |||||
FileOutputStream fos = new FileOutputStream(buildPropsFilePath); | FileOutputStream fos = new FileOutputStream(buildPropsFilePath); | ||||
buildProps.save(fos, null); | buildProps.save(fos, null); | ||||
@@ -153,7 +162,7 @@ public class PropertyFileTest extends TaskdefsTest { | |||||
File tempFile = new File(testPropsFilePath); | File tempFile = new File(testPropsFilePath); | ||||
tempFile.delete(); | tempFile.delete(); | ||||
tempFile = null; | tempFile = null; | ||||
tempFile = new File(buildPropsFilePath); | tempFile = new File(buildPropsFilePath); | ||||
tempFile.delete(); | tempFile.delete(); | ||||
tempFile = null; | tempFile = null; | ||||
@@ -162,13 +171,13 @@ public class PropertyFileTest extends TaskdefsTest { | |||||
private static final String | private static final String | ||||
projectFilePath = "src/etc/testcases/taskdefs/propertyfile.xml", | |||||
projectFilePath = "src/etc/testcases/taskdefs/optional/propertyfile.xml", | |||||
testPropertyFile = "propertyfile.test.properties", | testPropertyFile = "propertyfile.test.properties", | ||||
testPropertyFileKey = "test.propertyfile", | testPropertyFileKey = "test.propertyfile", | ||||
testPropsFilePath = "src/etc/testcases/taskdefs/" + testPropertyFile, | |||||
testPropsFilePath = "src/etc/testcases/taskdefs/optional/" + testPropertyFile, | |||||
buildPropsFilePath = "src/etc/testcases/taskdefs/propertyfile.build.properties", | |||||
buildPropsFilePath = "src/etc/testcases/taskdefs/optional/propertyfile.build.properties", | |||||
FNAME = "Bruce", | FNAME = "Bruce", | ||||
NEW_FNAME = "Clark", | NEW_FNAME = "Clark", | ||||
@@ -180,6 +189,15 @@ public class PropertyFileTest extends TaskdefsTest { | |||||
EMAIL = "incredible@hulk.com", | EMAIL = "incredible@hulk.com", | ||||
NEW_EMAIL = "kc@superman.com", | NEW_EMAIL = "kc@superman.com", | ||||
EMAIL_KEY = "email"; | |||||
EMAIL_KEY = "email", | |||||
NEW_PHONE = "(520) 555-1212", | |||||
PHONE_KEY = "phone", | |||||
NEW_AGE = "30", | |||||
AGE_KEY = "age", | |||||
NEW_DATE = "2001/01/01 12:45", | |||||
DATE_KEY = "date"; | |||||
} | } | ||||