diff --git a/manual/properties.html b/manual/properties.html index c058af9d30..22476c4a00 100644 --- a/manual/properties.html +++ b/manual/properties.html @@ -154,6 +154,20 @@

PropertyHelpers

this would be org.apache.tools.ant.property.LocalProperties which implements storage for local properties.

+ +
  • org.apache.tools.ant.PropertyHelper$PropertyEnumerator + is responsible for enumerating property names. + +

    This is the interface you'd implement if you want to provide + your own storage independent of Ant's project + instance—the interface represents part of the reading + end. An example for this would + be org.apache.tools.ant.property.LocalProperties + which implements storage for local + properties.

    + +

    This interface has been added with Ant 1.10.9.

    +
  • The default PropertyExpander looks similar to:

    diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java index 3f34736510..6104e53e62 100644 --- a/src/main/org/apache/tools/ant/Project.java +++ b/src/main/org/apache/tools/ant/Project.java @@ -642,13 +642,23 @@ public String getUserProperty(final String propertyName) { /** * Return a copy of the properties table. - * @return a hashtable containing all properties - * (including user properties). + * @return a hashtable containing all properties (including user + * properties) known to the project directly, does not + * contain local properties. */ public Hashtable getProperties() { return PropertyHelper.getPropertyHelper(this).getProperties(); } + /** + * Returns the names of all known properties. + * @since 1.10.9 + * @return the names of all known properties including local user and local properties. + */ + public Set getPropertyNames() { + return PropertyHelper.getPropertyHelper(this).getPropertyNames(); + } + /** * Return a copy of the user property hashtable. * @return a hashtable containing just the user properties. diff --git a/src/main/org/apache/tools/ant/PropertyHelper.java b/src/main/org/apache/tools/ant/PropertyHelper.java index 154ffdfd9e..53ec6ee7a0 100644 --- a/src/main/org/apache/tools/ant/PropertyHelper.java +++ b/src/main/org/apache/tools/ant/PropertyHelper.java @@ -161,7 +161,19 @@ boolean set( String property, Object value, PropertyHelper propertyHelper); } - //TODO PropertyEnumerator Delegate type, would improve PropertySet + /** + * Obtains the names of all known properties. + * + * @since 1.10.9 + */ + public interface PropertyEnumerator extends Delegate { + /** + * Returns the names of all properties known to this delegate. + * + * @return the names of all properties known to this delegate. + */ + Set getPropertyNames(); + } // -------------------------------------------------------- // @@ -842,6 +854,18 @@ public Object getProperty(String name) { return properties.get(name); } + /** + * Returns the names of all known properties. + * @since 1.10.9 + * @return the names of all known properties. + */ + public Set getPropertyNames() { + final Set names = new HashSet<>(properties.keySet()); + getDelegates(PropertyEnumerator.class) + .forEach(e -> names.addAll(e.getPropertyNames())); + return Collections.unmodifiableSet(names); + } + /** * Returns the value of a user property, if it is set. * @@ -1014,7 +1038,7 @@ public void copyUserProperties(Project other) { // 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(). diff --git a/src/main/org/apache/tools/ant/property/LocalProperties.java b/src/main/org/apache/tools/ant/property/LocalProperties.java index 1dcbc26674..327f978ba4 100644 --- a/src/main/org/apache/tools/ant/property/LocalProperties.java +++ b/src/main/org/apache/tools/ant/property/LocalProperties.java @@ -21,6 +21,8 @@ import org.apache.tools.ant.Project; import org.apache.tools.ant.PropertyHelper; +import java.util.Set; + /** * Thread local class containing local properties. * @since Ant 1.8.0 @@ -28,7 +30,7 @@ public class LocalProperties extends InheritableThreadLocal implements PropertyHelper.PropertyEvaluator, - PropertyHelper.PropertySetter { + PropertyHelper.PropertySetter, PropertyHelper.PropertyEnumerator { /** * Get a localproperties for the given project. @@ -147,4 +149,9 @@ public boolean set( String property, Object value, PropertyHelper propertyHelper) { return get().set(property, value, propertyHelper); } + + @Override + public Set getPropertyNames() { + return get().getPropertyNames(); + } } diff --git a/src/main/org/apache/tools/ant/property/LocalPropertyStack.java b/src/main/org/apache/tools/ant/property/LocalPropertyStack.java index 3b80b43f26..95b301f429 100644 --- a/src/main/org/apache/tools/ant/property/LocalPropertyStack.java +++ b/src/main/org/apache/tools/ant/property/LocalPropertyStack.java @@ -17,10 +17,14 @@ */ package org.apache.tools.ant.property; +import java.util.Collections; import java.util.Deque; +import java.util.HashSet; import java.util.LinkedList; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collector; import org.apache.tools.ant.PropertyHelper; @@ -148,6 +152,20 @@ public boolean set(String property, Object value, PropertyHelper propertyHelper) return true; } + /** + * Returns the names of all known local properties. + * @since 1.10.9 + * @return the names of all known local properties. + */ + public Set getPropertyNames() { + final Set names = stack.stream().map(Map::keySet) + .collect(Collector.of(() -> new HashSet(), + (ns, ks) -> ns.addAll(ks), + (ns1, ns2) -> { ns1.addAll(ns2); return ns1; }, + Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH)); + return Collections.unmodifiableSet(names); + } + private Map getMapForProperty(String property) { synchronized (LOCK) { for (Map map : stack) { diff --git a/src/tests/junit/org/apache/tools/ant/PropertyHelperTest.java b/src/tests/junit/org/apache/tools/ant/PropertyHelperTest.java new file mode 100644 index 0000000000..883e5f148d --- /dev/null +++ b/src/tests/junit/org/apache/tools/ant/PropertyHelperTest.java @@ -0,0 +1,55 @@ +/* + * 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 + * + * https://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 org.apache.tools.ant.property.LocalProperties; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class PropertyHelperTest { + + @Test + public void findsPropertyNamesSetDirectly() { + Project p = new Project(); + p.setNewProperty("foo", "bar"); + assertTrue(p.getPropertyNames().contains("foo")); + } + + @Test + public void findsPropertyNamesSetForLocalProperties() { + Project p = new Project(); + p.setNewProperty("foo", "bar"); + + LocalProperties localProperties = LocalProperties.get(p); + localProperties.enterScope(); + localProperties.addLocal("baz"); + p.setNewProperty("baz", "xyzzy"); + + assertTrue(p.getPropertyNames().contains("foo")); + assertTrue(p.getPropertyNames().contains("baz")); + assertTrue(p.getProperties().keySet().contains("foo")); + assertFalse(p.getProperties().keySet().contains("baz")); + localProperties.exitScope(); + + assertTrue(p.getPropertyNames().contains("foo")); + assertFalse(p.getPropertyNames().contains("baz")); + } +}