Browse Source

Fixing a potential ConcurrentModificationException that could occur when running Ant with the Parallel-Ant executor.

This closes #81 pull request at github/apache/ant
master
mharmer Jaikiran Pai 6 years ago
parent
commit
41eb0d922b
4 changed files with 37 additions and 16 deletions
  1. +1
    -0
      CONTRIBUTORS
  2. +4
    -0
      WHATSNEW
  3. +4
    -0
      contributors.xml
  4. +28
    -16
      src/main/org/apache/tools/ant/Project.java

+ 1
- 0
CONTRIBUTORS View File

@@ -251,6 +251,7 @@ Mario Frasca
Mariusz Nowostawski Mariusz Nowostawski
Mark A. Ziesemer Mark A. Ziesemer
Mark DeLaFranier Mark DeLaFranier
Mark Harmer
Mark Hecker Mark Hecker
Mark Niggemann Mark Niggemann
Mark R. Diggory Mark R. Diggory


+ 4
- 0
WHATSNEW View File

@@ -33,6 +33,10 @@ Fixed bugs:
of the destination directory. of the destination directory.
Bugzilla Report 62890 Bugzilla Report 62890


* Fixes a potential java.util.ConcurrentModificationException in
org.apache.tools.ant.Project#getCopyOfReferences.
Github Pull Request #81



Other changes: Other changes:
-------------- --------------


+ 4
- 0
contributors.xml View File

@@ -1045,6 +1045,10 @@
<first>Mark</first> <first>Mark</first>
<last>DeLaFranier</last> <last>DeLaFranier</last>
</name> </name>
<name>
<first>Mark</first>
<last>Harmer</last>
</name>
<name> <name>
<first>Mark</first> <first>Mark</first>
<last>Hecker</last> <last>Hecker</last>


+ 28
- 16
src/main/org/apache/tools/ant/Project.java View File

@@ -140,6 +140,9 @@ public class Project implements ResourceFactory {
private String description; private String description;




/** lock object used when adding/removing references */
private final Object referencesLock = new Object();

/** Map of references within the project (paths etc) (String to Object). */ /** Map of references within the project (paths etc) (String to Object). */
private final Hashtable<String, Object> references = new AntRefTable(); private final Hashtable<String, Object> references = new AntRefTable();


@@ -1971,17 +1974,19 @@ public class Project implements ResourceFactory {
* @param value The value of the reference. * @param value The value of the reference.
*/ */
public void addReference(final String referenceName, final Object value) { public void addReference(final String referenceName, final Object value) {
final Object old = ((AntRefTable) references).getReal(referenceName);
if (old == value) {
// no warning, this is not changing anything
return;
}
if (old != null && !(old instanceof UnknownElement)) {
log("Overriding previous definition of reference to " + referenceName,
MSG_VERBOSE);
synchronized (referencesLock) {
final Object old = ((AntRefTable) references).getReal(referenceName);
if (old == value) {
// no warning, this is not changing anything
return;
}
if (old != null && !(old instanceof UnknownElement)) {
log("Overriding previous definition of reference to " + referenceName,
MSG_VERBOSE);
}
log("Adding reference: " + referenceName, MSG_DEBUG);
references.put(referenceName, value);
} }
log("Adding reference: " + referenceName, MSG_DEBUG);
references.put(referenceName, value);
} }


/** /**
@@ -2002,7 +2007,9 @@ public class Project implements ResourceFactory {
* @since Ant 1.8.0 * @since Ant 1.8.0
*/ */
public boolean hasReference(final String key) { public boolean hasReference(final String key) {
return references.containsKey(key);
synchronized (referencesLock) {
return references.containsKey(key);
}
} }


/** /**
@@ -2015,7 +2022,9 @@ public class Project implements ResourceFactory {
* @since Ant 1.8.1 * @since Ant 1.8.1
*/ */
public Map<String, Object> getCopyOfReferences() { public Map<String, Object> getCopyOfReferences() {
return new HashMap<>(references);
synchronized (referencesLock) {
return new HashMap<>(references);
}
} }


/** /**
@@ -2029,11 +2038,14 @@ public class Project implements ResourceFactory {
* there is no such reference in the project, with type inference. * there is no such reference in the project, with type inference.
*/ */
public <T> T getReference(final String key) { public <T> T getReference(final String key) {
@SuppressWarnings("unchecked")
final T ret = (T) references.get(key);
if (ret != null) {
return ret;
synchronized (referencesLock) {
@SuppressWarnings("unchecked")
final T ret = (T) references.get(key);
if (ret != null) {
return ret;
}
} }

if (!key.equals(MagicNames.REFID_PROPERTY_HELPER)) { if (!key.equals(MagicNames.REFID_PROPERTY_HELPER)) {
try { try {
if (PropertyHelper.getPropertyHelper(this).containsProperties(key)) { if (PropertyHelper.getPropertyHelper(this).containsProperties(key)) {


Loading…
Cancel
Save