diff --git a/src/main/org/apache/tools/ant/ProjectHelper.java b/src/main/org/apache/tools/ant/ProjectHelper.java index c88df83e3..50acab8db 100644 --- a/src/main/org/apache/tools/ant/ProjectHelper.java +++ b/src/main/org/apache/tools/ant/ProjectHelper.java @@ -689,52 +689,80 @@ public class ProjectHelper { } - /** Replace ${NAME} with the property value + /** + * Replace ${} style constructions in the given value with the string value of + * the corresponding data types. + * + * @param value the string to be scanned for property references. */ public static String replaceProperties(Project project, String value, Hashtable keys ) - throws BuildException - { - // XXX use Map instead of proj, it's too heavy - - // XXX need to replace this code with something better. - StringBuffer sb=new StringBuffer(); - int i=0; - int prev=0; - // assert value!=nil + throws BuildException { + if (value == null) { + return null; + } + + Vector fragments = new Vector(); + Vector propertyRefs = new Vector(); + parsePropertyString(value, fragments, propertyRefs); + + StringBuffer sb = new StringBuffer(); + Enumeration i = fragments.elements(); + Enumeration j = propertyRefs.elements(); + while (i.hasMoreElements()) { + String fragment = (String)i.nextElement(); + if (fragment == null) { + String propertyName = (String)j.nextElement(); + if (!keys.containsKey(propertyName)) { + project.log("Property ${" + propertyName + "} has not been set", Project.MSG_VERBOSE); + } + fragment = (keys.containsKey(propertyName)) ? (String) keys.get(propertyName) + : "${" + propertyName + "}"; + } + sb.append(fragment); + } + + return sb.toString(); + } + + /** + * This method will parse a string containing ${value} style + * property values into two lists. The first list is a collection + * of text fragments, while the other is a set of string property names + * null entries in the first list indicate a property reference from the + * second list. + */ + public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs) + throws BuildException { + int prev = 0; int pos; - while( (pos=value.indexOf( "$", prev )) >= 0 ) { - if(pos>0) { - sb.append( value.substring( prev, pos ) ); + while ((pos = value.indexOf("$", prev)) >= 0) { + if (pos > 0) { + fragments.addElement(value.substring(prev, pos)); } + if( pos == (value.length() - 1)) { - sb.append('$'); + fragments.addElement("$"); prev = pos + 1; } - else if (value.charAt( pos + 1 ) != '{' ) { - sb.append( value.charAt( pos + 1 ) ); - prev=pos+2; // XXX + else if (value.charAt(pos + 1) != '{' ) { + fragments.addElement(value.substring(pos + 1, pos + 2)); + prev = pos + 2; } else { - int endName=value.indexOf( '}', pos ); - if( endName < 0 ) { - throw new BuildException("Syntax error in prop: " + - value ); - } - String n=value.substring( pos+2, endName ); - if (!keys.containsKey(n)) { - project.log("Property ${" + n + "} has not been set", Project.MSG_VERBOSE); + int endName = value.indexOf('}', pos); + if (endName < 0) { + throw new BuildException("Syntax error in property: " + + value ); } - - String v = (keys.containsKey(n)) ? (String) keys.get(n) : "${"+n+"}"; - - //System.out.println("N: " + n + " " + " V:" + v); - sb.append( v ); - prev=endName+1; + String propertyName = value.substring(pos + 2, endName); + fragments.addElement(null); + propertyRefs.addElement(propertyName); + prev = endName + 1; } } - if( prev < value.length() ) sb.append( value.substring( prev ) ); - // System.out.println("After replace: " + sb.toString()); - // System.out.println("Before replace: " + value); - return sb.toString(); + + if (prev < value.length()) { + fragments.addElement(value.substring(prev)); + } } private static SAXParserFactory getParserFactory() { diff --git a/src/main/org/apache/tools/ant/taskdefs/Property.java b/src/main/org/apache/tools/ant/taskdefs/Property.java index b54dc74e4..44be8a000 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Property.java +++ b/src/main/org/apache/tools/ant/taskdefs/Property.java @@ -160,26 +160,21 @@ public class Property extends Task { } public void execute() throws BuildException { - try { - if ((name != null) && (value != null)) { - addProperty(name, value); - } - - if (file != null) loadFile(file); - - if (resource != null) loadResource(resource); - - if (env != null) loadEnvironment(env); - - if ((name != null) && (ref != null)) { - Object obj = ref.getReferencedObject(getProject()); - if (obj != null) { - addProperty(name, obj.toString()); - } + if ((name != null) && (value != null)) { + addProperty(name, value); + } + + if (file != null) loadFile(file); + + if (resource != null) loadResource(resource); + + if (env != null) loadEnvironment(env); + + if ((name != null) && (ref != null)) { + Object obj = ref.getReferencedObject(getProject()); + if (obj != null) { + addProperty(name, obj.toString()); } - - } catch (Exception e) { - throw new BuildException(e, location); } } @@ -201,8 +196,8 @@ public class Property extends Task { log("Unable to find property file: " + file.getAbsolutePath(), Project.MSG_VERBOSE); } - } catch(Exception ex) { - throw new BuildException(ex.getMessage(), ex, location); + } catch(IOException ex) { + throw new BuildException(ex, location); } } @@ -231,8 +226,8 @@ public class Property extends Task { } else { log("Unable to find resource " + name, Project.MSG_WARN); } - } catch (Exception ex) { - ex.printStackTrace(); + } catch (IOException ex) { + throw new BuildException(ex, location); } } @@ -240,22 +235,18 @@ public class Property extends Task { Properties props = new Properties(); if (!prefix.endsWith(".")) prefix += "."; log("Loading Environment " + prefix, Project.MSG_VERBOSE); - try { - Vector osEnv = Execute.getProcEnvironment(); - for (Enumeration e = osEnv.elements(); e.hasMoreElements(); ) { - String entry = (String)e.nextElement(); - int pos = entry.indexOf('='); - if (pos == -1) { - log("Ignoring: " + entry, Project.MSG_WARN); - } else { - props.put(prefix + entry.substring(0, pos), - entry.substring(pos + 1)); - } + Vector osEnv = Execute.getProcEnvironment(); + for (Enumeration e = osEnv.elements(); e.hasMoreElements(); ) { + String entry = (String)e.nextElement(); + int pos = entry.indexOf('='); + if (pos == -1) { + log("Ignoring: " + entry, Project.MSG_WARN); + } else { + props.put(prefix + entry.substring(0, pos), + entry.substring(pos + 1)); } - addProperties(props); - } catch (Exception ex) { - throw new BuildException(ex, location); } + addProperties(props); } protected void addProperties(Properties props) { @@ -285,72 +276,43 @@ public class Property extends Task { } } - private void resolveAllProperties(Hashtable props) { - Hashtable unresolvableProperties = new Hashtable(); - for (Enumeration e = props.keys(); e.hasMoreElements(); ) { - String name = (String) e.nextElement(); - String value = (String) props.get(name); + private void resolveAllProperties(Properties props) throws BuildException { + for (Enumeration e = props.keys(); e.hasMoreElements();) { + String name = (String)e.nextElement(); + String value = props.getProperty(name); boolean resolved = false; - while (!resolved) { - Vector propsInValue = new Vector(); - - // assume it will be resolved + while (!resolved) { + Vector fragments = new Vector(); + Vector propertyRefs = new Vector(); + ProjectHelper.parsePropertyString(value, fragments, propertyRefs); + resolved = true; - boolean unresolvable = false; - if (extractProperties(value, propsInValue)) { - for (int i=0; i < propsInValue.size(); i++) { - String elem = (String) propsInValue.elementAt(i); - if (elem.equals(name) || unresolvableProperties.containsKey(elem)) { - // we won't try further resolving elements with circular - // property dependencies or dependencies on unresolvable elements - unresolvable = true; - break; - } - - if (project.getProperties().containsKey(elem) || - props.containsKey(elem)) { - resolved = false; + if (propertyRefs.size() != 0) { + StringBuffer sb = new StringBuffer(); + Enumeration i = fragments.elements(); + Enumeration j = propertyRefs.elements(); + while (i.hasMoreElements()) { + String fragment = (String)i.nextElement(); + if (fragment == null) { + String propertyName = (String)j.nextElement(); + if (propertyName.equals(name)) { + throw new BuildException("Property " + name + " was circularly defined."); + } + if (props.containsKey(propertyName)) { + fragment = props.getProperty(propertyName); + resolved = false; + } + else { + fragment = "${" + propertyName + "}"; + } } + sb.append(fragment); } - } - - if (unresolvable) { - unresolvableProperties.put(name, value); - resolved = true; - } - - if (!resolved) { - value = ProjectHelper.replaceProperties(project, value, - project.getProperties()); - value = ProjectHelper.replaceProperties(project, value, props); + value = sb.toString(); props.put(name, value); - } - } - } - } - - private boolean extractProperties(String source, Vector properties) { - // This is an abreviated version of - // ProjectHelper.replaceProperties method - int i=0; - int prev=0; - int pos; - - while( (pos=source.indexOf( "$", prev )) >= 0 ) { - if( pos == (source.length() - 1)) { - prev = pos + 1; - } else if (source.charAt( pos + 1 ) != '{' ) { - prev=pos+2; - } else { - int endName=source.indexOf( '}', pos ); - String n=source.substring( pos+2, endName ); - properties.addElement(n); - prev=endName+1; + } } } - - return (properties.size() > 0); - } - + } }