diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/PropertyHelper.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/PropertyHelper.java | 1215 |
1 files changed, 0 insertions, 1215 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/PropertyHelper.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/PropertyHelper.java deleted file mode 100644 index 1dbb280c..00000000 --- a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/PropertyHelper.java +++ /dev/null @@ -1,1215 +0,0 @@ -/* - * 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; - -import java.text.ParsePosition; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.List; -import java.util.Set; -import java.util.Vector; - -import org.apache.tools.ant.property.GetProperty; -import org.apache.tools.ant.property.NullReturn; -import org.apache.tools.ant.property.ParseNextProperty; -import org.apache.tools.ant.property.ParseProperties; -import org.apache.tools.ant.property.PropertyExpander; - -/* ISSUES: - - ns param. It could be used to provide "namespaces" for properties, which - may be more flexible. - - Object value. In ant1.5 String is used for Properties - but it would be nice - to support generic Objects (the property remains immutable - you can't change - the associated object). This will also allow JSP-EL style setting using the - Object if an attribute contains only the property (name="${property}" could - avoid Object->String->Object conversion) - - Currently we "chain" only for get and set property (probably most users - will only need that - if they need more they can replace the top helper). - Need to discuss this and find if we need more. - */ - -/* update for impending Ant 1.8.0: - - - I can't see any reason for ns and would like to deprecate it. - - Replacing chaining with delegates for certain behavioral aspects. - - Object value seems valuable as outlined. - - */ - -/** - * Deals with properties - substitution, dynamic properties, etc. - * - * <p>This code has been heavily restructured for Ant 1.8.0. It is - * expected that custom PropertyHelper implementation that used the - * older chaining mechanism of Ant 1.6 won't work in all cases, and - * its usage is deprecated. The preferred way to customize Ant's - * property handling is by {@link #add adding} {@link - * PropertyHelper.Delegate delegates} of the appropriate subinterface - * and have this implementation use them.</p> - * - * <p>When {@link #parseProperties expanding a string that may contain - * properties} this class will delegate the actual parsing to {@link - * org.apache.tools.ant.property.ParseProperties#parseProperties - * parseProperties} inside the ParseProperties class which in turn - * uses the {@link org.apache.tools.ant.property.PropertyExpander - * PropertyExpander delegates} to find properties inside the string - * and this class to expand the propertiy names found into the - * corresponding values.</p> - * - * <p>When {@link #getProperty looking up a property value} this class - * will first consult all {@link PropertyHelper.PropertyEvaluator - * PropertyEvaluator} delegates and fall back to an internal map of - * "project properties" if no evaluator matched the property name.</p> - * - * <p>When {@link #setProperty setting a property value} this class - * will first consult all {@link PropertyHelper.PropertySetter - * PropertySetter} delegates and fall back to an internal map of - * "project properties" if no setter matched the property name.</p> - * - * @since Ant 1.6 - */ -public class PropertyHelper implements GetProperty { - - // -------------------------------------------------------- - // - // The property delegate interfaces - // - // -------------------------------------------------------- - - /** - * Marker interface for a PropertyHelper delegate. - * @since Ant 1.8.0 - */ - public interface Delegate { - } - - /** - * Looks up a property's value based on its name. - * - * <p>Can be used to look up properties in a different storage - * than the project instance (like local properties for example) - * or to implement custom "protocols" like Ant's - * <code>${toString:refid}</code> syntax.</p> - * - * @since Ant 1.8.0 - */ - public interface PropertyEvaluator extends Delegate { - /** - * Evaluate a property. - * - * @param property the property's String "identifier". - * @param propertyHelper the invoking PropertyHelper. - * @return null if the property name could not be found, an - * instance of {@link org.apache.tools.ant.property.NullReturn - * NullReturn} to indicate a property with a name that can be - * matched but a value of <code>null</code> and the property's - * value otherwise. - */ - Object evaluate(String property, PropertyHelper propertyHelper); - } - - /** - * Sets or overrides a property. - * - * <p>Can be used to store properties in a different storage than - * the project instance (like local properties for example).</p> - * - * @since Ant 1.8.0 - */ - public interface PropertySetter extends Delegate { - /** - * Set a *new" property. - * - * <p>Should not replace the value of an existing property.</p> - * - * @param property the property's String "identifier". - * @param value the value to set. - * @param propertyHelper the invoking PropertyHelper. - * @return true if this entity 'owns' the property. - */ - boolean setNew( - String property, Object value, PropertyHelper propertyHelper); - - /** - * Set a property. - * - * <p>May replace the value of an existing property.</p> - * - * @param property the property's String "identifier". - * @param value the value to set. - * @param propertyHelper the invoking PropertyHelper. - * @return true if this entity 'owns' the property. - */ - boolean set( - String property, Object value, PropertyHelper propertyHelper); - } - - //TODO PropertyEnumerator Delegate type, would improve PropertySet - - // -------------------------------------------------------- - // - // The predefined property delegates - // - // -------------------------------------------------------- - - private static final PropertyEvaluator TO_STRING = new PropertyEvaluator() { - private final String PREFIX = "toString:"; - private final int PREFIX_LEN = PREFIX.length(); - - public Object evaluate(String property, PropertyHelper propertyHelper) { - Object o = null; - if (property.startsWith(PREFIX) && propertyHelper.getProject() != null) { - o = propertyHelper.getProject().getReference(property.substring(PREFIX_LEN)); - } - return o == null ? null : o.toString(); - } - }; - - private static final PropertyExpander DEFAULT_EXPANDER = new PropertyExpander() { - public String parsePropertyName( - String s, ParsePosition pos, ParseNextProperty notUsed) { - int index = pos.getIndex(); - //directly check near, triggering characters: - if (s.length() - index >= 3 - && '$' == s.charAt(index) && '{' == s.charAt(index + 1)) { - int start = index + 2; - //defer to String.indexOf() for protracted check: - int end = s.indexOf('}', start); - if (end < 0) { - throw new BuildException("Syntax error in property: " - + s.substring(index)); - } - pos.setIndex(end + 1); - return start == end ? "" : s.substring(start, end); - } - return null; - } - }; - - /** dummy */ - private static final PropertyExpander SKIP_DOUBLE_DOLLAR - = new PropertyExpander() { - // CheckStyle:LineLengthCheck OFF see too long - /** - * {@inheritDoc} - * @see org.apache.tools.ant.property.PropertyExpander#parsePropertyName(java.lang.String, java.text.ParsePosition, org.apache.tools.ant.PropertyHelper) - */ - // CheckStyle:LineLengthCheck ON - public String parsePropertyName( - String s, ParsePosition pos, ParseNextProperty notUsed) { - int index = pos.getIndex(); - if (s.length() - index >= 2) { - /* check for $$; if found, advance by one-- - * this expander is at the bottom of the stack - * and will thus be the last consulted, - * so the next thing that ParseProperties will do - * is advance the parse position beyond the second $ - */ - if ('$' == s.charAt(index) && '$' == s.charAt(++index)) { - pos.setIndex(index); - } - } - return null; - } - }; - - /** - * @since Ant 1.8.0 - */ - private static final PropertyEvaluator FROM_REF = new PropertyEvaluator() { - private final String PREFIX = "ant.refid:"; - private final int PREFIX_LEN = PREFIX.length(); - - public Object evaluate(String prop, PropertyHelper helper) { - return prop.startsWith(PREFIX) && helper.getProject() != null - ? helper.getProject().getReference(prop.substring(PREFIX_LEN)) - : null; - } - }; - - private Project project; - private PropertyHelper next; - private final Hashtable<Class<? extends Delegate>, List<Delegate>> delegates = new Hashtable<Class<? extends Delegate>, List<Delegate>>(); - - /** Project properties map (usually String to String). */ - private Hashtable<String, Object> properties = new Hashtable<String, Object>(); - - /** - * Map of "user" properties (as created in the Ant task, for example). - * Note that these key/value pairs are also always put into the - * project properties, so only the project properties need to be queried. - */ - private Hashtable<String, Object> userProperties = new Hashtable<String, Object>(); - - /** - * Map of inherited "user" properties - that are those "user" - * properties that have been created by tasks and not been set - * from the command line or a GUI tool. - */ - private Hashtable<String, Object> inheritedProperties = new Hashtable<String, Object>(); - - /** - * Default constructor. - */ - protected PropertyHelper() { - add(FROM_REF); - add(TO_STRING); - add(SKIP_DOUBLE_DOLLAR); - add(DEFAULT_EXPANDER); - } - - // -------------------------------------------------------- - // - // Some helper static methods to get and set properties - // - // -------------------------------------------------------- - - /** - * A helper static method to get a property - * from a particular project. - * @param project the project in question. - * @param name the property name - * @return the value of the property if present, null otherwise. - * @since Ant 1.8.0 - */ - public static Object getProperty(Project project, String name) { - return PropertyHelper.getPropertyHelper(project) - .getProperty(name); - } - - /** - * A helper static method to set a property - * from a particular project. - * @param project the project in question. - * @param name the property name - * @param value the value to use. - * @since Ant 1.8.0 - */ - public static void setProperty(Project project, String name, Object value) { - PropertyHelper.getPropertyHelper(project) - .setProperty(name, value, true); - } - - /** - * A helper static method to set a new property - * from a particular project. - * @param project the project in question. - * @param name the property name - * @param value the value to use. - * @since Ant 1.8.0 - */ - public static void setNewProperty( - Project project, String name, Object value) { - PropertyHelper.getPropertyHelper(project) - .setNewProperty(name, value); - } - - //override facility for subclasses to put custom hashtables in - - // -------------------- Hook management -------------------- - - /** - * Set the project for which this helper is performing property resolution. - * - * @param p the project instance. - */ - public void setProject(Project p) { - this.project = p; - } - - /** - * Get this PropertyHelper's Project. - * @return Project - */ - public Project getProject() { - return project; - } - - /** - * Prior to Ant 1.8.0 there have been 2 ways to hook into property handling: - * - * - you can replace the main PropertyHelper. The replacement is required - * to support the same semantics (of course :-) - * - * - you can chain a property helper capable of storing some properties. - * Again, you are required to respect the immutability semantics (at - * least for non-dynamic properties) - * - * <p>As of Ant 1.8.0 this method is never invoked by any code - * inside of Ant itself.</p> - * - * @param next the next property helper in the chain. - * @deprecated use the delegate mechanism instead - */ - public void setNext(PropertyHelper next) { - this.next = next; - } - - /** - * Get the next property helper in the chain. - * - * <p>As of Ant 1.8.0 this method is never invoked by any code - * inside of Ant itself except the {@link #setPropertyHook - * setPropertyHook} and {@link #getPropertyHook getPropertyHook} - * methods in this class.</p> - * - * @return the next property helper. - * @deprecated use the delegate mechanism instead - */ - public PropertyHelper getNext() { - return next; - } - - /** - * Factory method to create a property processor. - * Users can provide their own or replace it using "ant.PropertyHelper" - * reference. User tasks can also add themselves to the chain, and provide - * dynamic properties. - * - * @param project the project for which the property helper is required. - * - * @return the project's property helper. - */ - public static synchronized PropertyHelper getPropertyHelper(Project project) { - PropertyHelper helper = null; - if (project != null) { - helper = (PropertyHelper) project.getReference(MagicNames - .REFID_PROPERTY_HELPER); - } - if (helper != null) { - return helper; - } - - helper = new PropertyHelper(); - helper.setProject(project); - - if (project != null) { - project.addReference(MagicNames.REFID_PROPERTY_HELPER, helper); - } - - return helper; - } - - /** - * Get the {@link PropertyExpander expanders}. - * @since Ant 1.8.0 - * @return the expanders. - */ - public Collection<PropertyExpander> getExpanders() { - return getDelegates(PropertyExpander.class); - } - - - // -------------------- Methods to override -------------------- - - /** - * Sets a property. Any existing property of the same name - * is overwritten, unless it is a user property. - * - * If all helpers return false, the property will be saved in - * the default properties table by setProperty. - * - * <p>As of Ant 1.8.0 this method is never invoked by any code - * inside of Ant itself.</p> - * - * @param ns The namespace that the property is in (currently - * not used. - * @param name The name of property to set. - * Must not be <code>null</code>. - * @param value The new value of the property. - * Must not be <code>null</code>. - * @param inherited True if this property is inherited (an [sub]ant[call] property). - * @param user True if this property is a user property. - * @param isNew True is this is a new property. - * @return true if this helper has stored the property, false if it - * couldn't. Each helper should delegate to the next one (unless it - * has a good reason not to). - * @deprecated PropertyHelper chaining is deprecated. - */ - public boolean setPropertyHook(String ns, String name, - Object value, - boolean inherited, boolean user, - boolean isNew) { - if (getNext() != null) { - boolean subst = getNext().setPropertyHook(ns, name, value, inherited, user, isNew); - // If next has handled the property - if (subst) { - return true; - } - } - return false; - } - - /** - * Get a property. If all hooks return null, the default - * tables will be used. - * - * <p>As of Ant 1.8.0 this method is never invoked by any code - * inside of Ant itself.</p> - * - * @param ns namespace of the sought property. - * @param name name of the sought property. - * @param user True if this is a user property. - * @return The property, if returned by a hook, or null if none. - * @deprecated PropertyHelper chaining is deprecated. - */ - public Object getPropertyHook(String ns, String name, boolean user) { - if (getNext() != null) { - Object o = getNext().getPropertyHook(ns, name, user); - if (o != null) { - return o; - } - } - // Experimental/Testing, will be removed - if (project != null && name.startsWith("toString:")) { - name = name.substring("toString:".length()); - Object v = project.getReference(name); - return (v == null) ? null : v.toString(); - } - return null; - } - - // -------------------- Optional methods -------------------- - // You can override those methods if you want to optimize or - // do advanced things (like support a special syntax). - // The methods do not chain - you should use them when embedding ant - // (by replacing the main helper) - - /** - * Parses a string containing <code>${xxx}</code> style property - * references into two lists. The first list is a collection - * of text fragments, while the other is a set of string property names. - * <code>null</code> entries in the first list indicate a property - * reference from the second list. - * - * <p>Delegates to {@link #parsePropertyStringDefault - * parsePropertyStringDefault}.</p> - * - * <p>As of Ant 1.8.0 this method is never invoked by any code - * inside of Ant itself except {ProjectHelper#parsePropertyString - * ProjectHelper.parsePropertyString}.</p> - * - * @param value Text to parse. Must not be <code>null</code>. - * @param fragments List to add text fragments to. - * Must not be <code>null</code>. - * @param propertyRefs List to add property names to. - * Must not be <code>null</code>. - * - * @exception BuildException if the string contains an opening - * <code>${</code> without a closing - * <code>}</code> - * @deprecated use the other mechanisms of this class instead - */ - public void parsePropertyString(String value, Vector<String> fragments, - Vector<String> propertyRefs) throws BuildException { - parsePropertyStringDefault(value, fragments, propertyRefs); - } - - /** - * Replaces <code>${xxx}</code> style constructions in the given value - * with the string value of the corresponding data types. - * - * <p>Delegates to the one-arg version, completely ignoring the ns - * and keys parameters.</p> - * - * @param ns The namespace for the property. - * @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. - * @param keys Mapping (String to Object) of property names to their - * values. If <code>null</code>, only project properties will - * be used. - * - * @exception BuildException if the string contains an opening - * <code>${</code> without a closing - * <code>}</code> - * @return the original string with the properties replaced, or - * <code>null</code> if the original string is <code>null</code>. - */ - //TODO deprecate? Recall why no longer using ns/keys params - public String replaceProperties(String ns, String value, Hashtable<String, Object> keys) throws BuildException { - return replaceProperties(value); - } - - /** - * Replaces <code>${xxx}</code> 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. - * May be <code>null</code>, in which case this - * method returns immediately with no effect. - * - * @exception BuildException if the string contains an opening - * <code>${</code> without a closing - * <code>}</code> - * @return the original string with the properties replaced, or - * <code>null</code> if the original string is <code>null</code>. - */ - public String replaceProperties(String value) throws BuildException { - Object o = parseProperties(value); - return o == null || o instanceof String ? (String) o : o.toString(); - } - - /** - * 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. - * - * @exception BuildException if the string contains an opening - * <code>${</code> without a closing - * <code>}</code> - * @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) throws BuildException { - return new ParseProperties(getProject(), getExpanders(), this) - .parseProperties(value); - } - - /** - * 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) { - return new ParseProperties(getProject(), getExpanders(), this) - .containsProperties(value); - } - - // -------------------- Default implementation -------------------- - // Methods used to support the default behavior and provide backward - // compatibility. Some will be deprecated, you should avoid calling them. - - /** - * Default implementation of setProperty. Will be called from Project. - * This is the original 1.5 implementation, with calls to the hook - * added. - * - * <p>Delegates to the three-arg version, completely ignoring the - * ns parameter.</p> - * - * @param ns The namespace for the property (currently not used). - * @param name The name of the property. - * @param value The value to set the property to. - * @param verbose If this is true output extra log messages. - * @return true if the property is set. - * @deprecated namespaces are unnecessary. - */ - public boolean setProperty(String ns, String name, Object value, boolean verbose) { - return setProperty(name, value, verbose); - } - - /** - * Default implementation of setProperty. Will be called from Project. - * @param name The name of the property. - * @param value The value to set the property to. - * @param verbose If this is true output extra log messages. - * @return true if the property is set. - */ - public boolean setProperty(String name, Object value, boolean verbose) { - for (PropertySetter setter : getDelegates(PropertySetter.class)) { - if (setter.set(name, value, this)) { - return true; - } - } - synchronized (this) { - // user (CLI) properties take precedence - if (userProperties.containsKey(name)) { - if (project != null && verbose) { - project.log("Override ignored for user property \"" - + name + "\"", Project.MSG_VERBOSE); - } - return false; - } - if (project != null && verbose) { - if (properties.containsKey(name)) { - project.log("Overriding previous definition of property \"" - + name + "\"", Project.MSG_VERBOSE); - } - project.log("Setting project property: " + name + " -> " - + value, Project.MSG_DEBUG); - } - if (name != null && value != null) { - properties.put(name, value); - } - return true; - } - } - - /** - * Sets a property if no value currently exists. If the property - * exists already, a message is logged and the method returns with - * no other effect. - * - * <p>Delegates to the two-arg version, completely ignoring the - * ns parameter.</p> - * - * @param ns The namespace for the property (currently not used). - * @param name The name of property to set. - * Must not be <code>null</code>. - * @param value The new value of the property. - * Must not be <code>null</code>. - * @since Ant 1.6 - * @deprecated namespaces are unnecessary. - */ - public void setNewProperty(String ns, String name, Object value) { - setNewProperty(name, value); - } - - /** - * Sets a property if no value currently exists. If the property - * exists already, a message is logged and the method returns with - * no other effect. - * - * @param name The name of property to set. - * Must not be <code>null</code>. - * @param value The new value of the property. - * Must not be <code>null</code>. - * @since Ant 1.8.0 - */ - public void setNewProperty(String name, Object value) { - for (PropertySetter setter : getDelegates(PropertySetter.class)) { - if (setter.setNew(name, value, this)) { - return; - } - } - synchronized (this) { - if (project != null && properties.containsKey(name)) { - project.log("Override ignored for property \"" + name - + "\"", Project.MSG_VERBOSE); - return; - } - if (project != null) { - project.log("Setting project property: " + name - + " -> " + value, Project.MSG_DEBUG); - } - if (name != null && value != null) { - properties.put(name, value); - } - } - } - - /** - * Sets a user property, which cannot be overwritten by - * set/unset property calls. Any previous value is overwritten. - * - * <p>Delegates to the two-arg version, completely ignoring the - * ns parameter.</p> - * - * @param ns The namespace for the property (currently not used). - * @param name The name of property to set. - * Must not be <code>null</code>. - * @param value The new value of the property. - * Must not be <code>null</code>. - * @deprecated namespaces are unnecessary. - */ - public void setUserProperty(String ns, String name, Object value) { - setUserProperty(name, value); - } - - /** - * Sets a user property, which cannot be overwritten by - * set/unset property calls. Any previous value is overwritten. - * - * <p>Does <code>not</code> consult any delegates.</p> - * - * @param name The name of property to set. - * Must not be <code>null</code>. - * @param value The new value of the property. - * Must not be <code>null</code>. - */ - public void setUserProperty(String name, Object value) { - if (project != null) { - project.log("Setting ro project property: " - + name + " -> " + value, Project.MSG_DEBUG); - } - synchronized (this) { - userProperties.put(name, value); - properties.put(name, value); - } - } - - /** - * Sets an inherited user property, which cannot be overwritten by set/unset - * property calls. Any previous value is overwritten. Also marks - * these properties as properties that have not come from the - * command line. - * - * <p>Delegates to the two-arg version, completely ignoring the - * ns parameter.</p> - * - * @param ns The namespace for the property (currently not used). - * @param name The name of property to set. - * Must not be <code>null</code>. - * @param value The new value of the property. - * Must not be <code>null</code>. - * @deprecated namespaces are unnecessary. - */ - public void setInheritedProperty(String ns, String name, Object value) { - setInheritedProperty(name, value); - } - - /** - * Sets an inherited user property, which cannot be overwritten by set/unset - * property calls. Any previous value is overwritten. Also marks - * these properties as properties that have not come from the - * command line. - * - * <p>Does <code>not</code> consult any delegates.</p> - * - * @param name The name of property to set. - * Must not be <code>null</code>. - * @param value The new value of the property. - * Must not be <code>null</code>. - */ - public void setInheritedProperty(String name, Object value) { - if (project != null) { - project.log("Setting ro project property: " + name + " -> " - + value, Project.MSG_DEBUG); - } - - synchronized (this) { - inheritedProperties.put(name, value); - userProperties.put(name, value); - properties.put(name, value); - } - } - - // -------------------- Getting properties -------------------- - - /** - * Returns the value of a property, if it is set. You can override - * this method in order to plug your own storage. - * - * <p>Delegates to the one-arg version ignoring the ns parameter.</p> - * - * @param ns The namespace for the property (currently not used). - * @param name The name of the property. - * May be <code>null</code>, in which case - * the return value is also <code>null</code>. - * @return the property value, or <code>null</code> for no match - * or if a <code>null</code> name is provided. - * @deprecated namespaces are unnecessary. - */ - public Object getProperty(String ns, String name) { - return getProperty(name); - } - - /** - * Returns the value of a property, if it is set. - * - * <p>This is the method that is invoked by {Project#getProperty - * Project.getProperty}.</p> - * - * <p>You can override this method in order to plug your own - * storage but the recommended approach is to add your own - * implementation of {@link PropertyEvaluator PropertyEvaluator} - * instead.</p> - * - * @param name The name of the property. - * May be <code>null</code>, in which case - * the return value is also <code>null</code>. - * @return the property value, or <code>null</code> for no match - * or if a <code>null</code> name is provided. - */ - public Object getProperty(String name) { - if (name == null) { - return null; - } - for (PropertyEvaluator evaluator : getDelegates(PropertyEvaluator.class)) { - final Object o = evaluator.evaluate(name, this); - if (o == null) { - continue; - } - return o instanceof NullReturn ? null : o; - } - return properties.get(name); - } - - /** - * Returns the value of a user property, if it is set. - * - * <p>Delegates to the one-arg version ignoring the ns parameter.</p> - * - * @param ns The namespace for the property (currently not used). - * @param name The name of the property. - * May be <code>null</code>, in which case - * the return value is also <code>null</code>. - * @return the property value, or <code>null</code> for no match - * or if a <code>null</code> name is provided. - * @deprecated namespaces are unnecessary. - */ - public Object getUserProperty(String ns, String name) { - return getUserProperty(name); - } - - /** - * Returns the value of a user property, if it is set. - * - * <p>Does <code>not</code> consult any delegates.</p> - * - * @param name The name of the property. - * May be <code>null</code>, in which case - * the return value is also <code>null</code>. - * @return the property value, or <code>null</code> for no match - * or if a <code>null</code> name is provided. - */ - public Object getUserProperty(String name) { - if (name == null) { - return null; - } - return userProperties.get(name); - } - - // -------------------- Access to property tables -------------------- - // This is used to support ant call and similar tasks. It should be - // deprecated, it is possible to use a better (more efficient) - // mechanism to preserve the context. - - /** - * Returns a copy of the properties table. - * - * <p>Does not contain properties held by implementations of - * delegates (like local properties).</p> - * - * @return a hashtable containing all properties (including user properties). - */ - public Hashtable<String, Object> getProperties() { - //avoid concurrent modification: - synchronized (properties) { - return new Hashtable<String, Object>(properties); - } - // There is a better way to save the context. This shouldn't - // delegate to next, it's for backward compatibility only. - } - - /** - * Returns a copy of the user property hashtable - * - * <p>Does not contain properties held by implementations of - * delegates (like local properties).</p> - * - * @return a hashtable containing just the user properties - */ - public Hashtable<String, Object> getUserProperties() { - //avoid concurrent modification: - synchronized (userProperties) { - return new Hashtable<String, Object>(userProperties); - } - } - - /** - * Returns a copy of the inherited property hashtable - * - * <p>Does not contain properties held by implementations of - * delegates (like local properties).</p> - * - * @return a hashtable containing just the inherited properties - */ - public Hashtable<String, Object> getInheritedProperties() { - //avoid concurrent modification: - synchronized (inheritedProperties) { - return new Hashtable<String, Object>(inheritedProperties); - } - } - - /** - * special back door for subclasses, internal access to the hashtables - * @return the live hashtable of all properties - */ - protected Hashtable<String, Object> getInternalProperties() { - return properties; - } - - /** - * special back door for subclasses, internal access to the hashtables - * - * @return the live hashtable of user properties - */ - protected Hashtable<String, Object> getInternalUserProperties() { - return userProperties; - } - - /** - * special back door for subclasses, internal access to the hashtables - * - * @return the live hashtable inherited properties - */ - protected Hashtable<String, Object> getInternalInheritedProperties() { - return inheritedProperties; - } - - /** - * Copies all user properties that have not been set on the - * command line or a GUI tool from this instance to the Project - * instance given as the argument. - * - * <p>To copy all "user" properties, you will also have to call - * {@link #copyUserProperties copyUserProperties}.</p> - * - * <p>Does not copy properties held by implementations of - * delegates (like local properties).</p> - * - * @param other the project to copy the properties to. Must not be null. - * - * @since Ant 1.6 - */ - public void copyInheritedProperties(Project other) { - //avoid concurrent modification: - synchronized (inheritedProperties) { - Enumeration<String> e = inheritedProperties.keys(); - while (e.hasMoreElements()) { - String arg = e.nextElement().toString(); - if (other.getUserProperty(arg) != null) { - continue; - } - Object value = inheritedProperties.get(arg); - other.setInheritedProperty(arg, value.toString()); - } - } - } - - /** - * Copies all user properties that have been set on the command - * line or a GUI tool from this instance to the Project instance - * given as the argument. - * - * <p>To copy all "user" properties, you will also have to call - * {@link #copyInheritedProperties copyInheritedProperties}.</p> - * - * <p>Does not copy properties held by implementations of - * delegates (like local properties).</p> - * - * @param other the project to copy the properties to. Must not be null. - * - * @since Ant 1.6 - */ - public void copyUserProperties(Project other) { - //avoid concurrent modification: - synchronized (userProperties) { - Enumeration<String> e = userProperties.keys(); - while (e.hasMoreElements()) { - Object arg = e.nextElement(); - if (inheritedProperties.containsKey(arg)) { - continue; - } - Object value = userProperties.get(arg); - other.setUserProperty(arg.toString(), value.toString()); - } - } - } - - // -------------------- Property parsing -------------------- - // Moved from ProjectHelper. You can override the static method - - // this is used for backward compatibility (for code that calls - // the parse method in ProjectHelper). - - /** - * Default parsing method. It is here only to support backward compatibility - * for the static ProjectHelper.parsePropertyString(). - */ - static void parsePropertyStringDefault(String value, Vector<String> fragments, Vector<String> propertyRefs) - throws BuildException { - int prev = 0; - int pos; - //search for the next instance of $ from the 'prev' position - while ((pos = value.indexOf("$", prev)) >= 0) { - - //if there was any text before this, add it as a fragment - //TODO, this check could be modified to go if pos>prev; - //seems like this current version could stick empty strings - //into the list - if (pos > 0) { - fragments.addElement(value.substring(prev, pos)); - } - //if we are at the end of the string, we tack on a $ - //then move past it - if (pos == (value.length() - 1)) { - fragments.addElement("$"); - prev = pos + 1; - } else if (value.charAt(pos + 1) != '{') { - //peek ahead to see if the next char is a property or not - //not a property: insert the char as a literal - /* - fragments.addElement(value.substring(pos + 1, pos + 2)); - prev = pos + 2; - */ - if (value.charAt(pos + 1) == '$') { - //backwards compatibility two $ map to one mode - fragments.addElement("$"); - prev = pos + 2; - } else { - //new behaviour: $X maps to $X for all values of X!='$' - fragments.addElement(value.substring(pos, pos + 2)); - prev = pos + 2; - } - } else { - //property found, extract its name or bail on a typo - int endName = value.indexOf('}', pos); - if (endName < 0) { - throw new BuildException("Syntax error in property: " + value); - } - String propertyName = value.substring(pos + 2, endName); - fragments.addElement(null); - propertyRefs.addElement(propertyName); - prev = endName + 1; - } - } - //no more $ signs found - //if there is any tail to the file, append it - if (prev < value.length()) { - fragments.addElement(value.substring(prev)); - } - } - - /** - * Add the specified delegate object to this PropertyHelper. - * Delegates are processed in LIFO order. - * @param delegate the delegate to add. - * @since Ant 1.8.0 - */ - public void add(Delegate delegate) { - synchronized (delegates) { - for (Class<? extends Delegate> key : getDelegateInterfaces(delegate)) { - List<Delegate> list = delegates.get(key); - if (list == null) { - list = new ArrayList<Delegate>(); - } else { - //copy on write, top priority - list = new ArrayList<Delegate>(list); - list.remove(delegate); - } - list.add(0, delegate); - delegates.put(key, Collections.unmodifiableList(list)); - } - } - } - - /** - * Get the Collection of delegates of the specified type. - * - * @param type - * delegate type. - * @return Collection. - * @since Ant 1.8.0 - */ - protected <D extends Delegate> List<D> getDelegates(Class<D> type) { - @SuppressWarnings("unchecked") - final List<D> result = (List<D>) delegates.get(type); - return result == null ? Collections.<D> emptyList() : result; - } - - /** - * Get all Delegate interfaces (excluding Delegate itself) from the specified Delegate. - * @param d the Delegate to inspect. - * @return Set<Class> - * @since Ant 1.8.0 - */ - protected static Set<Class<? extends Delegate>> getDelegateInterfaces(Delegate d) { - final HashSet<Class<? extends Delegate>> result = new HashSet<Class<? extends Delegate>>(); - Class<?> c = d.getClass(); - while (c != null) { - Class<?>[] ifs = c.getInterfaces(); - for (int i = 0; i < ifs.length; i++) { - if (Delegate.class.isAssignableFrom(ifs[i])) { - @SuppressWarnings("unchecked") - final Class<? extends Delegate> delegateInterface = (Class<? extends Delegate>) ifs[i]; - result.add(delegateInterface); - } - } - c = c.getSuperclass(); - } - result.remove(Delegate.class); - return result; - } - - /** - * If the given object can be interpreted as a true/false value, - * turn it into a matching Boolean - otherwise return null. - * @since Ant 1.8.0 - */ - public static Boolean toBoolean(Object value) { - if (value instanceof Boolean) { - return (Boolean) value; - } - if (value instanceof String) { - String s = (String) value; - if (Project.toBoolean(s)) { - return Boolean.TRUE; - } - if ("off".equalsIgnoreCase(s) - || "false".equalsIgnoreCase(s) - || "no".equalsIgnoreCase(s)) { - return Boolean.FALSE; - } - } - return null; - } - - /** - * Returns true if the object is null or an empty string. - * - * @since Ant 1.8.0 - */ - private static boolean nullOrEmpty(Object value) { - return value == null || "".equals(value); - - } - - /** - * Returns true if the value can be interpreted as a true value or - * cannot be interpreted as a false value and a property of the - * value's name exists. - * @since Ant 1.8.0 - */ - private boolean evalAsBooleanOrPropertyName(Object value) { - Boolean b = toBoolean(value); - if (b != null) { - return b.booleanValue(); - } - return getProperty(String.valueOf(value)) != null; - } - - /** - * Returns true if the value is null or an empty string, can be - * interpreted as a true value or cannot be interpreted as a false - * value and a property of the value's name exists. - * @since Ant 1.8.0 - */ - public boolean testIfCondition(Object value) { - return nullOrEmpty(value) || evalAsBooleanOrPropertyName(value); - } - - /** - * Returns true if the value is null or an empty string, can be - * interpreted as a false value or cannot be interpreted as a true - * value and a property of the value's name doesn't exist. - * @since Ant 1.8.0 - */ - public boolean testUnlessCondition(Object value) { - return nullOrEmpty(value) || !evalAsBooleanOrPropertyName(value); - } -} |