git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@959019 13f79535-47bb-0310-9956-ffa450edef68master
@@ -32,6 +32,14 @@ Changes that could break older environments: | |||||
onMissingExtensionPoint attribute. | onMissingExtensionPoint attribute. | ||||
Bugzilla Report 49473. | Bugzilla Report 49473. | ||||
* When using <property file="..." prefix="..."/> properties defined | |||||
inside the same file will only get used in expansions if the ${} | |||||
reference uses the same prefix. This is different from Ant 1.8.1 | |||||
but is the same behavior Ant 1.8.0 and earlier exhibited. | |||||
A new attribute prefixValues can be used to re-enable the behavior | |||||
of Ant 1.8.1. | |||||
Bugzilla Report 49373. | |||||
Fixed bugs: | Fixed bugs: | ||||
----------- | ----------- | ||||
@@ -33,10 +33,11 @@ Also if the file is missing, the build is halted with an error, rather | |||||
than a warning being printed. | than a warning being printed. | ||||
</p> | </p> | ||||
<p>If you want to simulate <a href="property.html">property</a>'s | |||||
prefix attribute, please use <a | |||||
href="../Types/filterchain.html#prefixlines">prefixlines</a> | |||||
filter.</p> | |||||
<p><strong>Note:</strong> the default value of this | |||||
task's <code>prefixValues</code> attribute is different from the | |||||
default value of the same attribute in | |||||
the <a href="property.html"><code><property></code></a> | |||||
task.</p> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
@@ -78,6 +79,13 @@ filter.</p> | |||||
a "." is appended to the prefix if not specified. <em>Since Ant 1.8.1</em></td> | a "." is appended to the prefix if not specified. <em>Since Ant 1.8.1</em></td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">prefixValues</td> | |||||
<td valign="top">Whether to apply the prefix when expanding the | |||||
right hand side of the properties. | |||||
<em>Since Ant 1.8.2</em></td> | |||||
<td align="center" valign="top">No (default=<tt>true</tt>)</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
@@ -154,6 +154,14 @@ SYSTEM). | |||||
A "." is appended to the prefix if not specified.</td> | A "." is appended to the prefix if not specified.</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">prefixValues</td> | |||||
<td valign="top">Whether to apply the prefix when expanding the | |||||
right hand side of properties loaded using <code>file</code>, | |||||
<code>resource</code>, or <code>url</code>. | |||||
<em>Since Ant 1.8.2</em></td> | |||||
<td align="center" valign="top">No (default=<tt>false</tt>)</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">relative</td> | <td valign="top">relative</td> | ||||
<td valign="top">If set to <tt>true</tt> the relative path | <td valign="top">If set to <tt>true</tt> the relative path | ||||
@@ -198,7 +206,7 @@ to be your home directory. Where the "user.home" property resolves to | |||||
the file system depends on the operating system version and the JVM implementation. | the file system depends on the operating system version and the JVM implementation. | ||||
On Unix based systems, this will map to the user's home directory. On modern Windows | On Unix based systems, this will map to the user's home directory. On modern Windows | ||||
variants, this will most likely resolve to the user's directory in the "Documents | variants, this will most likely resolve to the user's directory in the "Documents | ||||
and Settings" folder. Older windows variants such as Windows 98/ME are less | |||||
and Settings" or "Users" folder. Older windows variants such as Windows 98/ME are less | |||||
predictable, as are other operating system/JVM combinations.</p> | predictable, as are other operating system/JVM combinations.</p> | ||||
<pre> | <pre> | ||||
@@ -247,8 +255,12 @@ project, that team members can customize. | |||||
<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream)">by Sun</a>. | <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream)">by Sun</a>. | ||||
This makes it hard for Team Ant to field bug reports about it. | This makes it hard for Team Ant to field bug reports about it. | ||||
<li>Trailing spaces are not stripped. It may have been what you wanted. | <li>Trailing spaces are not stripped. It may have been what you wanted. | ||||
<li>Want unusual characters? Escape them \u0456 or \" style. | |||||
<li>Ant Properties are expanded in the file. | |||||
<li>Want unusual characters? Escape them \u0456 or \" style. | |||||
<li>Ant Properties are expanded in the file | |||||
<li>If you want to expand properties defined inside the same file and | |||||
you use the prefix attribute of the task, you must use the same | |||||
prefix when expanding the properties or | |||||
set <code>prefixValues</code> to true.</li> | |||||
</ol> | </ol> | ||||
In-file property expansion is very cool. Learn to use it. | In-file property expansion is very cool. Learn to use it. | ||||
<p> | <p> | ||||
@@ -769,7 +769,7 @@ public class Main implements AntMain { | |||||
HashMap props = new HashMap(definedProps); | HashMap props = new HashMap(definedProps); | ||||
new ResolvePropertyMap(project, propertyHelper, | new ResolvePropertyMap(project, propertyHelper, | ||||
propertyHelper.getExpanders()) | propertyHelper.getExpanders()) | ||||
.resolveAllProperties(props, null); | |||||
.resolveAllProperties(props, null, false); | |||||
// set user-define properties | // set user-define properties | ||||
for (Iterator e = props.entrySet().iterator(); e.hasNext(); ) { | for (Iterator e = props.entrySet().iterator(); e.hasNext(); ) { | ||||
@@ -36,6 +36,12 @@ public class ResolvePropertyMap implements GetProperty { | |||||
private final GetProperty master; | private final GetProperty master; | ||||
private Map map; | private Map map; | ||||
private String prefix; | private String prefix; | ||||
// whether properties of the value side of the map should be | |||||
// expanded | |||||
private boolean prefixValues = false; | |||||
// whether the current getProperty call is expanding the key side | |||||
// of the map | |||||
private boolean expandingLHS = true; | |||||
/** | /** | ||||
* Constructor with a master getproperty and a collection of expanders. | * Constructor with a master getproperty and a collection of expanders. | ||||
@@ -59,19 +65,20 @@ public class ResolvePropertyMap implements GetProperty { | |||||
"Property " + name + " was circularly " + "defined."); | "Property " + name + " was circularly " + "defined."); | ||||
} | } | ||||
// if the property has already been set to the name it will | |||||
// have in the end, then return the existing value to ensure | |||||
// properties remain immutable | |||||
String masterPropertyName = name; | |||||
if (prefix != null) { | |||||
masterPropertyName = prefix + name; | |||||
} | |||||
Object masterProperty = master.getProperty(masterPropertyName); | |||||
if (masterProperty != null) { | |||||
return masterProperty; | |||||
} | |||||
try { | try { | ||||
String fullKey = name; | |||||
if (prefix != null && prefixValues) { | |||||
fullKey = prefix + name; | |||||
} | |||||
Object masterValue = expandingLHS | |||||
? null : master.getProperty(fullKey); | |||||
// if the property is defined outside of this map don't | |||||
// consult the map at all. | |||||
if (masterValue != null) { | |||||
return masterValue; | |||||
} | |||||
expandingLHS = false; | |||||
seen.add(name); | seen.add(name); | ||||
return parseProperties.parseProperties((String) map.get(name)); | return parseProperties.parseProperties((String) map.get(name)); | ||||
} finally { | } finally { | ||||
@@ -82,10 +89,10 @@ public class ResolvePropertyMap implements GetProperty { | |||||
/** | /** | ||||
* The action method - resolves all the properties in a map. | * The action method - resolves all the properties in a map. | ||||
* @param map the map to resolve properties in. | * @param map the map to resolve properties in. | ||||
* @deprecated since Ant 1.8.1, use the two-arg method instead. | |||||
* @deprecated since Ant 1.8.2, use the three-arg method instead. | |||||
*/ | */ | ||||
public void resolveAllProperties(Map map) { | public void resolveAllProperties(Map map) { | ||||
resolveAllProperties(map, null); | |||||
resolveAllProperties(map, null, false); | |||||
} | } | ||||
/** | /** | ||||
@@ -93,13 +100,44 @@ public class ResolvePropertyMap implements GetProperty { | |||||
* @param map the map to resolve properties in. | * @param map the map to resolve properties in. | ||||
* @param prefix the prefix the properties defined inside the map | * @param prefix the prefix the properties defined inside the map | ||||
* will finally receive - may be null. | * will finally receive - may be null. | ||||
* @deprecated since Ant 1.8.2, use the three-arg method instead. | |||||
*/ | */ | ||||
public void resolveAllProperties(Map map, String prefix) { | public void resolveAllProperties(Map map, String prefix) { | ||||
this.map = map; // The map gets used in the getProperty callback | |||||
resolveAllProperties(map, null, false); | |||||
} | |||||
/** | |||||
* The action method - resolves all the properties in a map. | |||||
* @param map the map to resolve properties in. | |||||
* @param prefix the prefix the properties defined inside the map | |||||
* will finally receive - may be null. | |||||
* @param prefixValues - whether the prefix will be applied | |||||
* to properties on the value side of the map as well. | |||||
*/ | |||||
public void resolveAllProperties(Map map, String prefix, | |||||
boolean prefixValues) { | |||||
// The map, prefix and prefixValues flag get used in the | |||||
// getProperty callback | |||||
this.map = map; | |||||
this.prefix = prefix; | this.prefix = prefix; | ||||
this.prefixValues = prefixValues; | |||||
for (Iterator i = map.keySet().iterator(); i.hasNext();) { | for (Iterator i = map.keySet().iterator(); i.hasNext();) { | ||||
expandingLHS = true; | |||||
String key = (String) i.next(); | String key = (String) i.next(); | ||||
Object result = getProperty(key); | |||||
// if the property has already been set to the name it | |||||
// will have in the end, then return the existing value to | |||||
// ensure properties remain immutable | |||||
String fullKey = key; | |||||
if (prefix != null) { | |||||
fullKey = prefix + key; | |||||
} | |||||
Object result = master.getProperty(fullKey); | |||||
if (result == null) { | |||||
result = getProperty(key); | |||||
} | |||||
String value = result == null ? "" : result.toString(); | String value = result == null ? "" : result.toString(); | ||||
map.put(key, value); | map.put(key, value); | ||||
} | } | ||||
@@ -66,6 +66,7 @@ public class LoadProperties extends Task { | |||||
* Prefix for loaded properties. | * Prefix for loaded properties. | ||||
*/ | */ | ||||
private String prefix = null; | private String prefix = null; | ||||
private boolean prefixValues = true; | |||||
/** | /** | ||||
* Set the file to load. | * Set the file to load. | ||||
@@ -141,6 +142,16 @@ public class LoadProperties extends Task { | |||||
this.prefix = prefix; | this.prefix = prefix; | ||||
} | } | ||||
/** | |||||
* Whether to apply the prefix when expanding properties on the | |||||
* right hand side of a properties file as well. | |||||
* | |||||
* @since Ant 1.8.2 | |||||
*/ | |||||
public void setPrefixValues(boolean b) { | |||||
prefixValues = b; | |||||
} | |||||
/** | /** | ||||
* load Ant properties from the source file or resource | * load Ant properties from the source file or resource | ||||
* | * | ||||
@@ -189,6 +200,7 @@ public class LoadProperties extends Task { | |||||
Property propertyTask = new Property(); | Property propertyTask = new Property(); | ||||
propertyTask.bindToOwner(this); | propertyTask.bindToOwner(this); | ||||
propertyTask.setPrefix(prefix); | propertyTask.setPrefix(prefix); | ||||
propertyTask.setPrefixValues(prefixValues); | |||||
propertyTask.addProperties(props); | propertyTask.addProperties(props); | ||||
} | } | ||||
} catch (final IOException ioe) { | } catch (final IOException ioe) { | ||||
@@ -94,6 +94,7 @@ public class Property extends Task { | |||||
private boolean valueAttributeUsed = false; | private boolean valueAttributeUsed = false; | ||||
private boolean relative = false; | private boolean relative = false; | ||||
private File basedir; | private File basedir; | ||||
private boolean prefixValues = false; | |||||
protected boolean userProperty; // set read-only properties | protected boolean userProperty; // set read-only properties | ||||
// CheckStyle:VisibilityModifier ON | // CheckStyle:VisibilityModifier ON | ||||
@@ -293,6 +294,26 @@ public class Property extends Task { | |||||
return prefix; | return prefix; | ||||
} | } | ||||
/** | |||||
* Whether to apply the prefix when expanding properties on the | |||||
* right hand side of a properties file as well. | |||||
* | |||||
* @since Ant 1.8.2 | |||||
*/ | |||||
public void setPrefixValues(boolean b) { | |||||
prefixValues = b; | |||||
} | |||||
/** | |||||
* Whether to apply the prefix when expanding properties on the | |||||
* right hand side of a properties file as well. | |||||
* | |||||
* @since Ant 1.8.2 | |||||
*/ | |||||
public boolean getPrefixValues() { | |||||
return prefixValues; | |||||
} | |||||
/** | /** | ||||
* Sets a reference to an Ant datatype | * Sets a reference to an Ant datatype | ||||
* declared elsewhere. | * declared elsewhere. | ||||
@@ -716,7 +737,7 @@ public class Property extends Task { | |||||
getProject(), | getProject(), | ||||
propertyHelper, | propertyHelper, | ||||
propertyHelper.getExpanders()) | propertyHelper.getExpanders()) | ||||
.resolveAllProperties(props, prefix); | |||||
.resolveAllProperties(props, getPrefix(), getPrefixValues()); | |||||
} | } | ||||
} | } |
@@ -93,7 +93,7 @@ y=$${x} | |||||
]]></echo> | ]]></echo> | ||||
<property file="${input}/y.properties" prefix="foo"/> | <property file="${input}/y.properties" prefix="foo"/> | ||||
<!-- passes in Ant 1.8.0 and 1.7.1, fails in 1.8.1 --> | <!-- passes in Ant 1.8.0 and 1.7.1, fails in 1.8.1 --> | ||||
<!--au:assertPropertyEquals name="foo.y" value="x"/--> | |||||
<au:assertPropertyEquals name="foo.y" value="x"/> | |||||
<echo file="${input}/z.properties"><![CDATA[ | <echo file="${input}/z.properties"><![CDATA[ | ||||
x=y | x=y | ||||
y=$${bar.x} | y=$${bar.x} | ||||
@@ -121,8 +121,8 @@ x=3 | |||||
<au:assertPropertyEquals name="foo.x" value="3"/> | <au:assertPropertyEquals name="foo.x" value="3"/> | ||||
</target> | </target> | ||||
<!-- passes in Ant 1.7.1 and 1.8.0, fails in 1.8.1 --> | |||||
<target name="NOtestNestedExpansionDoesntUsePrefix" | |||||
<!-- passes in Ant 1.7.1 and 1.8.0, fails in 1.8.1 --> | |||||
<target name="testNestedExpansionDoesntUsePrefix" | |||||
description="https://issues.apache.org/bugzilla/show_bug.cgi?id=49373"> | description="https://issues.apache.org/bugzilla/show_bug.cgi?id=49373"> | ||||
<mkdir dir="${input}"/> | <mkdir dir="${input}"/> | ||||
<property name="x" value="x"/> | <property name="x" value="x"/> | ||||