Author: peterreilly Date: Mon Sep 24 04:56:34 2007 New Revision: 578769 URL: http://svn.apache.org/viewvc?rev=578769&view=rev Log: Some cleanups of property expansion * extact expand property from PropertyExpander * extact resolve property map from Property task * remove use of ThreadLocal from Property task * remove need of cloning of PropertyHelper when resolving properties in a map.
Added: ant/core/trunk/src/main/org/apache/tools/ant/property/GetProperty.java (with props) ant/core/trunk/src/main/org/apache/tools/ant/property/ParseNextProperty.java (with props) ant/core/trunk/src/main/org/apache/tools/ant/property/ParseProperties.java (with props) ant/core/trunk/src/main/org/apache/tools/ant/property/PropertyExpander.java (with props) ant/core/trunk/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java (with props) Modified: ant/core/trunk/src/main/org/apache/tools/ant/PropertyHelper.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Property.java Modified: ant/core/trunk/src/main/org/apache/tools/ant/PropertyHelper.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/PropertyHelper.java?rev=578769&r1=578768&r2=578769&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/PropertyHelper.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/PropertyHelper.java Mon Sep 24 04:56:34 2007 @@ -27,8 +27,13 @@ import java.util.Set; import java.util.Vector; import java.util.Enumeration; +import java.util.Collection; import org.apache.tools.ant.property.NullReturn; +import org.apache.tools.ant.property.GetProperty; +import org.apache.tools.ant.property.ParseNextProperty; +import org.apache.tools.ant.property.PropertyExpander; +import org.apache.tools.ant.property.ParseProperties; /* ISSUES: - ns param. It could be used to provide "namespaces" for properties, which @@ -60,7 +65,7 @@ * * @since Ant 1.6 */ -public class PropertyHelper implements Cloneable { +public class PropertyHelper implements GetProperty { // -------------------------------------------------------- // @@ -90,22 +95,6 @@ } /** - * Describes an entity capable of expanding properties embedded in a string. - * @since Ant 1.8 - */ - public interface PropertyExpander extends Delegate { - /** - * Parse the next property name. - * @param s the String to parse. - * @param pos the ParsePosition in use. - * @param propertyHelper the invoking PropertyHelper. - * @return parsed String if any, else <code>null</code>. - */ - String parsePropertyName( - String s, ParsePosition pos, PropertyHelper propertyHelper); - } - - /** * Describes an entity capable of setting a property to a value. * @since Ant 1.8 */ @@ -151,7 +140,7 @@ private static final PropertyExpander DEFAULT_EXPANDER = new PropertyExpander() { public String parsePropertyName( - String s, ParsePosition pos, PropertyHelper propertyHelper) { + String s, ParsePosition pos, ParseNextProperty notUsed) { int index = pos.getIndex(); if (s.indexOf("${", index) == index) { int end = s.indexOf('}', index); @@ -176,7 +165,8 @@ */ // CheckStyle:LineLengthCheck ON public String parsePropertyName( - String s, ParsePosition pos, PropertyHelper propertyHelper) { + String s, ParsePosition pos, ParseNextProperty notUsed) { + //System.out.println("parseproperty " + s); int index = pos.getIndex(); if (s.indexOf("$$", index) == index) { pos.setIndex(++index); @@ -331,6 +321,15 @@ return helper; } + /** + * Get the expanders. + * @return the exapanders. + */ + public Collection getExpanders() { + return getDelegates(PropertyExpander.class); + } + + // -------------------- Methods to override -------------------- /** @@ -483,31 +482,8 @@ * <code>null</code> if the original string is <code>null</code>. */ public Object parseProperties(String value) throws BuildException { - if (value == null || "".equals(value)) { - return value; - } - ParsePosition pos = new ParsePosition(0); - Object o = parseNextProperty(value, pos); - if (o != null && pos.getIndex() == value.length()) { - return o; - } - StringBuffer sb = new StringBuffer(value.length() * 2); - if (o == null) { - sb.append(value.charAt(pos.getIndex())); - pos.setIndex(pos.getIndex() + 1); - } else { - sb.append(o); - } - while (pos.getIndex() < value.length()) { - o = parseNextProperty(value, pos); - if (o == null) { - sb.append(value.charAt(pos.getIndex())); - pos.setIndex(pos.getIndex() + 1); - } else { - sb.append(o); - } - } - return sb.toString(); + return new ParseProperties(getProject(), getExpanders(), this) + .parseProperties(value); } /** @@ -516,50 +492,8 @@ * @return <code>true</code> if <code>value</code> contains property notation. */ public boolean containsProperties(String value) { - if (value == null) { - return false; - } - for (ParsePosition pos = new ParsePosition(0); pos.getIndex() < value.length();) { - if (parsePropertyName(value, pos) != null) { - return true; - } - pos.setIndex(pos.getIndex() + 1); - } - return false; - } - - /** - * Return any property that can be parsed from the specified position in the specified String. - * @param value String to parse - * @param pos ParsePosition - * @return Object or null if no property is at the current location. - */ - public Object parseNextProperty(String value, ParsePosition pos) { - int start = pos.getIndex(); - String propertyName = parsePropertyName(value, pos); - if (propertyName != null) { - Object result = getProperty(propertyName); - if (result != null) { - return result; - } - getProject().log("Property \"" + propertyName - + "\" has not been set", Project.MSG_VERBOSE); - return value.substring(start, pos.getIndex()); - } - return null; - } - - private String parsePropertyName(String value, ParsePosition pos) { - for (Iterator iter = getDelegates(PropertyExpander.class).iterator(); - iter.hasNext();) { - String propertyName = ((PropertyExpander) iter.next()) - .parsePropertyName(value, pos, this); - if (propertyName == null) { - continue; - } - return propertyName; - } - return null; + return new ParseProperties(getProject(), getExpanders(), this) + .containsProperties(value); } // -------------------- Default implementation -------------------- @@ -1062,22 +996,4 @@ return result; } - /** - * Make a clone of this PropertyHelper. - * @return the cloned PropertyHelper. - * @since Ant 1.8 - */ - public synchronized Object clone() { - PropertyHelper result; - try { - result = (PropertyHelper) super.clone(); - result.delegates = (Hashtable) delegates.clone(); - result.properties = (Hashtable) properties.clone(); - result.userProperties = (Hashtable) userProperties.clone(); - result.inheritedProperties = (Hashtable) inheritedProperties.clone(); - } catch (CloneNotSupportedException e) { - throw new BuildException(e); - } - return result; - } } Added: ant/core/trunk/src/main/org/apache/tools/ant/property/GetProperty.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/property/GetProperty.java?rev=578769&view=auto ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/property/GetProperty.java (added) +++ ant/core/trunk/src/main/org/apache/tools/ant/property/GetProperty.java Mon Sep 24 04:56:34 2007 @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.property; + +/** Interface to a class (normally PropertyHelper) to get a property */ +public interface GetProperty { + /** + * Returns the value of a property if it is set. + * @param name name of the property. + * @return the property value, or null for no match or for name being null. + */ + Object getProperty(String name); +} Propchange: ant/core/trunk/src/main/org/apache/tools/ant/property/GetProperty.java ------------------------------------------------------------------------------ svn:eol-style = native Added: ant/core/trunk/src/main/org/apache/tools/ant/property/ParseNextProperty.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/property/ParseNextProperty.java?rev=578769&view=auto ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/property/ParseNextProperty.java (added) +++ ant/core/trunk/src/main/org/apache/tools/ant/property/ParseNextProperty.java Mon Sep 24 04:56:34 2007 @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.property; + +import java.text.ParsePosition; + +import org.apache.tools.ant.Project; + +/** Interface to parse a property */ +public interface ParseNextProperty { + /** + * Get the current project. + * @return the current ant project. + */ + Project getProject(); + + /** + * Return any property that can be parsed from the specified position + * in the specified String. + * @param value String to parse + * @param pos ParsePosition + * @return Object or null if no property is at the current location. + */ + Object parseNextProperty(String value, ParsePosition pos); +} Propchange: ant/core/trunk/src/main/org/apache/tools/ant/property/ParseNextProperty.java ------------------------------------------------------------------------------ svn:eol-style = native Added: ant/core/trunk/src/main/org/apache/tools/ant/property/ParseProperties.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/property/ParseProperties.java?rev=578769&view=auto ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/property/ParseProperties.java (added) +++ ant/core/trunk/src/main/org/apache/tools/ant/property/ParseProperties.java Mon Sep 24 04:56:34 2007 @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.property; + +import java.text.ParsePosition; +import java.util.Collection; +import java.util.Iterator; +import org.apache.tools.ant.Project; + +/** + * Parse properties using a collection of expanders. + */ +public class ParseProperties implements ParseNextProperty { + + private final Project project; + private final GetProperty getProperty; + private final Collection expanders; + + /** + * Constructor with a getProperty. + * @param project the current ant project. + * @param expanders a sequence of exapanders + * @param getProperty property resolver. + */ + public ParseProperties( + Project project, Collection expanders, GetProperty getProperty) { + this.project = project; + this.expanders = expanders; + this.getProperty = getProperty; + } + + /** + * Get the project. + * @return the current ant project. + */ + public Project getProject() { + return project; + } + + /** + * 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. + * + * @param value The string to be scanned for property references. + * May be <code>null</code>, in which case this + * method returns immediately with no effect. + * + * @return the original string with the properties replaced, or + * <code>null</code> if the original string is <code>null</code>. + */ + public Object parseProperties(String value) { + if (value == null || "".equals(value) || value.indexOf('$') == -1) { + return value; + } + ParsePosition pos = new ParsePosition(0); + Object o = parseNextProperty(value, pos); + if (o != null && pos.getIndex() == value.length()) { + return o; + } + StringBuffer sb = new StringBuffer(value.length() * 2); + if (o == null) { + sb.append(value.charAt(pos.getIndex())); + pos.setIndex(pos.getIndex() + 1); + } else { + sb.append(o); + } + while (pos.getIndex() < value.length()) { + o = parseNextProperty(value, pos); + if (o == null) { + sb.append(value.charAt(pos.getIndex())); + pos.setIndex(pos.getIndex() + 1); + } else { + sb.append(o); + } + } + return sb.toString(); + } + + /** + * Learn whether a String contains replaceable properties. + * @param value the String to check. + * @return <code>true</code> if <code>value</code> contains property notation. + */ + public boolean containsProperties(String value) { + if (value == null) { + return false; + } + for (ParsePosition pos = new ParsePosition(0); pos.getIndex() < value.length();) { + if (parsePropertyName(value, pos) != null) { + return true; + } + pos.setIndex(pos.getIndex() + 1); + } + return false; + } + + /** + * Return any property that can be parsed from the specified position + * in the specified String. + * @param value String to parse + * @param pos ParsePosition + * @return Object or null if no property is at the current location. + */ + public Object parseNextProperty(String value, ParsePosition pos) { + int start = pos.getIndex(); + String propertyName = parsePropertyName(value, pos); + if (propertyName != null) { + Object result = getProperty(propertyName); + if (result != null) { + return result; + } + if (project != null) { + project.log( + "Property \"" + propertyName + + "\" has not been set", Project.MSG_VERBOSE); + } + return value.substring(start, pos.getIndex()); + } + return null; + } + + private String parsePropertyName(String value, ParsePosition pos) { + for (Iterator iter = expanders.iterator(); iter.hasNext();) { + String propertyName = ((PropertyExpander) iter.next()) + .parsePropertyName(value, pos, this); + if (propertyName == null) { + continue; + } + return propertyName; + } + return null; + } + + private Object getProperty(String propertyName) { + return getProperty.getProperty(propertyName); + } +} Propchange: ant/core/trunk/src/main/org/apache/tools/ant/property/ParseProperties.java ------------------------------------------------------------------------------ svn:eol-style = native Added: ant/core/trunk/src/main/org/apache/tools/ant/property/PropertyExpander.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/property/PropertyExpander.java?rev=578769&view=auto ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/property/PropertyExpander.java (added) +++ ant/core/trunk/src/main/org/apache/tools/ant/property/PropertyExpander.java Mon Sep 24 04:56:34 2007 @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.property; + +import org.apache.tools.ant.PropertyHelper; + +import java.text.ParsePosition; + +/** Interface to a class (normally PropertyHelper) to get a property */ +public interface PropertyExpander extends PropertyHelper.Delegate { + /** + * Parse the next property name. + * @param s the String to parse. + * @param pos the ParsePosition in use. + * @param parseNextProperty parse next property + * @return parsed String if any, else <code>null</code>. + */ + String parsePropertyName( + String s, ParsePosition pos, ParseNextProperty parseNextProperty); +} + Propchange: ant/core/trunk/src/main/org/apache/tools/ant/property/PropertyExpander.java ------------------------------------------------------------------------------ svn:eol-style = native Added: ant/core/trunk/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java?rev=578769&view=auto ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java (added) +++ ant/core/trunk/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java Mon Sep 24 04:56:34 2007 @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.property; + +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.HashSet; +import java.util.Collection; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.BuildException; + +/** + * Class to resolve properties in a map. + */ +public class ResolvePropertyMap implements GetProperty { + private final Set seen = new HashSet(); + private final ParseProperties parseProperties; + private final GetProperty master; + private Map map; + + /** + * Constructor with a master getproperty and a collection of expanders. + * @param project the current ant project. + * @param master the master property holder (usually PropertyHelper) + * @param expanders a collection of expanders (usually from PropertyHelper). + */ + public ResolvePropertyMap( + Project project, GetProperty master, Collection expanders) { + this.master = master; + this.parseProperties = new ParseProperties(project, expanders, this); + } + + /** + * Returns the value of a property if it is set. + * @param name name of the property. + * @return the property value, or null for no match or for name being null. + */ + public Object getProperty(String name) { + if (seen.contains(name)) { + throw new BuildException( + "Property " + name + " was circularly " + "defined."); + } + // Note: the master overrides (even if the name is subsequently + // prefixed) + Object masterProperty = master.getProperty(name); + if (masterProperty != null) { + return masterProperty; + } + try { + seen.add(name); + return parseProperties.parseProperties((String) map.get(name)); + } finally { + seen.remove(name); + } + } + + /** + * The action method - resolves all the properties in a map. + * @param map the map to resolve properties in. + */ + public void resolveAllProperties(Map map) { + this.map = map; // The map gets used in the getProperty callback + for (Iterator i = map.keySet().iterator(); i.hasNext();) { + String key = (String) i.next(); + Object result = getProperty(key); + String value = result == null ? "" : result.toString(); + map.put(key, value); + } + } +} Propchange: ant/core/trunk/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Property.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Property.java?rev=578769&r1=578768&r2=578769&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Property.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Property.java Mon Sep 24 04:56:34 2007 @@ -28,7 +28,6 @@ import java.util.Iterator; import java.util.Map; import java.util.Properties; -import java.util.Stack; import java.util.Vector; import org.apache.tools.ant.BuildException; @@ -38,6 +37,7 @@ import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Reference; import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.property.ResolvePropertyMap; /** * Sets a property by name, or set of properties (from file or @@ -73,62 +73,6 @@ * @ant.task category="property" */ public class Property extends Task { - private static class PropertyResolver implements PropertyHelper.PropertyEvaluator { - private ThreadLocal getStack = new ThreadLocal() { - protected Object initialValue() { - return new Stack(); - } - }; - private ThreadLocal replaceStack = new ThreadLocal() { - protected Object initialValue() { - return new Stack(); - } - }; - private Map map; - - /** - * Construct a new Property.PropertyResolver instance. - */ - public PropertyResolver(Map map) { - this.map = map; - } - - // CheckStyle:LineLengthCheck OFF see to long - /* (non-Javadoc) - * @see org.apache.tools.ant.PropertyHelper.PropertyEvaluator#evaluate(java.lang.String, org.apache.tools.ant.PropertyHelper) - */ - // CheckStyle:LineLengthCheck ON - public Object evaluate(String property, PropertyHelper propertyHelper) { - //our feeble properties don't matter if the PropertyHelper - // can resolve the property without us: - Stack stk = (Stack) getStack.get(); - if (stk.contains(property)) { - return null; - } - stk.push(property); - try { - if (propertyHelper.getProperty(property) != null) { - return null; - } - } finally { - stk.pop(); - } - Object value = map.get(property); - if (!(value instanceof String)) { - return null; - } - stk = (Stack) replaceStack.get(); - if (stk.contains(property)) { - throw new BuildException("Property " + property + " was circularly defined."); - } - stk.push(property); - try { - return propertyHelper.replaceProperties((String) value); - } finally { - stk.pop(); - } - } - } // CheckStyle:VisibilityModifier OFF - bc protected String name; @@ -696,16 +640,12 @@ * @param props properties object to resolve */ private void resolveAllProperties(Map props) throws BuildException { - PropertyHelper propertyHelper = (PropertyHelper) PropertyHelper.getPropertyHelper( - getProject()).clone(); - propertyHelper.add(new PropertyResolver(props)); - for (Iterator it = props.keySet().iterator(); it.hasNext();) { - Object k = it.next(); - if (k instanceof String) { - Object value = propertyHelper.getProperty((String) k); - props.put(k, value); - } - } + PropertyHelper propertyHelper + = (PropertyHelper) PropertyHelper.getPropertyHelper(getProject()); + new ResolvePropertyMap( + getProject(), + propertyHelper, + propertyHelper.getExpanders()).resolveAllProperties(props); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]