Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Belle2019-02-20 12:42:25 -0500
committerJan Belle2019-02-21 11:56:02 -0500
commitc15e54cb40b88b06840b9197cf2dc752c0914351 (patch)
treea33b922fcc196ac517d54070687e6959b7b2ee57 /plugins
parent6f5cdb957fcf53bb0865fc514b5a967f09ea2dbf (diff)
downloadorg.eclipse.etrice-c15e54cb40b88b06840b9197cf2dc752c0914351.tar.gz
org.eclipse.etrice-c15e54cb40b88b06840b9197cf2dc752c0914351.tar.xz
org.eclipse.etrice-c15e54cb40b88b06840b9197cf2dc752c0914351.zip
[generator] Fix concurrent modification exception in resource validator
The ModelValidator iterates directly over the list of resources in the resource set. If emf proxies get resolved and thus resources are added to the resource set, a concurrent modification exception is raised. Bug 544504 Change-Id: Ie681b3eae7d91cdc56b6274dd62ab213b6beb807
Diffstat (limited to 'plugins')
-rw-r--r--plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/io/GeneratorResourceLoader.java10
-rw-r--r--plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/validation/GeneratorResourceValidator.java11
-rw-r--r--plugins/org.eclipse.etrice.generator.doc/src/org/eclipse/etrice/generator/doc/setup/GeneratorModule.java4
-rw-r--r--plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/AbstractGeneratorBaseModule.java3
-rw-r--r--plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelLoader.java201
-rw-r--r--plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelValidator.java11
6 files changed, 32 insertions, 208 deletions
diff --git a/plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/io/GeneratorResourceLoader.java b/plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/io/GeneratorResourceLoader.java
index 46cd56949..0a59f8bed 100644
--- a/plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/io/GeneratorResourceLoader.java
+++ b/plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/io/GeneratorResourceLoader.java
@@ -58,19 +58,19 @@ public class GeneratorResourceLoader implements IGeneratorResourceLoader {
public List<Resource> load(List<String> files, Arguments arguments, ILogger logger) throws GeneratorException {
doEMFRegistration();
- List<Resource> models = new ArrayList<>(files.size());
+ List<Resource> resources = new ArrayList<>(files.size());
ResourceSet resourceSet = resourceSetProvider.get();
Adapter resourceAddedAdapter = new ResourceAddedAdapter(logger);
resourceSet.eAdapters().add(resourceAddedAdapter);
for(String f: files) {
Resource r = loadResource(f, resourceSet, logger);
- models.add(r);
+ resources.add(r);
}
EcoreUtil.resolveAll(resourceSet);
- return models;
+ return resources;
}
private void doEMFRegistration() {
@@ -91,14 +91,12 @@ public class GeneratorResourceLoader implements IGeneratorResourceLoader {
}
}
- private URI createURI(String file) throws IOException {
+ protected URI createURI(String file) throws IOException {
String realPath = Paths.get(file).toRealPath().toString();
URI uri = URI.createFileURI(realPath);
return uri;
}
-
-
private class ResourceAddedAdapter extends AdapterImpl {
private ILogger logger;
diff --git a/plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/validation/GeneratorResourceValidator.java b/plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/validation/GeneratorResourceValidator.java
index 7c6a88434..0b6759e30 100644
--- a/plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/validation/GeneratorResourceValidator.java
+++ b/plugins/org.eclipse.etrice.generator.base/src/org/eclipse/etrice/generator/base/validation/GeneratorResourceValidator.java
@@ -27,11 +27,10 @@ import org.eclipse.xtext.validation.CheckMode;
import org.eclipse.xtext.validation.IResourceValidator;
import org.eclipse.xtext.validation.Issue;
-import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
/**
- * Simple implementation of an resource validator using an {@link IResourceValidator}.
+ * Simple implementation of a resource validator using an {@link IResourceValidator}.
*/
public class GeneratorResourceValidator implements IGeneratorResourceValidator {
@@ -52,8 +51,7 @@ public class GeneratorResourceValidator implements IGeneratorResourceValidator {
int errors = 0;
int warnings = 0;
- ImmutableList<Resource> toValidate = ImmutableList.copyOf(resources);
- for (Resource resource : toValidate) {
+ for (Resource resource : resources) {
List<Issue> list = resourceValidator.validate(resource, CheckMode.ALL, CancelIndicator.NullImpl);
for (Issue issue : list) {
@@ -71,11 +69,6 @@ public class GeneratorResourceValidator implements IGeneratorResourceValidator {
}
}
- // Bug 544504
- if(toValidate.size() != resources.size()) {
- throw new IllegalStateException("List of resources has changed during validation");
- }
-
if(warnings > 0) {
logger.logWarning(warnings + " warnings");
}
diff --git a/plugins/org.eclipse.etrice.generator.doc/src/org/eclipse/etrice/generator/doc/setup/GeneratorModule.java b/plugins/org.eclipse.etrice.generator.doc/src/org/eclipse/etrice/generator/doc/setup/GeneratorModule.java
index 758fb559f..e30640d60 100644
--- a/plugins/org.eclipse.etrice.generator.doc/src/org/eclipse/etrice/generator/doc/setup/GeneratorModule.java
+++ b/plugins/org.eclipse.etrice.generator.doc/src/org/eclipse/etrice/generator/doc/setup/GeneratorModule.java
@@ -24,8 +24,10 @@ import org.eclipse.etrice.generator.base.EMFSetup;
import org.eclipse.etrice.generator.base.GenerationEMFDiagnostician;
import org.eclipse.etrice.generator.base.IGenerator;
import org.eclipse.etrice.generator.base.ITranslationProvider;
+import org.eclipse.etrice.generator.base.ModelLoader;
import org.eclipse.etrice.generator.base.ModelValidator;
import org.eclipse.etrice.generator.base.io.IGeneratorEMFSetup;
+import org.eclipse.etrice.generator.base.io.IGeneratorResourceLoader;
import org.eclipse.etrice.generator.base.setup.GeneratorName;
import org.eclipse.etrice.generator.base.setup.GeneratorOptions;
import org.eclipse.etrice.generator.base.validation.IGeneratorResourceValidator;
@@ -45,8 +47,8 @@ public class GeneratorModule implements Module {
public void configure(Binder binder) {
binder.bind(String.class).annotatedWith(GeneratorName.class).toInstance(GENERATOR_NAME);
binder.bind(GeneratorOptions.class).to(DocGeneratorOptions.class);
-// binder.bind(IGeneratorResourceLoader.class).to(ModelLoader.class);
binder.bind(IGeneratorEMFSetup.class).to(EMFSetup.class);
+ binder.bind(IGeneratorResourceLoader.class).to(ModelLoader.class);
binder.bind(IGeneratorResourceValidator.class).to(ModelValidator.class);
binder.bind(IGenerator.class).to(Main.class);
diff --git a/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/AbstractGeneratorBaseModule.java b/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/AbstractGeneratorBaseModule.java
index 78569b55b..8d6d1b3f0 100644
--- a/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/AbstractGeneratorBaseModule.java
+++ b/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/AbstractGeneratorBaseModule.java
@@ -23,6 +23,7 @@ import org.eclipse.etrice.core.naming.RoomNameProvider;
import org.eclipse.etrice.core.room.util.CommonDataCalculator;
import org.eclipse.etrice.generator.base.io.GeneratorFileIO;
import org.eclipse.etrice.generator.base.io.IGeneratorEMFSetup;
+import org.eclipse.etrice.generator.base.io.IGeneratorResourceLoader;
import org.eclipse.etrice.generator.base.logging.Logger;
import org.eclipse.etrice.generator.base.setup.GeneratorName;
import org.eclipse.etrice.generator.base.setup.GeneratorOptions;
@@ -76,7 +77,7 @@ public abstract class AbstractGeneratorBaseModule implements Module {
}
binder.bind(String.class).annotatedWith(GeneratorName.class).toInstance(bindGeneratorName());
binder.bind(GeneratorOptions.class).to(bindGeneratorOptions());
-// binder.bind(IGeneratorResourceLoader.class).to(ModelLoader.class);
+ binder.bind(IGeneratorResourceLoader.class).to(ModelLoader.class);
binder.bind(IGeneratorResourceValidator.class).to(ModelValidator.class);
binder.bind(Diagnostician.class).in(Singleton.class);
binder.bind(IDiagnostician.class).to(Diagnostician.class);
diff --git a/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelLoader.java b/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelLoader.java
index b8f5e57ee..556410078 100644
--- a/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelLoader.java
+++ b/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelLoader.java
@@ -14,211 +14,32 @@
package org.eclipse.etrice.generator.base;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.etrice.core.common.scoping.ModelLocatorUriResolver;
-import org.eclipse.etrice.generator.base.args.Arguments;
+import org.eclipse.etrice.generator.base.io.GeneratorResourceLoader;
import org.eclipse.etrice.generator.base.io.IGeneratorEMFSetup;
-import org.eclipse.etrice.generator.base.io.IGeneratorResourceLoader;
-import org.eclipse.etrice.generator.base.logging.ILogger;
-import org.eclipse.etrice.generator.base.logging.NullLogger;
-import org.eclipse.xtext.EcoreUtil2;
-import org.eclipse.xtext.resource.XtextResourceSet;
-import org.eclipse.xtext.util.CancelIndicator;
-import org.xml.sax.SAXException;
-
import com.google.inject.Inject;
import com.google.inject.Provider;
/**
* @author Henrik Rentz-Reichert
- *
+ *
*/
-public class ModelLoader implements IGeneratorResourceLoader {
+public class ModelLoader extends GeneratorResourceLoader {
- /**
- * The injected resource set provider
- */
- @Inject
- private Provider<ResourceSet> resourceSetProvider;
-
- /**
- * The injected platform relative URI resolver
- */
- @Inject
- protected ModelLocatorUriResolver uriResolver;
+ private ModelLocatorUriResolver uriResolver;
@Inject
- private IGeneratorEMFSetup emfSetup;
-
- protected ILogger logger;
- private boolean initializedEMF = EMFPlugin.IS_ECLIPSE_RUNNING;
- private ResourceSet resourceSet;
- private HashSet<URI> modelURIs = new HashSet<URI>();
- private HashSet<URI> mainModelURIs = new HashSet<URI>();
- private HashSet<URI> loadedModelURIs = new HashSet<URI>();
-
- @Override
- public List<Resource> load(List<String> files, Arguments arguments, ILogger logger) {
- if(!initializedEMF) {
- emfSetup.doEMFRegistration();
- initializedEMF = true;
- }
-
- logger.logInfo("-- reading models");
-
- if(loadModels(files, logger)) {
- List<Resource> resources = getResourceSet().getResources().stream()
- .filter(r -> getMainModelURIs().contains(r.getURI())).collect(Collectors.toList());
- return resources;
- }
- else {
- logger.logError("reading models failed");
- logger.logInfo("-- terminating");
- throw new GeneratorException("reading models failed");
- }
- }
-
- public boolean loadModels(List<String> uriList) {
- return loadModels(uriList, null);
- }
-
- public boolean loadModels(List<String> uriList, ILogger logger) {
- if (logger==null) {
- logger = new NullLogger();
- }
- this.logger = logger;
-
- resourceSet = resourceSetProvider.get();
- if (resourceSet instanceof XtextResourceSet) {
- ((XtextResourceSet) resourceSet).setClasspathURIContext(getClass().getClassLoader());
- }
- modelURIs.clear();
- mainModelURIs.clear();
- loadedModelURIs.clear();
-
- for (String uri : uriList) {
- addResourceURI(uriResolver.resolve(uri, null));
- }
+ public ModelLoader(Provider<ResourceSet> resourceSetProvider, IGeneratorEMFSetup emfSetup, ModelLocatorUriResolver uriResolver) {
+ super(resourceSetProvider, emfSetup);
- // now that we have a list of normalized input models we make a copy of them
- mainModelURIs.addAll(modelURIs);
-
- boolean ok = true;
- while (!modelURIs.isEmpty()) {
- URI uri = modelURIs.iterator().next();
- //logger.logInfo("Loading " + uriString);
- try {
- if (loadModel(uri)) {
- Resource resource = resourceSet.getResources().get(resourceSet.getResources().size()-1);
- for (EObject root : resource.getContents()) {
- Iterator<EObject> it = root.eContents().iterator();
- while (it.hasNext()) {
- EObject obj = it.next();
- String importUri = uriResolver.resolve(obj);
- if (importUri!=null) {
- addResourceURI(importUri);
- }
- }
- }
- }
- }
- catch (Exception e) {
- ok = false;
- if (e instanceof FileNotFoundException)
- logger.logError("couldn't load '"+uri+"' (file not found)");
- if(e instanceof SAXException)
- logger.logError("couldn't load '"+uri+"' (maybe unknown or wrong file extension, eTrice file extensions have to be lower case)");
- else
- logger.logError(e.getMessage());
- }
- modelURIs.remove(uri);
- }
-
- // make a copy to avoid concurrent modification
- ArrayList<Resource> resources = new ArrayList<Resource>(resourceSet.getResources());
- for (Resource res : resources) {
- EcoreUtil2.resolveAll(res, CancelIndicator.NullImpl);
- }
-
- return ok;
- }
-
- /**
- * Called by {@link #loadModels(List)} for each single model.
- *
- * @param uri the model URI
- * @return <code>true</code> if successfully loaded or already loaded
- * @throws RuntimeException
- * @throws IOException
- */
- private boolean loadModel(URI uri)
- throws RuntimeException, IOException {
-
- if (loadedModelURIs.contains(uri))
- return true;
-
- if (resourceSet.getResource(uri, false) != null)
- // already loaded
- return false;
-
- logger.logInfo("loading model " + uri);
- resourceSet.getResource(uri, true); // Could throw an exception...
- loadedModelURIs.add(uri);
- return true;
+ this.uriResolver = uriResolver;
}
- /**
- * This implementation of the method assumes the URI is already normalized and adds it to the
- * list of models to load if not already loaded.
- */
- private boolean addResourceURI(String uri) {
- URI can = null;
- try {
- // try valid uri
- can = URI.createURI(uri);
- } catch(IllegalArgumentException e1) {
- }
- if(can == null || !(can.isFile() || can.isArchive() || can.isPlatform() || can.scheme() == "classpath")) {
- // try file path
- can = URI.createFileURI(uri);
- }
-
- if (loadedModelURIs.contains(can))
- return false;
-
- boolean added = modelURIs.add(can);
- if (added) {
- if (loadedModelURIs.isEmpty())
- logger.logInfo("added model "+uri);
- else
- logger.logInfo("added imported model "+uri);
- }
- return added;
- }
-
- /**
- * @return
- */
- public ResourceSet getResourceSet() {
- return resourceSet;
- }
-
- /**
- * @return the mainModelURIs
- */
- public HashSet<URI> getMainModelURIs() {
- return mainModelURIs;
+ @Override
+ protected URI createURI(String file) {
+ String uri = uriResolver.resolve(file, null);
+ return URI.createURI(uri);
}
}
diff --git a/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelValidator.java b/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelValidator.java
index 6379d0424..b2e538414 100644
--- a/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelValidator.java
+++ b/plugins/org.eclipse.etrice.generator/src/org/eclipse/etrice/generator/base/ModelValidator.java
@@ -15,6 +15,7 @@
package org.eclipse.etrice.generator.base;
+import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.ecore.resource.Resource;
@@ -40,6 +41,7 @@ public class ModelValidator extends GeneratorResourceValidator {
public void validate(List<Resource> resources, Arguments arguments, ILogger logger) {
logger.logInfo("-- validating models");
+ // Validate all resources in the resource set
if(!resources.isEmpty()) {
ResourceSet rs = resources.get(0).getResourceSet();
if(rs != null) {
@@ -48,7 +50,14 @@ public class ModelValidator extends GeneratorResourceValidator {
}
try {
- super.validate(resources, arguments, logger);
+ List<Resource> toValidate = new ArrayList<>(resources);
+
+ super.validate(toValidate, arguments, logger);
+
+ // Bug 544504
+ if(toValidate.size() != resources.size()) {
+ throw new IllegalStateException("List of resources has changed during validation");
+ }
}
catch(Exception e) {
logger.logInfo("validation failed");

Back to the top