git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@908035 13f79535-47bb-0310-9956-ffa450edef68master
@@ -7,9 +7,18 @@ Changes that could break older environments: | |||||
Fixed bugs: | Fixed bugs: | ||||
----------- | ----------- | ||||
* Tasks that iterate over task or type definitions, references or | |||||
targets now iterate over copies instead of the live maps to avoid | |||||
ConcurrentModificationExceptions if another thread changes the | |||||
maps. | |||||
Bugzilla Report 48310. | |||||
Other changes: | Other changes: | ||||
-------------- | -------------- | ||||
* Project provides new get methods that return copies instead of the | |||||
live maps of task and type definitions, references and targets. | |||||
Changes from Ant 1.8.0RC1 TO Ant 1.8.0 | Changes from Ant 1.8.0RC1 TO Ant 1.8.0 | ||||
====================================== | ====================================== | ||||
@@ -425,10 +425,10 @@ public class Project implements ResourceFactory { | |||||
} | } | ||||
/** | /** | ||||
* Return a copy of the list of build listeners for the project. | |||||
* | |||||
* @return a list of build listeners for the project | |||||
*/ | |||||
* Return a copy of the list of build listeners for the project. | |||||
* | |||||
* @return a list of build listeners for the project | |||||
*/ | |||||
public Vector getBuildListeners() { | public Vector getBuildListeners() { | ||||
synchronized (listenersLock) { | synchronized (listenersLock) { | ||||
Vector r = new Vector(listeners.length); | Vector r = new Vector(listeners.length); | ||||
@@ -1024,6 +1024,19 @@ public class Project implements ResourceFactory { | |||||
return ComponentHelper.getComponentHelper(this).getTaskDefinitions(); | return ComponentHelper.getComponentHelper(this).getTaskDefinitions(); | ||||
} | } | ||||
/** | |||||
* Return the current task definition map. The returned map is a | |||||
* copy of the "live" definitions. | |||||
* | |||||
* @return a map of from task name to implementing class | |||||
* (String to Class). | |||||
* | |||||
* @since Ant 1.8.1 | |||||
*/ | |||||
public Map getCopyOfTaskDefinitions() { | |||||
return new HashMap(getTaskDefinitions()); | |||||
} | |||||
/** | /** | ||||
* Add a new datatype definition. | * Add a new datatype definition. | ||||
* Attempting to override an existing definition with an | * Attempting to override an existing definition with an | ||||
@@ -1053,6 +1066,19 @@ public class Project implements ResourceFactory { | |||||
return ComponentHelper.getComponentHelper(this).getDataTypeDefinitions(); | return ComponentHelper.getComponentHelper(this).getDataTypeDefinitions(); | ||||
} | } | ||||
/** | |||||
* Return the current datatype definition map. The returned | |||||
* map is a copy pf the "live" definitions. | |||||
* | |||||
* @return a map of from datatype name to implementing class | |||||
* (String to Class). | |||||
* | |||||
* @since Ant 1.8.1 | |||||
*/ | |||||
public Map getCopyOfDataTypeDefinitions() { | |||||
return new HashMap(getDataTypeDefinitions()); | |||||
} | |||||
/** | /** | ||||
* Add a <em>new</em> target to the project. | * Add a <em>new</em> target to the project. | ||||
* | * | ||||
@@ -1123,6 +1149,16 @@ public class Project implements ResourceFactory { | |||||
return targets; | return targets; | ||||
} | } | ||||
/** | |||||
* Return the map of targets. The returned map | |||||
* is a copy of the "live" targets. | |||||
* @return a map from name to target (String to Target). | |||||
* @since Ant 1.8.1 | |||||
*/ | |||||
public Map getCopyOfTargets() { | |||||
return new HashMap(targets); | |||||
} | |||||
/** | /** | ||||
* Create a new instance of a task, adding it to a list of | * Create a new instance of a task, adding it to a list of | ||||
* created tasks for later invalidation. This causes all tasks | * created tasks for later invalidation. This causes all tasks | ||||
@@ -1970,6 +2006,19 @@ public class Project implements ResourceFactory { | |||||
return references.containsKey(key); | return references.containsKey(key); | ||||
} | } | ||||
/** | |||||
* Return a map of the references in the project (String to | |||||
* Object). The returned hashtable is a copy of the | |||||
* "live" references. | |||||
* | |||||
* @return a map of the references in the project (String to Object). | |||||
* | |||||
* @since Ant 1.8.1 | |||||
*/ | |||||
public Map getCopyOfReferences() { | |||||
return new HashMap(references); | |||||
} | |||||
/** | /** | ||||
* Look up a reference by its key (ID). | * Look up a reference by its key (ID). | ||||
* | * | ||||
@@ -27,6 +27,7 @@ import java.io.PrintWriter; | |||||
import java.io.UnsupportedEncodingException; | import java.io.UnsupportedEncodingException; | ||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
import java.util.Hashtable; | import java.util.Hashtable; | ||||
import java.util.Iterator; | |||||
import java.util.Vector; | import java.util.Vector; | ||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.IntrospectionHelper; | import org.apache.tools.ant.IntrospectionHelper; | ||||
@@ -95,22 +96,24 @@ public class AntStructure extends Task { | |||||
} | } | ||||
printer.printHead(out, getProject(), | printer.printHead(out, getProject(), | ||||
getProject().getTaskDefinitions(), | |||||
getProject().getDataTypeDefinitions()); | |||||
new Hashtable(getProject().getTaskDefinitions()), | |||||
new Hashtable(getProject().getDataTypeDefinitions())); | |||||
printer.printTargetDecl(out); | printer.printTargetDecl(out); | ||||
Enumeration dataTypes = getProject().getDataTypeDefinitions().keys(); | |||||
while (dataTypes.hasMoreElements()) { | |||||
String typeName = (String) dataTypes.nextElement(); | |||||
Iterator dataTypes = getProject().getCopyOfDataTypeDefinitions() | |||||
.keySet().iterator(); | |||||
while (dataTypes.hasNext()) { | |||||
String typeName = (String) dataTypes.next(); | |||||
printer.printElementDecl( | printer.printElementDecl( | ||||
out, getProject(), typeName, | out, getProject(), typeName, | ||||
(Class) getProject().getDataTypeDefinitions().get(typeName)); | (Class) getProject().getDataTypeDefinitions().get(typeName)); | ||||
} | } | ||||
Enumeration tasks = getProject().getTaskDefinitions().keys(); | |||||
while (tasks.hasMoreElements()) { | |||||
String tName = (String) tasks.nextElement(); | |||||
Iterator tasks = getProject().getCopyOfTaskDefinitions().keySet() | |||||
.iterator(); | |||||
while (tasks.hasNext()) { | |||||
String tName = (String) tasks.next(); | |||||
printer.printElementDecl(out, getProject(), tName, | printer.printElementDecl(out, getProject(), tName, | ||||
(Class) getProject().getTaskDefinitions().get(tName)); | (Class) getProject().getTaskDefinitions().get(tName)); | ||||
} | } | ||||
@@ -306,8 +306,8 @@ public abstract class ScriptRunnerBase { | |||||
project = component.getProject(); | project = component.getProject(); | ||||
addBeans(project.getProperties()); | addBeans(project.getProperties()); | ||||
addBeans(project.getUserProperties()); | addBeans(project.getUserProperties()); | ||||
addBeans(project.getTargets()); | |||||
addBeans(project.getReferences()); | |||||
addBeans(project.getCopyOfTargets()); | |||||
addBeans(project.getCopyOfReferences()); | |||||
addBean("project", project); | addBean("project", project); | ||||
addBean("self", component); | addBean("self", component); | ||||
} | } | ||||