mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 08:48:55 +00:00
[valueConversion] Guard against concurrent access
see https://bugs.eclipse.org/bugs/show_bug.cgi?id=400061
This commit is contained in:
parent
c94c1e452d
commit
df18d11326
2 changed files with 45 additions and 7 deletions
|
@ -21,6 +21,20 @@
|
|||
</message_arguments>
|
||||
</filter>
|
||||
</resource>
|
||||
<resource path="src/org/eclipse/xtext/conversion/impl/AbstractDeclarativeValueConverterService.java" type="org.eclipse.xtext.conversion.impl.AbstractDeclarativeValueConverterService">
|
||||
<filter comment="Fix for bug 400061" id="338792546">
|
||||
<message_arguments>
|
||||
<message_argument value="org.eclipse.xtext.conversion.impl.AbstractDeclarativeValueConverterService"/>
|
||||
<message_argument value="internalRegisterForClass(Class<?>)"/>
|
||||
</message_arguments>
|
||||
</filter>
|
||||
<filter comment="Fix for bug 400061" id="338792546">
|
||||
<message_arguments>
|
||||
<message_argument value="org.eclipse.xtext.conversion.impl.AbstractDeclarativeValueConverterService"/>
|
||||
<message_argument value="registerEFactoryConverters()"/>
|
||||
</message_arguments>
|
||||
</filter>
|
||||
</resource>
|
||||
<resource path="src/org/eclipse/xtext/nodemodel/impl/NodeModelBuilder.java" type="org.eclipse.xtext.nodemodel.impl.NodeModelBuilder">
|
||||
<filter id="338792546">
|
||||
<message_arguments>
|
||||
|
|
|
@ -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<String, IValueConverter<Object>> getConverters() {
|
||||
if (converters == null) {
|
||||
converters = new HashMap<String, IValueConverter<Object>>();
|
||||
internalRegisterForClass(getClass());
|
||||
synchronized(this) {
|
||||
if (converters == null) {
|
||||
Map<String, IValueConverter<Object>> 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<String, IValueConverter<Object>> converters) {
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
Set<String> 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<String, IValueConverter<Object>> converters) {
|
||||
for (ParserRule parserRule : allParserRules(getGrammar())) {
|
||||
if (isDatatypeRule(parserRule) && !converters.containsKey(parserRule.getName())) {
|
||||
EDataType datatype = (EDataType) parserRule.getType().getClassifier();
|
||||
|
|
Loading…
Reference in a new issue