FileDocCategorySizeDatePackage
PropertyHelper.javaAPI DocApache Ant 1.7023540Wed Dec 13 06:16:18 GMT 2006org.apache.tools.ant

PropertyHelper

public class PropertyHelper extends Object
NOT FINAL. API MAY CHANGE Deals with properties - substitution, dynamic properties, etc. This is the same code as in Ant1.5. The main addition is the ability to chain multiple PropertyHelpers and to replace the default.
since
Ant 1.6

Fields Summary
private Project
project
private PropertyHelper
next
private Hashtable
properties
Project properties map (usually String to String).
private Hashtable
userProperties
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. Mapping is String to String.
private Hashtable
inheritedProperties
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. Mapping is String to String.
Constructors Summary
protected PropertyHelper()
Default constructor.


           
      
    
Methods Summary
public voidcopyInheritedProperties(Project other)
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.

To copy all "user" properties, you will also have to call {@link #copyUserProperties copyUserProperties}.

param
other the project to copy the properties to. Must not be null.
since
Ant 1.6

        Enumeration 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());
        }
    
public voidcopyUserProperties(Project other)
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.

To copy all "user" properties, you will also have to call {@link #copyInheritedProperties copyInheritedProperties}.

param
other the project to copy the properties to. Must not be null.
since
Ant 1.6

        Enumeration 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());
        }
    
protected java.util.HashtablegetInternalInheritedProperties()
special back door for subclasses, internal access to the hashtables

return
the live hashtable inherited properties

        return inheritedProperties;
    
protected java.util.HashtablegetInternalProperties()
special back door for subclasses, internal access to the hashtables

return
the live hashtable of all properties

        return properties;
    
protected java.util.HashtablegetInternalUserProperties()
special back door for subclasses, internal access to the hashtables

return
the live hashtable of user properties

        return userProperties;
    
public org.apache.tools.ant.PropertyHelpergetNext()
Get the next property helper in the chain.

return
the next property helper.

        return next;
    
public java.util.HashtablegetProperties()
Returns a copy of the properties table.

return
a hashtable containing all properties (including user properties).

        return new Hashtable(properties);
        // There is a better way to save the context. This shouldn't
        // delegate to next, it's for backward compatibility only.
    
public synchronized java.lang.ObjectgetProperty(java.lang.String ns, java.lang.String name)
Returns the value of a property, if it is set. You can override this method in order to plug your own storage.

param
ns The namespace for the property (currently not used).
param
name The name of the property. May be null, in which case the return value is also null.
return
the property value, or null for no match or if a null name is provided.

        if (name == null) {
            return null;
        }

        Object o = getPropertyHook(ns, name, false);
        if (o != null) {
            return o;
        }

        return properties.get(name);
    
public static synchronized org.apache.tools.ant.PropertyHelpergetPropertyHelper(Project project)
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 fro which the property helper is required.
return
the project's property helper.

        PropertyHelper helper
            = (PropertyHelper) project.getReference(MagicNames.REFID_PROPERTY_HELPER);
        if (helper != null) {
            return helper;
        }
        helper = new PropertyHelper();
        helper.setProject(project);

        project.addReference(MagicNames.REFID_PROPERTY_HELPER, helper);
        return helper;
    
public java.lang.ObjectgetPropertyHook(java.lang.String ns, java.lang.String name, boolean user)
Get a property. If all hooks return null, the default tables will be used.

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.

        if (getNext() != null) {
            Object o = getNext().getPropertyHook(ns, name, user);
            if (o != null) {
                return o;
            }
        }
        // Experimental/Testing, will be removed
        if (name.startsWith("toString:")) {
            name = name.substring("toString:".length());
            Object v = project.getReference(name);
            return (v == null) ? null : v.toString();
        }
        return null;
    
public java.util.HashtablegetUserProperties()
Returns a copy of the user property hashtable

return
a hashtable containing just the user properties

        return new Hashtable(userProperties);
    
public synchronized java.lang.ObjectgetUserProperty(java.lang.String ns, java.lang.String name)
Returns the value of a user property, if it is set.

param
ns The namespace for the property (currently not used).
param
name The name of the property. May be null, in which case the return value is also null.
return
the property value, or null for no match or if a null name is provided.

        if (name == null) {
            return null;
        }
        Object o = getPropertyHook(ns, name, true);
        if (o != null) {
            return o;
        }
        return  userProperties.get(name);
    
public voidparsePropertyString(java.lang.String value, java.util.Vector fragments, java.util.Vector propertyRefs)
Parses a string containing ${xxx} 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. null entries in the first list indicate a property reference from the second list. It can be overridden with a more efficient or customized version.

param
value Text to parse. Must not be null.
param
fragments List to add text fragments to. Must not be null.
param
propertyRefs List to add property names to. Must not be null.
exception
BuildException if the string contains an opening ${ without a closing }

        parsePropertyStringDefault(value, fragments, propertyRefs);
    
static voidparsePropertyStringDefault(java.lang.String value, java.util.Vector fragments, java.util.Vector propertyRefs)
Default parsing method. It is here only to support backward compatibility for the static ProjectHelper.parsePropertyString().

        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));
        }
    
public java.lang.StringreplaceProperties(java.lang.String ns, java.lang.String value, java.util.Hashtable keys)
Replaces ${xxx} style constructions in the given value with the string value of the corresponding data types.

param
ns The namespace for the property.
param
value The string to be scanned for property references. May be null, in which case this method returns immediately with no effect.
param
keys Mapping (String to String) of property names to their values. If null, only project properties will be used.
exception
BuildException if the string contains an opening ${ without a closing }
return
the original string with the properties replaced, or null if the original string is null.

        if (value == null || value.indexOf('$") == -1) {
            return value;
        }
        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();
                Object replacement = null;

                // try to get it from the project or keys
                // Backward compatibility
                if (keys != null) {
                    replacement = keys.get(propertyName);
                }
                if (replacement == null) {
                    replacement = getProperty(ns, propertyName);
                }

                if (replacement == null) {
                    project.log("Property \"" + propertyName
                            + "\" has not been set", Project.MSG_VERBOSE);
                }
                fragment = (replacement != null)
                        ? replacement.toString()
                        : "${" + propertyName + "}";
            }
            sb.append(fragment);
        }
        return sb.toString();
    
public synchronized voidsetInheritedProperty(java.lang.String ns, java.lang.String name, java.lang.Object 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.

param
ns The namespace for the property (currently not used).
param
name The name of property to set. Must not be null.
param
value The new value of the property. Must not be null.

        inheritedProperties.put(name, value);

        project.log("Setting ro project property: " + name + " -> "
            + value, Project.MSG_DEBUG);
        userProperties.put(name, value);

        boolean done = setPropertyHook(ns, name, value, true, false, false);
        if (done) {
            return;
        }
        properties.put(name, value);
    
public synchronized voidsetNewProperty(java.lang.String ns, java.lang.String name, java.lang.Object 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
ns The namespace for the property (currently not used).
param
name The name of property to set. Must not be null.
param
value The new value of the property. Must not be null.
since
Ant 1.6

        if (null != properties.get(name)) {
            project.log("Override ignored for property \"" + name
                + "\"", Project.MSG_VERBOSE);
            return;
        }

        boolean done = setPropertyHook(ns, name, value, false, false, true);
        if (done) {
            return;
        }

        project.log("Setting project property: " + name + " -> "
            + value, Project.MSG_DEBUG);
        if (name != null && value != null) {
            properties.put(name, value);
        }
    
public voidsetNext(org.apache.tools.ant.PropertyHelper next)
There are 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)

param
next the next property helper in the chain.

        this.next = next;
    
public voidsetProject(Project p)
Set the project for which this helper is performing property resolution

param
p the project instance.

        this.project = p;
    
public synchronized booleansetProperty(java.lang.String ns, java.lang.String name, java.lang.Object value, boolean verbose)
Default implementation of setProperty. Will be called from Project. This is the original 1.5 implementation, with calls to the hook added.

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.

        // user (CLI) properties take precedence
        if (null != userProperties.get(name)) {
            if (verbose) {
                project.log("Override ignored for user property \"" + name
                    + "\"", Project.MSG_VERBOSE);
            }
            return false;
        }

        boolean done = setPropertyHook(ns, name, value, false, false, false);
        if (done) {
            return true;
        }

        if (null != properties.get(name) && verbose) {
            project.log("Overriding previous definition of property \"" + name
                + "\"", Project.MSG_VERBOSE);
        }

        if (verbose) {
            project.log("Setting project property: " + name + " -> "
                + value, Project.MSG_DEBUG);
        }
        properties.put(name, value);
        return true;
    
public booleansetPropertyHook(java.lang.String ns, java.lang.String name, java.lang.Object value, boolean inherited, boolean user, boolean isNew)
Sets a property. Any existing property of the same name is overwritten, unless it is a user property. Will be called from setProperty(). If all helpers return false, the property will be saved in the default properties table by setProperty.

param
ns The namespace that the property is in (currently not used.
param
name The name of property to set. Must not be null.
param
value The new value of the property. Must not be null.
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).

        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;
    
public synchronized voidsetUserProperty(java.lang.String ns, java.lang.String name, java.lang.Object value)
Sets a user property, which cannot be overwritten by set/unset property calls. Any previous value is overwritten.

param
ns The namespace for the property (currently not used).
param
name The name of property to set. Must not be null.
param
value The new value of the property. Must not be null.

        project.log("Setting ro project property: " + name + " -> "
            + value, Project.MSG_DEBUG);
        userProperties.put(name, value);

        boolean done = setPropertyHook(ns, name, value, false, true, false);
        if (done) {
            return;
        }
        properties.put(name, value);