From df18d11326ac37578718d87edd593b2c9aaffbcd Mon Sep 17 00:00:00 2001 From: Sebastian Zarnekow Date: Thu, 14 Feb 2013 12:03:19 +0100 Subject: [PATCH] [valueConversion] Guard against concurrent access see https://bugs.eclipse.org/bugs/show_bug.cgi?id=400061 --- .../org.eclipse.xtext/.settings/.api_filters | 14 +++++++ ...tractDeclarativeValueConverterService.java | 38 +++++++++++++++---- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/plugins/org.eclipse.xtext/.settings/.api_filters b/plugins/org.eclipse.xtext/.settings/.api_filters index c99aedbcd..52f6afada 100644 --- a/plugins/org.eclipse.xtext/.settings/.api_filters +++ b/plugins/org.eclipse.xtext/.settings/.api_filters @@ -21,6 +21,20 @@ + + + + + + + + + + + + + + diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/conversion/impl/AbstractDeclarativeValueConverterService.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/conversion/impl/AbstractDeclarativeValueConverterService.java index 6381f6618..c0315bd07 100644 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/conversion/impl/AbstractDeclarativeValueConverterService.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/conversion/impl/AbstractDeclarativeValueConverterService.java @@ -11,12 +11,12 @@ package org.eclipse.xtext.conversion.impl; import static org.eclipse.xtext.GrammarUtil.*; import java.lang.reflect.Method; -import java.util.HashMap; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EFactory; import org.eclipse.xtext.AbstractRule; import org.eclipse.xtext.Grammar; import org.eclipse.xtext.GrammarUtil; @@ -24,14 +24,23 @@ import org.eclipse.xtext.IGrammarAccess; import org.eclipse.xtext.ParserRule; import org.eclipse.xtext.TerminalRule; import org.eclipse.xtext.conversion.IValueConverter; +import org.eclipse.xtext.conversion.IValueConverterService; import org.eclipse.xtext.conversion.ValueConverter; import org.eclipse.xtext.conversion.ValueConverterException; import org.eclipse.xtext.nodemodel.INode; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.inject.Inject; /** + * Abstract base implementation for the {@link IValueConverterService}. + * + * All methods that are annotated with {@link ValueConverter @ValueConverter} are + * used to collect the strategies for this language. Furthermore, the {@link EFactory EMF factories} + * are inspected to create converters for data types that have not yet been mapped. + * * @author Sven Efftinge - Initial contribution and API */ public abstract class AbstractDeclarativeValueConverterService extends AbstractValueConverterService { @@ -73,14 +82,24 @@ public abstract class AbstractDeclarativeValueConverterService extends AbstractV protected Map> getConverters() { if (converters == null) { - converters = new HashMap>(); - internalRegisterForClass(getClass()); + synchronized(this) { + if (converters == null) { + Map> converters = Maps.newHashMap(); + internalRegisterForClass(getClass(), converters); + this.converters = ImmutableMap.copyOf(converters); + } + } } return converters; } + /** + * @since 2.4 + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + */ @SuppressWarnings("unchecked") - protected void internalRegisterForClass(Class clazz) { + protected void internalRegisterForClass(Class clazz, Map> converters) { Method[] methods = clazz.getDeclaredMethods(); Set thisConverters = Sets.newHashSet(); for (Method method : methods) { @@ -114,9 +133,9 @@ public abstract class AbstractDeclarativeValueConverterService extends AbstractV } } if (clazz.getSuperclass() != null) { - internalRegisterForClass(clazz.getSuperclass()); + internalRegisterForClass(clazz.getSuperclass(), converters); } - registerEFactoryConverters(); + registerEFactoryConverters(converters); } protected boolean isConfigurationMethod(Method method) { @@ -124,7 +143,12 @@ public abstract class AbstractDeclarativeValueConverterService extends AbstractV && IValueConverter.class.isAssignableFrom(method.getReturnType()); } - protected void registerEFactoryConverters() { + /** + * @since 2.4 + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + */ + protected void registerEFactoryConverters(Map> converters) { for (ParserRule parserRule : allParserRules(getGrammar())) { if (isDatatypeRule(parserRule) && !converters.containsKey(parserRule.getName())) { EDataType datatype = (EDataType) parserRule.getType().getClassifier();