diff --git a/src/main/org/apache/tools/ant/property/ParseNextProperty.java b/src/main/org/apache/tools/ant/property/ParseNextProperty.java index c39118daa..5e5dfc07d 100644 --- a/src/main/org/apache/tools/ant/property/ParseNextProperty.java +++ b/src/main/org/apache/tools/ant/property/ParseNextProperty.java @@ -22,7 +22,8 @@ import java.text.ParsePosition; import org.apache.tools.ant.Project; /** - * Interface to parse a property. + * Helper for {@link PropertyExpander PropertyExpander} that can be + * used to expand property references to values. * @since Ant 1.8.0 */ public interface ParseNextProperty { diff --git a/src/main/org/apache/tools/ant/property/ParseProperties.java b/src/main/org/apache/tools/ant/property/ParseProperties.java index 7f54bd2fc..b955f6347 100644 --- a/src/main/org/apache/tools/ant/property/ParseProperties.java +++ b/src/main/org/apache/tools/ant/property/ParseProperties.java @@ -24,6 +24,7 @@ import org.apache.tools.ant.Project; /** * Parse properties using a collection of expanders. + * * @since Ant 1.8.0 */ public class ParseProperties implements ParseNextProperty { @@ -53,9 +54,33 @@ public class ParseProperties implements ParseNextProperty { } /** - * Decode properties from a String representation. If the entire - * contents of the String resolve to a single property, that value - * is returned. Otherwise a String is returned. + * Decode properties from a String representation. + * + * + * + *

If the entire contents of value resolves to a + * single property, the looked up property value is returned. + * Otherwise a String is returned that concatenates the + * non-property parts of value and the expanded + * values of the properties that have been found.

* * @param value The string to be scanned for property references. * May be null, in which case this @@ -68,19 +93,20 @@ public class ParseProperties implements ParseNextProperty { if (value == null || "".equals(value)) { return value; } + final int len = value.length(); ParsePosition pos = new ParsePosition(0); Object o = parseNextProperty(value, pos); - if (o != null && pos.getIndex() == value.length()) { + if (o != null && pos.getIndex() >= len) { return o; } - StringBuffer sb = new StringBuffer(value.length() * 2); + StringBuffer sb = new StringBuffer(len * 2); if (o == null) { sb.append(value.charAt(pos.getIndex())); pos.setIndex(pos.getIndex() + 1); } else { sb.append(o); } - while (pos.getIndex() < value.length()) { + while (pos.getIndex() < len) { o = parseNextProperty(value, pos); if (o == null) { sb.append(value.charAt(pos.getIndex())); @@ -94,6 +120,12 @@ public class ParseProperties implements ParseNextProperty { /** * Learn whether a String contains replaceable properties. + * + *

Uses the configured {@link + * org.apache.tools.ant.PropertyHelper.PropertyExpander + * PropertyExpanders} and scans through the string. Returns true + * as soon as any expander finds a property.

+ * * @param value the String to check. * @return true if value contains property notation. */ @@ -101,7 +133,8 @@ public class ParseProperties implements ParseNextProperty { if (value == null) { return false; } - for (ParsePosition pos = new ParsePosition(0); pos.getIndex() < value.length();) { + final int len = value.length(); + for (ParsePosition pos = new ParsePosition(0); pos.getIndex() < len;) { if (parsePropertyName(value, pos) != null) { return true; } @@ -113,12 +146,28 @@ public class ParseProperties implements ParseNextProperty { /** * Return any property that can be parsed from the specified position * in the specified String. + * + *

Uses the configured {@link + * org.apache.tools.ant.PropertyHelper.PropertyExpander + * PropertyExpanders} and {@link GetProperty GetProperty} + * instance .

+ * * @param value String to parse * @param pos ParsePosition - * @return Object or null if no property is at the current location. + * @return Object or null if no property is at the current + * location. If a property reference has been found but the + * property doesn't expand to a value, the property's name is + * returned. */ public Object parseNextProperty(String value, ParsePosition pos) { - int start = pos.getIndex(); + final int start = pos.getIndex(); + + if (start > value.length()) { + // early exit, can't find any property here, no need to + // consult all the delegates. + return null; + } + String propertyName = parsePropertyName(value, pos); if (propertyName != null) { Object result = getProperty(propertyName); diff --git a/src/main/org/apache/tools/ant/property/PropertyExpander.java b/src/main/org/apache/tools/ant/property/PropertyExpander.java index 48d256a5b..9df8f31b0 100644 --- a/src/main/org/apache/tools/ant/property/PropertyExpander.java +++ b/src/main/org/apache/tools/ant/property/PropertyExpander.java @@ -22,17 +22,30 @@ import org.apache.tools.ant.PropertyHelper; import java.text.ParsePosition; /** - * Interface to a class (normally PropertyHelper) to get a property. + * Responsible for locating a property reference inside a String. * @since Ant 1.8.0 */ public interface PropertyExpander extends PropertyHelper.Delegate { + /** - * Parse the next property name. + * Determine whether there is a property reference at the current + * ParsePosition and return its name (or null if there is none). + * + *

Implementations should advance the ParsePosition to the last + * character that makes up the property reference. E.g. the + * default implementation would return "foo" for + * ${foo} and advance the ParsePosition to the + * } character.

+ * * @param s the String to parse. - * @param pos the ParsePosition in use. - * @param parseNextProperty parse next property - * @return parsed String if any, else null. + * @param pos the ParsePosition in use, the location is expected + * to be modified if a property reference has been found (and may + * even be modified if no reference has been found). + * @param parseNextProperty provides access to the Project and may + * be used to look up property values. + * @return property name if any, else null. */ - String parsePropertyName(String s, ParsePosition pos, ParseNextProperty parseNextProperty); + String parsePropertyName(String s, ParsePosition pos, + ParseNextProperty parseNextProperty); }