ASF Bugzilla – Attachment 29236 Details for
Bug 53723
[Patch] Local task: local by prefix, all local, New: global task
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch with improved local task, the new global task and antunit test
local-global.patch (text/plain), 21.86 KB, created by
Ralf
on 2012-08-15 07:32:50 UTC
(
hide
)
Description:
Patch with improved local task, the new global task and antunit test
Filename:
MIME Type:
Creator:
Ralf
Created:
2012-08-15 07:32:50 UTC
Size:
21.86 KB
patch
obsolete
>Index: src/main/org/apache/tools/ant/taskdefs/Local.java >=================================================================== >--- src/main/org/apache/tools/ant/taskdefs/Local.java (revision 1372370) >+++ src/main/org/apache/tools/ant/taskdefs/Local.java (working copy) >@@ -17,6 +17,7 @@ > */ > package org.apache.tools.ant.taskdefs; > >+import org.apache.maven.artifact.resolver.WarningResolutionListener; > import org.apache.tools.ant.BuildException; > import org.apache.tools.ant.Task; > import org.apache.tools.ant.property.LocalProperties; >@@ -25,23 +26,60 @@ > * Task to create a local property in the current scope. > */ > public class Local extends Task { >- private String name; >+ private String name; >+ private String prefix; >+ >+ /** >+ * Set the name attribute. >+ * >+ * @param name >+ * the name of the local property. >+ */ >+ public void setName(String name) { >+ checkAlreadyConfigured(); >+ this.name = name; >+ } > >- /** >- * Set the name attribute. >- * @param name the name of the local property. >- */ >- public void setName(String name) { >- this.name = name; >- } >+ /** >+ * Set the prefix attribute. >+ * >+ * @param name >+ * the prefix to detect a local property. Must not be an empty >+ * string >+ */ >+ public void setPrefix(String prefix) { >+ checkAlreadyConfigured(); >+ if (prefix != null) { >+ if (prefix.length() == 0) { >+ throw new BuildException("Empty prefix not supported"); >+ } else if (!prefix.endsWith(".")) { >+ prefix = prefix + "."; >+ } >+ } >+ this.prefix = prefix; >+ } > >- /** >- * Run the task. >- */ >- public void execute() { >- if (name == null) { >- throw new BuildException("Missing attribute name"); >- } >- LocalProperties.get(getProject()).addLocal(name); >- } >+ /** >+ * Throw a BuildException if already one attribute was set. >+ */ >+ private void checkAlreadyConfigured() { >+ if (name != null || prefix != null) { >+ throw new BuildException( >+ "Only one of the attributes name or prefix is allowed"); >+ } >+ >+ } >+ >+ /** >+ * Run the task. >+ */ >+ public void execute() { >+ if (name != null) { >+ LocalProperties.get(getProject()).addLocal(name); >+ } else if (prefix != null) { >+ LocalProperties.get(getProject()).addLocalPrefix(prefix); >+ } else { >+ LocalProperties.get(getProject()).setAllLocal(); >+ } >+ } > } >Index: src/main/org/apache/tools/ant/taskdefs/Global.java >=================================================================== >--- src/main/org/apache/tools/ant/taskdefs/Global.java (revision 0) >+++ src/main/org/apache/tools/ant/taskdefs/Global.java (revision 0) >@@ -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.taskdefs; >+ >+import org.apache.tools.ant.BuildException; >+import org.apache.tools.ant.Task; >+import org.apache.tools.ant.property.LocalProperties; >+ >+/** >+ * Task to create a global property in the current scope. >+ * >+ * Only useful after visibility was restricted with the local task with the >+ * attributes prefix or all. >+ */ >+public class Global extends Task { >+ private String name; >+ private String prefix; >+ >+ /** >+ * Set the name attribute. >+ * >+ * @param name >+ * the name of the global property. >+ */ >+ public void setName(String name) { >+ checkAlreadyConfigured(); >+ this.name = name; >+ } >+ >+ /** >+ * Set the prefix attribute. >+ * >+ * @param name >+ * the prefix to detect a global property. >+ */ >+ public void setPrefix(String prefix) { >+ checkAlreadyConfigured(); >+ if (prefix != null) { >+ if (prefix.length() == 0) { >+ throw new BuildException("Empty prefix not supported"); >+ } else if (!prefix.endsWith(".")) { >+ prefix = prefix + "."; >+ } >+ } >+ this.prefix = prefix; >+ } >+ >+ /** >+ * Throw a BuildException if already one attribute was set. >+ */ >+ private void checkAlreadyConfigured() { >+ if (name != null || prefix != null) { >+ throw new BuildException( >+ "Only one of the attributes name or prefix is allowed"); >+ } >+ >+ } >+ >+ /** >+ * Run the task. >+ */ >+ public void execute() { >+ if (name != null) { >+ LocalProperties.get(getProject()).addGlobal(name); >+ } else if (prefix != null) { >+ LocalProperties.get(getProject()).addGlobalPrefix(prefix); >+ } >+ else { >+ throw new BuildException("Missing attribute. Either attribute name or prefix must be set"); >+ } >+ } >+} >Index: src/main/org/apache/tools/ant/taskdefs/defaults.properties >=================================================================== >--- src/main/org/apache/tools/ant/taskdefs/defaults.properties (revision 1372370) >+++ src/main/org/apache/tools/ant/taskdefs/defaults.properties (working copy) >@@ -56,6 +56,7 @@ > #funtest=org.apache.tools.ant.taskdefs.optional.testing.Funtest > genkey=org.apache.tools.ant.taskdefs.GenerateKey > get=org.apache.tools.ant.taskdefs.Get >+global=org.apache.tools.ant.taskdefs.Global > gunzip=org.apache.tools.ant.taskdefs.GUnzip > gzip=org.apache.tools.ant.taskdefs.GZip > hostinfo=org.apache.tools.ant.taskdefs.HostInfo >Index: src/main/org/apache/tools/ant/property/LocalPropertyStack.java >=================================================================== >--- src/main/org/apache/tools/ant/property/LocalPropertyStack.java (revision 1372370) >+++ src/main/org/apache/tools/ant/property/LocalPropertyStack.java (working copy) >@@ -17,35 +17,173 @@ > */ > package org.apache.tools.ant.property; > >- >-import java.util.LinkedList; > import java.util.HashMap; >+import java.util.HashSet; > import java.util.Iterator; >+import java.util.LinkedList; > import java.util.Map; >+import java.util.Set; > > import org.apache.tools.ant.PropertyHelper; > > /** >- * A stack of local property maps. >- * There is a map for each scope (target, sequential, macro). >+ * A stack of local property maps. There is a map for each scope (target, >+ * sequential, macro). >+ * > * @since Ant 1.8.0 > */ > public class LocalPropertyStack { >- private LinkedList stack = new LinkedList(); >+ >+ /** >+ * An entry in the property stack. >+ */ >+ private static class StackEntry { >+ /** Map of local properties. */ >+ private Map<String, Object> propertyMap; >+ /** >+ * Set of local prefixes. All variables with such a prefix are local. >+ */ >+ private Set<String> localPrefixSet; >+ /** If true, all properties in the current scope are local. */ >+ private boolean allLocal; >+ /** >+ * Properties named in this set are not local to this scope, even if >+ * they are named in propertyMap or have a prefix contained in >+ * localPrefixSet or allLocal is set. >+ */ >+ private Set<String> globalProperties; >+ /** >+ * Properties with a prefix contained in this set are not local to this >+ * scope, even if they are named in propertyMap or have a prefix >+ * contained in localPrefixSet or allLocal is set. >+ */ >+ private Set<String> globalPrefixSet; >+ >+ private StackEntry() { >+ propertyMap = new HashMap<String, Object>(); >+ localPrefixSet = new HashSet<String>(); >+ globalProperties = new HashSet<String>(); >+ globalPrefixSet = new HashSet<String>(); >+ } >+ >+ private void clear() { >+ propertyMap.clear(); >+ localPrefixSet.clear(); >+ globalPrefixSet.clear(); >+ globalProperties.clear(); >+ propertyMap = null; >+ localPrefixSet = null; >+ globalPrefixSet = null; >+ globalProperties = null; >+ } >+ >+ /** >+ * Determine if the given property is local to this scope. >+ * >+ * @param property >+ * property name to check >+ * @return true if it is local, else false >+ */ >+ private boolean isLocalProperty(String property) { >+ if (globalProperties.contains(property)) { >+ return false; >+ } >+ for (Iterator<String> prefixIter = globalPrefixSet.iterator(); prefixIter >+ .hasNext();) { >+ if (property.startsWith(prefixIter.next())) { >+ return false; >+ } >+ } >+ >+ if (allLocal) { >+ return true; >+ } >+ if (propertyMap.get(property) != null) { >+ return true; >+ } >+ for (Iterator<String> prefixIter = localPrefixSet.iterator(); prefixIter >+ .hasNext();) { >+ if (property.startsWith(prefixIter.next())) { >+ return true; >+ } >+ } >+ >+ return false; >+ } >+ >+ } >+ >+ private LinkedList<StackEntry> stack = new LinkedList<StackEntry>(); > > // -------------------------------------------------- > // >- // Local property adding and scoping >+ // Local property adding and scoping > // > // -------------------------------------------------- > > /** > * Add a local property. >- * @param property the name of the local property. >+ * >+ * @param property >+ * the name of the local property. > */ > public void addLocal(String property) { > if (!stack.isEmpty()) { >- ((Map) stack.getFirst()).put(property, NullReturn.NULL); >+ stack.getFirst().propertyMap.put(property, NullReturn.NULL); >+ } >+ } >+ >+ /** >+ * Add a local prefix. All properties with this prefix are handled as local >+ * property. >+ * >+ * @param prefix >+ * the prefix to detect a local property. >+ */ >+ public void addLocalPrefix(String prefix) { >+ if (!stack.isEmpty()) { >+ stack.getFirst().localPrefixSet.add(prefix); >+ } >+ } >+ >+ /** >+ * Set all properties in the current scope as local. >+ */ >+ public void setAllLocal() { >+ if (!stack.isEmpty()) { >+ stack.getFirst().allLocal = true; >+ } >+ } >+ >+ /** >+ * Add a global property. >+ * >+ * This is useful if the visibility of properties were restricted with >+ * {@link #addLocalPrefix(String)} or {@link #setAllLocal()} but a certain >+ * property should be global. >+ * >+ * @param property >+ * the name of the global property. >+ */ >+ public void addGlobal(String property) { >+ if (!stack.isEmpty()) { >+ stack.getFirst().globalProperties.add(property); >+ } >+ } >+ >+ /** >+ * Add a global prefix. >+ * >+ * This is useful if the visibility of properties were restricted with >+ * {@link #setAllLocal()} but properties with the given prefix should be >+ * global. >+ * >+ * @param prefix >+ * the prefix to detect a global property. >+ */ >+ public void addGlobalPrefix(String prefix) { >+ if (!stack.isEmpty()) { >+ stack.getFirst().globalPrefixSet.add(prefix); > } > } > >@@ -53,24 +191,25 @@ > * Enter the local scope. > */ > public void enterScope() { >- stack.addFirst(new HashMap()); >+ stack.addFirst(new StackEntry()); > } > > /** > * Exit the local scope. > */ > public void exitScope() { >- ((HashMap) stack.removeFirst()).clear(); >+ ((StackEntry) stack.removeFirst()).clear(); > } > > // -------------------------------------------------- > // >- // Copy - used in parallel to make a new stack >+ // Copy - used in parallel to make a new stack > // > // -------------------------------------------------- > > /** > * Copy the stack for a parallel thread. >+ * > * @return a copy. > */ > public LocalPropertyStack copy() { >@@ -81,42 +220,51 @@ > > // -------------------------------------------------- > // >- // PropertyHelper delegate methods >+ // PropertyHelper delegate methods > // > // -------------------------------------------------- > > /** > * Evaluate a property. >- * @param property the property's String "identifier". >- * @param helper the invoking PropertyHelper. >+ * >+ * @param property >+ * the property's String "identifier". >+ * @param helper >+ * the invoking PropertyHelper. > * @return Object value. > */ > public Object evaluate(String property, PropertyHelper helper) { >- for (Iterator i = stack.iterator(); i.hasNext();) { >- Map map = (Map) i.next(); >- Object ret = map.get(property); >- if (ret != null) { >- return ret; >- } >+ Map<String, Object> map = getMapForProperty(property); >+ if (map == null) { >+ return null; >+ } >+ Object ret = map.get(property); >+ if (ret != null) { >+ // Note: NullReturn.NULL is handled on upper level. >+ return ret; > } > return null; > } > > /** > * Set a *new" property. >- * @param property the property's String "identifier". >- * @param value the value to set. >- * @param propertyHelper the invoking PropertyHelper. >+ * >+ * @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. > */ >- public boolean setNew( >- String property, Object value, PropertyHelper propertyHelper) { >- Map map = getMapForProperty(property); >+ public boolean setNew(String property, Object value, >+ PropertyHelper propertyHelper) { >+ Map<String, Object> map = getMapForProperty(property); > if (map == null) { > return false; > } > Object currValue = map.get(property); >- if (currValue == NullReturn.NULL) { >+ if (currValue == NullReturn.NULL || !map.containsKey(property)) { > map.put(property, value); > } > return true; >@@ -124,13 +272,18 @@ > > /** > * Set a property. >- * @param property the property's String "identifier". >- * @param value the value to set. >- * @param propertyHelper the invoking PropertyHelper. >+ * >+ * @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. > */ >- public boolean set(String property, Object value, PropertyHelper propertyHelper) { >- Map map = getMapForProperty(property); >+ public boolean set(String property, Object value, >+ PropertyHelper propertyHelper) { >+ Map<String, Object> map = getMapForProperty(property); > if (map == null) { > return false; > } >@@ -138,14 +291,13 @@ > return true; > } > >- private Map getMapForProperty(String property) { >- for (Iterator i = stack.iterator(); i.hasNext();) { >- Map map = (Map) i.next(); >- if (map.get(property) != null) { >- return map; >+ private Map<String, Object> getMapForProperty(String property) { >+ for (Iterator<StackEntry> i = stack.iterator(); i.hasNext();) { >+ StackEntry se = i.next(); >+ if (se.isLocalProperty(property)) { >+ return se.propertyMap; > } > } > return null; > } > } >- >Index: src/main/org/apache/tools/ant/property/LocalProperties.java >=================================================================== >--- src/main/org/apache/tools/ant/property/LocalProperties.java (revision 1372370) >+++ src/main/org/apache/tools/ant/property/LocalProperties.java (working copy) >@@ -26,7 +26,7 @@ > * @since Ant 1.8.0 > */ > public class LocalProperties >- extends InheritableThreadLocal >+ extends InheritableThreadLocal<LocalPropertyStack> > implements PropertyHelper.PropertyEvaluator, > PropertyHelper.PropertySetter { > >@@ -62,7 +62,7 @@ > * Get the initial value. > * @return a new localproperties stack. > */ >- protected synchronized Object initialValue() { >+ protected synchronized LocalPropertyStack initialValue() { > return new LocalPropertyStack(); > } > >@@ -84,6 +84,38 @@ > current().addLocal(property); > } > >+ /** >+ * Add a local prefix to the current scope. >+ * @param prefix the prefix to add. >+ */ >+ public void addLocalPrefix(String prefix) { >+ current().addLocalPrefix(prefix); >+ } >+ >+ /** >+ * Add a local prefix to the current scope. >+ * @param property the prefix to add. >+ */ >+ public void setAllLocal() { >+ current().setAllLocal(); >+ } >+ >+ /** >+ * Add a global property to the current scope. >+ * @param property the property name to add. >+ */ >+ public void addGlobal(String property) { >+ current().addGlobal(property); >+ } >+ >+ /** >+ * Add a global prefix to the current scope. >+ * @param property the prefix to add. >+ */ >+ public void addGlobalPrefix(String prefix) { >+ current().addGlobalPrefix(prefix); >+ } >+ > /** enter the scope */ > public void enterScope() { > current().enterScope(); >Index: src/tests/antunit/taskdefs/local-test.xml >=================================================================== >--- src/tests/antunit/taskdefs/local-test.xml (revision 1372370) >+++ src/tests/antunit/taskdefs/local-test.xml (working copy) >@@ -19,6 +19,7 @@ > <import file="../antunit-base.xml" /> > > <property name="foo" value="foo" /> >+ <property name="prefix.foo" value="prefix.foo" /> > > <local name="bar" /> > <property name="bar" value="bar" /> >@@ -93,4 +94,108 @@ > <au:assertPropertyEquals name="foo" value="foo" /> > </target> > >+ <target name="testLocalPrefix"> >+ <sequential> >+ <local prefix="prefix" /> >+ <property name="prefix.foo" value="foo.1" /> >+ <sequential> >+ <local prefix="prefix" /> >+ <property name="prefix.foo" value="foo.2" /> >+ <au:assertPropertyEquals name="prefix.foo" value="foo.2" /> >+ </sequential> >+ <au:assertPropertyEquals name="prefix.foo" value="foo.1" /> >+ </sequential> >+ <au:assertPropertyEquals name="prefix.foo" value="prefix.foo" /> >+ </target> >+ >+ <target name="testAllLocal"> >+ <sequential> >+ <local name="foo" /> >+ <property name="foo" value="foo.1" /> >+ <sequential> >+ <local /> >+ <property name="foo" value="foo.2" /> >+ <au:assertPropertyEquals name="foo" value="foo.2" /> >+ </sequential> >+ <au:assertPropertyEquals name="foo" value="foo.1" /> >+ </sequential> >+ <au:assertPropertyEquals name="foo" value="foo" /> >+ </target> >+ >+ <target name="testGlobal"> >+ <sequential> >+ <local name="foo" /> >+ <property name="foo" value="foo.1" /> >+ <sequential> >+ <local /> >+ <global name="gFoo" /> >+ <property name="foo" value="foo.2" /> >+ <property name="gFoo" value="global" /> >+ <au:assertPropertyEquals name="foo" value="foo.2" /> >+ </sequential> >+ <au:assertPropertyEquals name="foo" value="foo.1" /> >+ </sequential> >+ <au:assertPropertyEquals name="foo" value="foo" /> >+ <au:assertPropertyEquals name="gFoo" value="global" /> >+ </target> >+ >+ <target name="testGlobalPrefix"> >+ <sequential> >+ <local name="foo" /> >+ <property name="foo" value="foo.1" /> >+ <sequential> >+ <local /> >+ <global prefix="global" /> >+ <property name="foo" value="foo.2" /> >+ <property name="global.foo" value="global" /> >+ <au:assertPropertyEquals name="foo" value="foo.2" /> >+ </sequential> >+ <au:assertPropertyEquals name="foo" value="foo.1" /> >+ </sequential> >+ <au:assertPropertyEquals name="foo" value="foo" /> >+ <au:assertPropertyEquals name="global.foo" value="global" /> >+ </target> >+ >+ <target name="testLocalAttributes"> >+ <au:expectfailure expectedMessage="Only one of the attributes name or prefix is allowed"> >+ <local name="name" prefix="prefix" /> >+ </au:expectfailure> >+ <au:expectfailure expectedMessage="Empty prefix not supported"> >+ <local prefix="" /> >+ </au:expectfailure> >+ </target> >+ >+ <target name="testGlobalAttributes"> >+ <au:expectfailure expectedMessage="Only one of the attributes name or prefix is allowed"> >+ <global name="name" prefix="prefix" /> >+ </au:expectfailure> >+ <au:expectfailure expectedMessage="Empty prefix not supported"> >+ <global prefix="" /> >+ </au:expectfailure> >+ <au:expectfailure expectedMessage="Missing attribute. Either attribute name or prefix must be set"> >+ <global /> >+ </au:expectfailure> >+ </target> >+ >+ <target name="testStrangeUsage"> >+ <sequential> >+ <local name="strange" /> >+ <property name="strange" value="bar" /> >+ <au:assertPropertyEquals name="strange" value="bar" /> >+ <global name="strange" /> >+ <au:assertTrue message="Property 'strange' should not be set."> >+ <not> >+ <isset property="strange" /> >+ </not> >+ </au:assertTrue> >+ <property name="strange" value="bar2" /> >+ <au:assertPropertyEquals name="strange" value="bar2" /> >+ <local name="strange" /> >+ <au:assertPropertyEquals name="strange" value="bar2" /> >+ </sequential> >+ <au:assertPropertyEquals name="strange" value="bar2" /> >+ </target> >+ >+ >+ > </project>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 53723
: 29236