1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 06:02:11 +02:00

Bug 489553 - ConcurrentModificationException below

MapProblemPreference.clone

Change-Id: If80417f386890495961745d13b3ad16040677e2e
This commit is contained in:
Alena Laskavaia 2016-03-14 11:17:07 -04:00 committed by Gerrit Code Review @ Eclipse.org
parent 6a7969bc85
commit d8a5d3cc0e
2 changed files with 47 additions and 37 deletions

View file

@ -12,9 +12,12 @@ package org.eclipse.cdt.codan.core.param;
import java.io.IOException; import java.io.IOException;
import java.io.StreamTokenizer; import java.io.StreamTokenizer;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences; 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. * @noextend This class is not intended to be extended by clients.
*/ */
public class MapProblemPreference extends AbstractProblemPreference implements IProblemPreferenceCompositeValue, public class MapProblemPreference extends AbstractProblemPreference
IProblemPreferenceCompositeDescriptor { implements IProblemPreferenceCompositeValue, IProblemPreferenceCompositeDescriptor {
protected LinkedHashMap<String, IProblemPreference> hash = new LinkedHashMap<String, IProblemPreference>(); private Map<String, IProblemPreference> hash = Collections.synchronizedMap(new LinkedHashMap<String, IProblemPreference>());
/** /**
* Default constructor * Default constructor
@ -123,16 +126,19 @@ public class MapProblemPreference extends AbstractProblemPreference implements I
@Override @Override
public Object clone() { public Object clone() {
MapProblemPreference map = (MapProblemPreference) super.clone(); MapProblemPreference map = (MapProblemPreference) super.clone();
map.hash = new LinkedHashMap<String, IProblemPreference>(); synchronized (hash) {
for (Iterator<String> iterator = hash.keySet().iterator(); iterator.hasNext();) { map.hash = Collections.synchronizedMap(new LinkedHashMap<String, IProblemPreference>(hash));
String key = iterator.next(); }
map.hash.put(key, (IProblemPreference) hash.get(key).clone()); // now we have to clone the values too
for (Entry<String, IProblemPreference> entry : map.hash.entrySet()) {
entry.setValue((IProblemPreference) entry.getValue().clone());
} }
return map; return map;
} }
@Override @Override
public String exportValue() { public String exportValue() {
synchronized (hash) {
StringBuffer buf = new StringBuffer("{"); //$NON-NLS-1$ StringBuffer buf = new StringBuffer("{"); //$NON-NLS-1$
for (Iterator<String> iterator = hash.keySet().iterator(); iterator.hasNext();) { for (Iterator<String> iterator = hash.keySet().iterator(); iterator.hasNext();) {
String key = iterator.next(); String key = iterator.next();
@ -148,6 +154,7 @@ public class MapProblemPreference extends AbstractProblemPreference implements I
} }
return buf.toString() + "}"; //$NON-NLS-1$ return buf.toString() + "}"; //$NON-NLS-1$
} }
}
@Override @Override
public void importValue(String str) { public void importValue(String str) {
@ -243,6 +250,7 @@ public class MapProblemPreference extends AbstractProblemPreference implements I
*/ */
@Override @Override
public Object getValue() { public Object getValue() {
synchronized (hash) {
LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>(); LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
for (Iterator<IProblemPreference> iterator = hash.values().iterator(); iterator.hasNext();) { for (Iterator<IProblemPreference> iterator = hash.values().iterator(); iterator.hasNext();) {
IProblemPreference pref = iterator.next(); IProblemPreference pref = iterator.next();
@ -250,6 +258,7 @@ public class MapProblemPreference extends AbstractProblemPreference implements I
} }
return map; return map;
} }
}
/** /**
* Set values for this object child elements. Elements are not present in * Set values for this object child elements. Elements are not present in
@ -263,7 +272,8 @@ public class MapProblemPreference extends AbstractProblemPreference implements I
@Override @Override
public void setValue(Object value) { public void setValue(Object value) {
Map<String, Object> map = (Map<String, Object>) value; Map<String, Object> map = (Map<String, Object>) value;
LinkedHashMap<String, IProblemPreference> hash2 = (LinkedHashMap<String, IProblemPreference>) hash.clone(); synchronized (hash) {
Map<String, IProblemPreference> hashCopy = new HashMap<>(hash);
hash.clear(); hash.clear();
for (Iterator<String> iterator = map.keySet().iterator(); iterator.hasNext();) { for (Iterator<String> iterator = map.keySet().iterator(); iterator.hasNext();) {
String key = iterator.next(); String key = iterator.next();
@ -271,7 +281,7 @@ public class MapProblemPreference extends AbstractProblemPreference implements I
if (value2 instanceof IProblemPreference) { if (value2 instanceof IProblemPreference) {
hash.put(key, (IProblemPreference) value2); hash.put(key, (IProblemPreference) value2);
} else { } else {
IProblemPreference pref = hash2.get(key); IProblemPreference pref = hashCopy.get(key);
addChildDescriptor(pref); addChildDescriptor(pref);
//setChildValue(key, value2); //setChildValue(key, value2);
pref.setValue(value2); pref.setValue(value2);
@ -280,3 +290,4 @@ public class MapProblemPreference extends AbstractProblemPreference implements I
} }
} }
} }
}

View file

@ -20,7 +20,6 @@ public class SharedRootProblemPreference extends RootProblemPreference {
public Object clone() { public Object clone() {
SharedRootProblemPreference map = (SharedRootProblemPreference) super.clone(); SharedRootProblemPreference map = (SharedRootProblemPreference) super.clone();
// alruiz: sharing the internal hash is the only way I could make this work. // alruiz: sharing the internal hash is the only way I could make this work.
map.hash = hash;
return map; return map;
} }
} }