diff --git a/WHATSNEW b/WHATSNEW index eae9c772a..6e96a642e 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -305,6 +305,9 @@ Other changes: * Users can now modify the list of default excludes using the new defaultexcludes task. Bugzilla Report 12700. +* There is a new data type that can be used to collect + properties. + Changes from Ant 1.5.2 to Ant 1.5.3 =================================== diff --git a/src/main/org/apache/tools/ant/types/PropertySet.java b/src/main/org/apache/tools/ant/types/PropertySet.java new file mode 100644 index 000000000..554fce676 --- /dev/null +++ b/src/main/org/apache/tools/ant/types/PropertySet.java @@ -0,0 +1,315 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Ant" and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.types; + +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Properties; +import java.util.Stack; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Property; +import org.apache.tools.ant.util.FileNameMapper; +import org.apache.tools.ant.util.regexp.RegexpMatcher; +import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; + +/** + * A set of properties. + * + * @author Dominique Devienne + * @since Ant 1.6 + */ +public class PropertySet extends DataType { + + private boolean dynamic = true; + private Vector cachedNames; + private Vector ptyRefs = new Vector(); + private Vector setRefs = new Vector(); + private Mapper _mapper; + + public static class PropertyRef { + + private int count; + private String name; + private String regex; + private String prefix; + + public void setName(String name) { + assertValid("name", name); + this.name = name; + } + + public void setRegex(String regex) { + assertValid("regex", regex); + this.regex = regex; + } + + public void setPrefix(String prefix) { + assertValid("prefix", prefix); + this.prefix = prefix; + } + + private void assertValid(String attr, String value) { + if (value == null || value.length() < 1) { + throw new BuildException("Invalid attribute: " + attr); + } + + if (++count != 1) { + throw new BuildException("Attributes name, regex, and " + + "prefix are mutually exclusive"); + } + } + + public String toString() { + return "name=" + name + ", regex=" + regex + ", prefix=" + prefix; + } + + } + + public void appendName(String name) { + PropertyRef ref = new PropertyRef(); + ref.setName(name); + addPropertyref(ref); + } + + public void appendRegex(String regex) { + PropertyRef ref = new PropertyRef(); + ref.setRegex(regex); + addPropertyref(ref); + } + + public void appendPrefix(String prefix) { + PropertyRef ref = new PropertyRef(); + ref.setPrefix(prefix); + addPropertyref(ref); + } + + public void setMapper(String type, String from, String to) { + Mapper mapper = createMapper(); + Mapper.MapperType mapperType = new Mapper.MapperType(); + mapperType.setValue(type); + mapper.setFrom(from); + mapper.setTo(to); + } + + public void addPropertyref(PropertyRef ref) { + assertNotReference(); + ptyRefs.addElement(ref); + } + + public void addPropertyset(PropertySet ref) { + assertNotReference(); + setRefs.addElement(ref); + } + + public Mapper createMapper() { + assertNotReference(); + if (_mapper != null) { + throw new BuildException("Too many s!"); + } + _mapper = new Mapper(getProject()); + return _mapper; + } + + public void setDynamic(boolean dynamic) { + assertNotReference(); + this.dynamic = dynamic; + } + + public boolean getDynamic() { + return getRef().dynamic; + } + + public Properties getProperties() { + Vector names = null; + Project prj = getProject(); + + if (getDynamic() || cachedNames == null) { + names = new Vector(); // :TODO: should be a Set! + getRef().addPropertyNames(names, prj.getProperties()); + if (!getDynamic()) { + cachedNames = names; + } + } + else { + names = cachedNames; + } + + FileNameMapper mapper = null; + if (_mapper != null) { + mapper = _mapper.getImplementation(); + } + Properties properties = new Properties(); + for (Enumeration e = names.elements(); e.hasMoreElements();) { + String name = (String) e.nextElement(); + String value = prj.getProperty(name); + if (mapper != null) { + String[] newname = mapper.mapFileName(name); + if (newname != null) { + name = newname[0]; + } + } + properties.setProperty(name, value); + } + return properties; + } + + /** + * @param names the output vector to fill with the property names + * matching this PropertySet selection criteria. + * @param properties the current Project properties, passed in to + * avoid needless duplication of the Hashtable during recursion. + */ + private void addPropertyNames(Vector names, Hashtable properties) { + Project prj = getProject(); + + // Add this PropertySet's property names. + for (Enumeration e = ptyRefs.elements(); e.hasMoreElements();) { + PropertyRef ref = (PropertyRef) e.nextElement(); + if (ref.name != null) { + if (prj.getProperty(ref.name) != null) { + names.addElement(ref.name); + } + } + else if (ref.prefix != null) { + for (Enumeration p = properties.keys(); p.hasMoreElements();) { + String name = (String) p.nextElement(); + if (name.startsWith(ref.prefix)) { + names.addElement(name); + } + } + } + else if (ref.regex != null) { + RegexpMatcherFactory matchMaker = new RegexpMatcherFactory(); + RegexpMatcher matcher = matchMaker.newRegexpMatcher(); + matcher.setPattern(ref.regex); + for (Enumeration p = properties.keys(); p.hasMoreElements();) { + String name = (String) p.nextElement(); + if (matcher.matches(name)) { + names.addElement(name); + } + } + } + else { + throw new BuildException("Impossible: Invalid PropertyRef!"); + } + } + + // Add this PropertySet's nested PropertySets' property names. + for (Enumeration e = setRefs.elements(); e.hasMoreElements();) { + PropertySet set = (PropertySet) e.nextElement(); + set.addPropertyNames(names, properties); + } + } + + /** + * Performs the check for circular references and returns the + * referenced FileList. + */ + protected PropertySet getRef() { + if (!isChecked()) { + Stack stk = new Stack(); + stk.push(this); + dieOnCircularReference(stk, getProject()); + } + + Object o = getRefid().getReferencedObject(getProject()); + if (!(o instanceof PropertySet)) { + String msg = getRefid().getRefId() + + " doesn\'t denote a propertyset"; + throw new BuildException(msg); + } else { + return (PropertySet) o; + } + } + + /** + * Sets the value of the refid attribute. + * + * @param r the reference this datatype should point to. + * @throws BuildException if another attribute was set, since + * refid and all other attributes are mutually exclusive. + */ + public final void setRefid(Reference r) { + if (!noAttributeSet) { + throw tooManyAttributes(); + } + super.setRefid(r); + } + + /** + * Ensures this data type is not a reference. + * + *

Calling this method as the first line of every bean method of + * this data type (setXyz, addXyz, createXyz) ensure proper handling + * of the refid attribute.

+ * + * @throws BuildException if the refid attribute was already set, since + * refid and all other attributes are mutually exclusive. + */ + protected final void assertNotReference() { + if (isReference()) { + throw tooManyAttributes(); + } + noAttributeSet = false; + } + private boolean noAttributeSet = true; +} // END class PropertySet + diff --git a/src/main/org/apache/tools/ant/types/defaults.properties b/src/main/org/apache/tools/ant/types/defaults.properties index fbe7d36cb..0b24f6c30 100644 --- a/src/main/org/apache/tools/ant/types/defaults.properties +++ b/src/main/org/apache/tools/ant/types/defaults.properties @@ -18,3 +18,4 @@ libfileset=org.apache.tools.ant.taskdefs.optional.extension.LibFileSet selector=org.apache.tools.ant.types.selectors.SelectSelector zipfileset=org.apache.tools.ant.types.ZipFileSet scriptfilter=org.apache.tools.ant.types.optional.ScriptFilter +propertyset=org.apache.tools.ant.types.PropertySet