From 4c4ad3483de60ef46e02f3b4f217e78422ac5ab4 Mon Sep 17 00:00:00 2001 From: Scokart Gilles Date: Wed, 20 Aug 2008 13:28:52 +0000 Subject: [PATCH] Thread safety fix (list of delegates were modified and copied concurrently without common lock). The hashtable is thread safe and not published outside the class, so no need to copy it (synchronize non atomic modification is enought). However, the list contained in the delegates hashtable are published and should thus be copied. I put the copy in the add method so that the getDelegates doesn't need to be synchronized. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@687325 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/tools/ant/PropertyHelper.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main/org/apache/tools/ant/PropertyHelper.java b/src/main/org/apache/tools/ant/PropertyHelper.java index 2c7956405..02a621167 100644 --- a/src/main/org/apache/tools/ant/PropertyHelper.java +++ b/src/main/org/apache/tools/ant/PropertyHelper.java @@ -177,7 +177,7 @@ public class PropertyHelper implements GetProperty { private Project project; private PropertyHelper next; - private volatile Hashtable delegates = new Hashtable(); + private Hashtable delegates = new Hashtable(); /** Project properties map (usually String to String). */ private Hashtable properties = new Hashtable(); @@ -924,35 +924,33 @@ public class PropertyHelper implements GetProperty { * @since Ant 1.8 */ public void add(Delegate delegate) { - synchronized (Delegate.class) { - Hashtable newDelegates = (Hashtable) delegates.clone(); + synchronized (delegates) { for (Iterator iter = getDelegateInterfaces(delegate).iterator(); iter.hasNext();) { Object key = iter.next(); - List list = (List) newDelegates.get(key); + List list = (List) delegates.get(key); if (list == null) { list = new ArrayList(); - newDelegates.put(key, list); - } - if (list.contains(delegate)) { + } else { + list = new ArrayList(list); list.remove(delegate); } list.add(0, delegate); + delegates.put(key, Collections.unmodifiableList(list)); } - delegates = newDelegates; } } /** * Get the Collection of delegates of the specified type. - * @param type delegate type. + * + * @param type + * delegate type. * @return Collection. * @since Ant 1.8 */ protected List getDelegates(Class type) { - Hashtable curDelegates = delegates; - return curDelegates.containsKey(type) - ? (List) new ArrayList((List) curDelegates.get(type)) - : Collections.EMPTY_LIST; + List r = (List) delegates.get(type); + return r == null ? Collections.EMPTY_LIST : r; } /**