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"/> | ||||