diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java index 6893ae0508e..6f690fcdee2 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/MapProblemPreference.java @@ -12,9 +12,12 @@ package org.eclipse.cdt.codan.core.param; import java.io.IOException; import java.io.StreamTokenizer; +import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Map.Entry; import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences; @@ -30,9 +33,9 @@ import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences; * * @noextend This class is not intended to be extended by clients. */ -public class MapProblemPreference extends AbstractProblemPreference implements IProblemPreferenceCompositeValue, - IProblemPreferenceCompositeDescriptor { - protected LinkedHashMap hash = new LinkedHashMap(); +public class MapProblemPreference extends AbstractProblemPreference + implements IProblemPreferenceCompositeValue, IProblemPreferenceCompositeDescriptor { + private Map hash = Collections.synchronizedMap(new LinkedHashMap()); /** * Default constructor @@ -123,30 +126,34 @@ public class MapProblemPreference extends AbstractProblemPreference implements I @Override public Object clone() { MapProblemPreference map = (MapProblemPreference) super.clone(); - map.hash = new LinkedHashMap(); - for (Iterator iterator = hash.keySet().iterator(); iterator.hasNext();) { - String key = iterator.next(); - map.hash.put(key, (IProblemPreference) hash.get(key).clone()); + synchronized (hash) { + map.hash = Collections.synchronizedMap(new LinkedHashMap(hash)); + } + // now we have to clone the values too + for (Entry entry : map.hash.entrySet()) { + entry.setValue((IProblemPreference) entry.getValue().clone()); } return map; } @Override public String exportValue() { - StringBuffer buf = new StringBuffer("{"); //$NON-NLS-1$ - for (Iterator iterator = hash.keySet().iterator(); iterator.hasNext();) { - String key = iterator.next(); - IProblemPreference d = hash.get(key); - if (d instanceof AbstractProblemPreference) { - if (((AbstractProblemPreference) d).isDefault()) { - continue; + synchronized (hash) { + StringBuffer buf = new StringBuffer("{"); //$NON-NLS-1$ + for (Iterator iterator = hash.keySet().iterator(); iterator.hasNext();) { + String key = iterator.next(); + IProblemPreference d = hash.get(key); + if (d instanceof AbstractProblemPreference) { + if (((AbstractProblemPreference) d).isDefault()) { + continue; + } } + buf.append(key + "=>" + d.exportValue()); //$NON-NLS-1$ + if (iterator.hasNext()) + buf.append(","); //$NON-NLS-1$ } - buf.append(key + "=>" + d.exportValue()); //$NON-NLS-1$ - if (iterator.hasNext()) - buf.append(","); //$NON-NLS-1$ + return buf.toString() + "}"; //$NON-NLS-1$ } - return buf.toString() + "}"; //$NON-NLS-1$ } @Override @@ -243,12 +250,14 @@ public class MapProblemPreference extends AbstractProblemPreference implements I */ @Override public Object getValue() { - LinkedHashMap map = new LinkedHashMap(); - for (Iterator iterator = hash.values().iterator(); iterator.hasNext();) { - IProblemPreference pref = iterator.next(); - map.put(pref.getKey(), pref.getValue()); + synchronized (hash) { + LinkedHashMap map = new LinkedHashMap(); + for (Iterator iterator = hash.values().iterator(); iterator.hasNext();) { + IProblemPreference pref = iterator.next(); + map.put(pref.getKey(), pref.getValue()); + } + return map; } - return map; } /** @@ -263,19 +272,21 @@ public class MapProblemPreference extends AbstractProblemPreference implements I @Override public void setValue(Object value) { Map map = (Map) value; - LinkedHashMap hash2 = (LinkedHashMap) hash.clone(); - hash.clear(); - for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) { - String key = iterator.next(); - Object value2 = map.get(key); - if (value2 instanceof IProblemPreference) { - hash.put(key, (IProblemPreference) value2); - } else { - IProblemPreference pref = hash2.get(key); - addChildDescriptor(pref); - //setChildValue(key, value2); - pref.setValue(value2); - hash.put(key, pref); + synchronized (hash) { + Map hashCopy = new HashMap<>(hash); + hash.clear(); + for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) { + String key = iterator.next(); + Object value2 = map.get(key); + if (value2 instanceof IProblemPreference) { + hash.put(key, (IProblemPreference) value2); + } else { + IProblemPreference pref = hashCopy.get(key); + addChildDescriptor(pref); + //setChildValue(key, value2); + pref.setValue(value2); + hash.put(key, pref); + } } } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java index 09f6e266a80..9629281a9dc 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java @@ -20,7 +20,6 @@ public class SharedRootProblemPreference extends RootProblemPreference { public Object clone() { SharedRootProblemPreference map = (SharedRootProblemPreference) super.clone(); // alruiz: sharing the internal hash is the only way I could make this work. - map.hash = hash; return map; } }