Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [m2m-atl-dev] ATL 3.0 architecture & ASMEMFModel Memory leak comes back to haunt?

Hello Dennis,

Answers below:
Dennis Wagelaar a écrit :
Hello ATL devs,

In this mail, I'll try to re-describe how the EMF model memory leak relates to the new ATL 3.0.0 architecture in CVS HEAD. Below, I'll indicate how ATL HEAD differs from ATL 2.1:

Dennis Wagelaar schreef:
Hello devs,

Recently, the "extent.unload()" line was removed from ASMEMFModel's dispose method. Calling "unload()" should indeed not be necessary, and removing a Resource from its ResourceSet should suffice.

Some tests with running ATL via Ant on some UML2 models revealed that, even though ATL's ResourceSet never grew larger, memory was leaking at about 20MB per Ant run. I also found that a couple of models (profiles, libraries) were not removed from the ResourceSet afterwards, because ATL is not aware of them.

The problem in ATL is that we're constantly trying to clean up ATL's static ResourceSet, while EMF happily auto-resolves and auto-loads referenced models. I've committed a new branch to the ATL CVS ("ATL_Dynamic_ResourceSet") that uses dynamic ResourceSet instances, which are coupled to ModelLoader instances. This required breaking the existing API for loading/saving models. I've used that as an opportunity to remove all unused and/or duplicated API for loading and saving.

I encountered this problem too... so I add an option to clear the resourceSet after each transformation run. It's definitely not the better solution...
In ATL HEAD, EMFModel no longer distinguishes between the main Resource and referenced Resources. Instead, there is EMFModel.getResources(). There is still a static ResourceSet, which resides inside EMFModelFactory (slightly overkill, as EMFModelFactory is in effect a singleton).

ATL is currently trying to do its own garbage collection: when it's cleanup time, EMFModel.dispose() removes all Resources from the static ResourceSet. This ensures that even auto-loaded referenced models are removed.

This approach is problematic, because:
======================================

- Only metamodels (EMFReferenceModels) have referenced resources in addition to the main resource. Contrary the main resource, which is *owned*, those referenced resources may be *shared*. Other metamodels may reference the same shared resource(s). That means you cannot remove them from the ResourceSet unless *all* metamodels using the same ResourceSet are cleaned up.

- There is no way of knowing when *all* metamodels using the same ResourceSet are cleaned up. The garbage collector can tell by checking if there are any IModel and ResourceSet references left. As the ResourceSet is static, the garbage collector cannot touch the Resources inside it until the EMFModelFactory class is unloaded. That normally happens when you shut down Eclipse.

The problem cannot be solved like this:
=======================================

- Making the ResourceSet in EMFModelFactory a dynamic field causes the ResourceSet to be garbage collected as soon as the corresponding EMFModelFactory is garbage collected. Currently, the EMFModelFactory is a singleton, which resides in a static registry. EMFModelFactory is garbage collected when Eclipse shuts down.

- Creating a separate ResourceSet for each EMFModel -- or a cluster of EMFModels tied to one EMFReferenceModel -- will ensure that referenced resources are *not shared*. This may cause severe aliasing problems, however. In the case of cross-references between multiple loaded (meta)models, the same Resource is loaded multiple times in multiple ResourceSets. Multiple representations of the same model element lead to all kinds of errors in ATL transformations, ranging from equality check failures to implicit tracing resolve failures.

The problem was solved in the following way in ATL_Dynamic_ResourceSet:
=======================================================================


AtlModelHandlers no longer include model loading/saving methods. Instead, they have a Factory Method for creating ModelLoaders. A ModelLoader instance can be used for a single ATL run (or a chain of ATL runs). Afterwards, the ModelLoader will be garbage collected, with ResourceSet and all. Models no longer need to be explicitly disposed: this functionality has been moved to the "finalize()" method of the ModelLoader, which is automatically invoked by the garbage collector. The code still uses "unload()", but at least it is only used in the garbage collection thread and doesn't interfere with the main model transformation algorithms.

Cheers,

The equivalent of a disposable ModelLoader is not available in the ATL 3.0.0 architecture. In addition, the ResourceSet is used in EMFInjector, which does the bulk of the model loading now. IInjectors are singletons, like ModelFactories.

Therefore, I'd like to see the return of ModelLoader (even if it gets a different name), which is disposable and can be created by ModelFactory. Any chance of seeing this happen?
Sure! The current architecture needs to be improved to fit all needs.
What are your opinions on this? William: what do you think of an architecture change that involves something like a ModelLoader?
I agree with your demonstration. A solution could be to make the EMFModelFactory "dynamic": * in CoreService, no more registry for it, but a "createModelFactory(String modelFactoryName)" method.
* in the EMFModelFactory, a non-static ResourceSet.
So the EMFModelFactory is transparently linked with its ResourceSet instance, and is recreated for each launch. Note that a programmatic launch (or another launching tool, like ant) can provide the same behaviour as before is necessary, by keeping the same factory into chained transformation.

Would you agree with that? I tested an implementation and attached a patch to this mail if you want to see details.

Thank you for your feedback!

William

Cheers,
Dennis

_______________________________________________
m2m-atl-dev mailing list
m2m-atl-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/m2m-atl-dev


### Eclipse Workspace Patch 1.0
#P org.eclipse.m2m.atl.engine.emfvm
Index: src/org/eclipse/m2m/atl/engine/emfvm/launch/EMFVMLauncher.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.engine.emfvm/src/org/eclipse/m2m/atl/engine/emfvm/launch/EMFVMLauncher.java,v
retrieving revision 1.2
diff -u -r1.2 EMFVMLauncher.java
--- src/org/eclipse/m2m/atl/engine/emfvm/launch/EMFVMLauncher.java	10 Dec 2008 09:27:59 -0000	1.2
+++ src/org/eclipse/m2m/atl/engine/emfvm/launch/EMFVMLauncher.java	12 Dec 2008 14:25:40 -0000
@@ -5,15 +5,10 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.logging.Level;
 
-import org.eclipse.core.runtime.CoreException;
 import org.eclipse.m2m.atl.ATLLogger;
 import org.eclipse.m2m.atl.core.IModel;
-import org.eclipse.m2m.atl.core.ModelFactory;
-import org.eclipse.m2m.atl.core.emf.EMFModelFactory;
 import org.eclipse.m2m.atl.core.launch.ILauncher;
-import org.eclipse.m2m.atl.core.service.CoreService;
 import org.eclipse.m2m.atl.engine.emfvm.ASM;
 import org.eclipse.m2m.atl.engine.emfvm.ASMXMLReader;
 import org.eclipse.m2m.atl.engine.emfvm.Messages;
@@ -100,10 +95,6 @@
 	public void initialize(Map<String, Object> parameters) {
 		models = new HashMap<String, IModel>();
 		libraries = new HashMap<String, ASM>();
-		boolean clearResourceSet = "true".equals(parameters.get("clearResourceSet")); //$NON-NLS-1$//$NON-NLS-2$
-		if (clearResourceSet) {
-			EMFModelFactory.init();
-		}
 	}
 
 	/**
@@ -158,13 +149,8 @@
 	 * 
 	 * @see org.eclipse.m2m.atl.core.launch.ILauncher#getDefaultModelFactory()
 	 */
-	public ModelFactory getDefaultModelFactory() {
-		try {
-			return CoreService.getModelFactory("EMF"); //$NON-NLS-1$
-		} catch (CoreException e) {
-			ATLLogger.log(Level.SEVERE, e.getLocalizedMessage(), e);
-		}
-		return null;
+	public String getDefaultModelFactoryName() {
+		return "EMF";
 	}
 
 }
#P org.eclipse.m2m.atl.core.emf
Index: src/org/eclipse/m2m/atl/core/emf/EMFReferenceModel.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core.emf/src/org/eclipse/m2m/atl/core/emf/EMFReferenceModel.java,v
retrieving revision 1.3
diff -u -r1.3 EMFReferenceModel.java
--- src/org/eclipse/m2m/atl/core/emf/EMFReferenceModel.java	9 Dec 2008 16:31:46 -0000	1.3
+++ src/org/eclipse/m2m/atl/core/emf/EMFReferenceModel.java	12 Dec 2008 14:25:42 -0000
@@ -50,8 +50,9 @@
 	/**
 	 * Metametamodel constructor.
 	 */
-	private EMFReferenceModel() {
+	private EMFReferenceModel(EMFModelFactory modelFactory) {
 		super(null);
+		this.modelFactory = modelFactory;
 	}
 
 	/**
@@ -94,11 +95,13 @@
 	/**
 	 * Returns the Metametamodel.
 	 * 
+	 * @param modelFactory
+	 *            the model factory used to create models.
 	 * @return the Metametamodel
 	 */
-	public static EMFReferenceModel getMetametamodel() {
+	public static EMFReferenceModel getMetametamodel(EMFModelFactory modelFactory) {
 		if (metametamodel == null) {
-			metametamodel = new EMFReferenceModel();
+			metametamodel = new EMFReferenceModel(modelFactory);
 			metametamodel.getResources().add(EcorePackage.eINSTANCE.eResource());
 		}
 		return metametamodel;
@@ -115,13 +118,13 @@
 		// unregister packages
 		for (Iterator<String> unrs = unregister.iterator(); unrs.hasNext();) {
 			String nsURI = unrs.next();
-			synchronized (EMFModelFactory.getResourceSet()) {
-				EMFModelFactory.getResourceSet().getPackageRegistry().remove(nsURI);
+			synchronized (modelFactory.getResourceSet()) {
+				modelFactory.getResourceSet().getPackageRegistry().remove(nsURI);
 			}
 		}
 		// take resource out of (static) resourceSet
-		synchronized (EMFModelFactory.getResourceSet()) {
-			EMFModelFactory.getResourceSet().getResources().removeAll(resources);
+		synchronized (modelFactory.getResourceSet()) {
+			modelFactory.getResourceSet().getResources().removeAll(resources);
 		}
 		resources.clear();
 		super.dispose();
@@ -176,11 +179,11 @@
 				nsURI = p.getName();
 				p.setNsURI(nsURI);
 			}
-			if (!EMFModelFactory.getResourceSet().getPackageRegistry().containsKey(nsURI)) {
+			if (!modelFactory.getResourceSet().getPackageRegistry().containsKey(nsURI)) {
 				unregister.add(nsURI);
 			}
-			synchronized (EMFModelFactory.getResourceSet()) {
-				EMFModelFactory.getResourceSet().getPackageRegistry().put(nsURI, p);
+			synchronized (modelFactory.getResourceSet()) {
+				modelFactory.getResourceSet().getPackageRegistry().put(nsURI, p);
 			}
 		}
 	}
Index: src/org/eclipse/m2m/atl/core/emf/EMFExtractor.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core.emf/src/org/eclipse/m2m/atl/core/emf/EMFExtractor.java,v
retrieving revision 1.2
diff -u -r1.2 EMFExtractor.java
--- src/org/eclipse/m2m/atl/core/emf/EMFExtractor.java	9 Dec 2008 16:31:46 -0000	1.2
+++ src/org/eclipse/m2m/atl/core/emf/EMFExtractor.java	12 Dec 2008 14:25:42 -0000
@@ -18,6 +18,7 @@
 
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.emf.ecore.xmi.XMLResource;
 import org.eclipse.m2m.atl.ATLLogger;
 import org.eclipse.m2m.atl.core.IExtractor;
@@ -37,6 +38,8 @@
 	 */
 	public void extract(IModel targetModel, Object target, Map<String, Object> options) {
 		Map<?, ?> pathMap = null;
+		ResourceSet resourceSet = ((EMFModelFactory)targetModel.getModelFactory()).getResourceSet();
+		
 		Object contentType = options.get(EMFModelFactory.OPTION_CONTENT_TYPE);
 		Object object = target.toString();
 		if (object instanceof Map<?, ?>) {
@@ -46,7 +49,7 @@
 				if (path.startsWith("ext:")) { //$NON-NLS-1$
 					path = path.substring(4);
 				}
-				extract(resource, path, contentType, options);
+				extract(resourceSet, resource, path, contentType, options);
 			}
 		} else if (object instanceof String) {
 			String path = (String)object;
@@ -54,7 +57,7 @@
 				path = path.substring(4);
 			}
 			if (!((EMFModel)targetModel).getResources().isEmpty()) {
-				extract(((EMFModel)targetModel).getResources().get(0), path, contentType, options);
+				extract(resourceSet, ((EMFModel)targetModel).getResources().get(0), path, contentType, options);
 			} else {
 				ATLLogger.severe(Messages.getString("EMFExtractor.NO_RESOURCE", new Object[] {path})); //$NON-NLS-1$
 			}
@@ -70,15 +73,16 @@
 		extract(targetModel, target, Collections.<String, Object> emptyMap());
 	}
 
-	private void extract(Resource resource, String path, Object contentType, Map<String, Object> options) {
+	private void extract(ResourceSet resourceSet, Resource resource, String path, Object contentType, Map<String, Object> options) {
+		//TODO do not systematically recreate the resource
 		Resource newResource = null;
 		if (contentType == null) {
-			newResource = EMFModelFactory.getResourceSet().createResource(URI.createFileURI(path));
+			newResource = resourceSet.createResource(URI.createFileURI(path));
 		} else {
 			// TODO compatibility
 			// newResource = EMFModelFactory.getResourceSet().createResource(URI.createFileURI(path),
 			// (String)contentType);
-			newResource = EMFModelFactory.getResourceSet().createResource(URI.createFileURI(path));
+			newResource = resourceSet.createResource(URI.createFileURI(path));
 		}
 		newResource.getContents().addAll(resource.getContents());
 
@@ -93,7 +97,7 @@
 		} catch (IOException e) {
 			ATLLogger.log(Level.SEVERE, Messages.getString("EMFExtractor.ERROR_EXTRACTING", path), e); //$NON-NLS-1$
 		}
-		EMFModelFactory.getResourceSet().getResources().remove(newResource);
+		resourceSet.getResources().remove(newResource);
 	}
 
 }
Index: src/org/eclipse/m2m/atl/core/emf/EMFModel.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core.emf/src/org/eclipse/m2m/atl/core/emf/EMFModel.java,v
retrieving revision 1.1
diff -u -r1.1 EMFModel.java
--- src/org/eclipse/m2m/atl/core/emf/EMFModel.java	9 Dec 2008 11:28:13 -0000	1.1
+++ src/org/eclipse/m2m/atl/core/emf/EMFModel.java	12 Dec 2008 14:25:42 -0000
@@ -39,6 +39,8 @@
 
 	protected List<Resource> resources;
 
+	protected EMFModelFactory modelFactory;
+	
 	private boolean isTarget;
 
 	private EMFReferenceModel referenceModel;
@@ -54,6 +56,10 @@
 	public EMFModel(EMFReferenceModel referenceModel) {
 		this.resources = new ArrayList<Resource>();
 		this.referenceModel = referenceModel;
+		// If the current model isn't a metametamodel
+		if (referenceModel != null) {
+			this.modelFactory = referenceModel.getModelFactory();	
+		}		
 	}
 
 	/**
@@ -64,7 +70,7 @@
 	public Object newElement(Object metaElement) {
 		Resource mainResource = null;
 		if (resources.isEmpty()) {
-			mainResource = EMFModelFactory.getResourceSet().createResource(URI.createURI("new-model")); //$NON-NLS-1$
+			mainResource = modelFactory.getResourceSet().createResource(URI.createURI("new-model")); //$NON-NLS-1$
 			resources.add(mainResource);
 		} else {
 			mainResource = resources.get(0);
@@ -137,7 +143,7 @@
 		if (this != referenceModel) {
 			// we clean our references, except for the metametamodel
 			for (Resource resource : resources) {
-				EMFModelFactory.getResourceSet().getResources().remove(resource);
+				modelFactory.getResourceSet().getResources().remove(resource);
 			}
 		}
 	}
@@ -147,6 +153,15 @@
 	}
 
 	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.m2m.atl.core.IModel#getModelFactory()
+	 */
+	public EMFModelFactory getModelFactory() {
+		return modelFactory;
+	}
+
+	/**
 	 * Finalizes the model.
 	 */
 	public void commitToResources() {
Index: src/org/eclipse/m2m/atl/core/emf/EMFModelFactory.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core.emf/src/org/eclipse/m2m/atl/core/emf/EMFModelFactory.java,v
retrieving revision 1.2
diff -u -r1.2 EMFModelFactory.java
--- src/org/eclipse/m2m/atl/core/emf/EMFModelFactory.java	9 Dec 2008 14:28:22 -0000	1.2
+++ src/org/eclipse/m2m/atl/core/emf/EMFModelFactory.java	12 Dec 2008 14:25:42 -0000
@@ -21,8 +21,6 @@
 import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
 import org.eclipse.emf.ecore.xmi.impl.XMLParserPoolImpl;
 import org.eclipse.m2m.atl.ATLLogger;
-import org.eclipse.m2m.atl.core.IExtractor;
-import org.eclipse.m2m.atl.core.IInjector;
 import org.eclipse.m2m.atl.core.IModel;
 import org.eclipse.m2m.atl.core.IReferenceModel;
 import org.eclipse.m2m.atl.core.ModelFactory;
@@ -34,19 +32,26 @@
  */
 public final class EMFModelFactory extends ModelFactory {
 
+	/** The model factory name which is also the extractor/injector name. */
+	public static final String MODEL_FACTORY_NAME = "EMF"; //$NON-NLS-1$
+
 	/** Content type. */
 	public static final String OPTION_CONTENT_TYPE = "OPTION_CONTENT_TYPE"; //$NON-NLS-1$
 
-	private static ResourceSet resourceSet;
+	private ResourceSet resourceSet;
 
-	static {
+	/**
+	 * Creates a new {@link EMFModelFactory} and initialize the {@link ResourceSet}.
+	 */
+	public EMFModelFactory() {
+		super();
 		init();
 	}
 
 	/**
 	 * Recreates the {@link ResourceSet}.
 	 */
-	public static void init() {
+	public void init() {
 		Map<String, Object> etfm = Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap();
 		if (!etfm.containsKey("*")) { //$NON-NLS-1$
 			etfm.put("*", new XMIResourceFactoryImpl()); //$NON-NLS-1$
@@ -75,7 +80,7 @@
 	 */
 	@Override
 	public IReferenceModel newReferenceModel() {
-		return new EMFReferenceModel(EMFReferenceModel.getMetametamodel());
+		return new EMFReferenceModel(EMFReferenceModel.getMetametamodel(this));
 	}
 
 	/**
@@ -102,24 +107,24 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.m2m.atl.core.ModelFactory#getDefaultExtractor()
+	 * @see org.eclipse.m2m.atl.core.ModelFactory#getDefaultExtractorName()
 	 */
 	@Override
-	public IExtractor getDefaultExtractor() {
-		return new EMFExtractor();
+	public String getDefaultExtractorName() {
+		return MODEL_FACTORY_NAME;
 	}
 
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.m2m.atl.core.ModelFactory#getDefaultInjector()
+	 * @see org.eclipse.m2m.atl.core.ModelFactory#getDefaultInjectorName()
 	 */
 	@Override
-	public IInjector getDefaultInjector() {
-		return new EMFInjector();
+	public String getDefaultInjectorName() {
+		return MODEL_FACTORY_NAME;
 	}
 
-	public static ResourceSet getResourceSet() {
+	public ResourceSet getResourceSet() {
 		return resourceSet;
 	}
 
@@ -130,7 +135,7 @@
 	 */
 	@Override
 	public IReferenceModel getBuiltInResource(String name) {
-		EMFReferenceModel model = new EMFReferenceModel(EMFReferenceModel.getMetametamodel());
+		EMFReferenceModel model = new EMFReferenceModel(EMFReferenceModel.getMetametamodel(this));
 		String path = "org.eclipse.m2m.atl/src/org/eclipse/m2m/atl/resources/" + name + ".ecore"; //$NON-NLS-1$//$NON-NLS-2$
 		Resource builtin = resourceSet.getResource(URI.createPlatformPluginURI(path, false), true);
 		if (builtin == null) {
Index: src/org/eclipse/m2m/atl/core/emf/EMFInjector.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core.emf/src/org/eclipse/m2m/atl/core/emf/EMFInjector.java,v
retrieving revision 1.2
diff -u -r1.2 EMFInjector.java
--- src/org/eclipse/m2m/atl/core/emf/EMFInjector.java	9 Dec 2008 16:31:46 -0000	1.2
+++ src/org/eclipse/m2m/atl/core/emf/EMFInjector.java	12 Dec 2008 14:25:42 -0000
@@ -18,6 +18,7 @@
 import org.eclipse.emf.ecore.EPackage;
 import org.eclipse.emf.ecore.EcorePackage;
 import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.m2m.atl.ATLLogger;
 import org.eclipse.m2m.atl.core.IInjector;
 import org.eclipse.m2m.atl.core.IModel;
@@ -36,6 +37,8 @@
 	 */
 	public void inject(IModel sourceModel, Object source, Map<String, Object> options) {
 		Resource mainResource = null;
+		ResourceSet resourceSet = ((EMFModelFactory)sourceModel.getModelFactory()).getResourceSet();
+		
 		String path = source.toString();
 		if (path != null) {
 			// EMF Registry
@@ -52,13 +55,13 @@
 				// File system
 			} else if (path.startsWith("ext:")) { //$NON-NLS-1$
 				path = path.substring(4);
-				mainResource = EMFModelFactory.getResourceSet().getResource(URI.createFileURI(path), true);
+				mainResource = resourceSet.getResource(URI.createFileURI(path), true);
 				// EMF
 			} else if (path.equals("#EMF")) { //$NON-NLS-1$
 				mainResource = EcorePackage.eINSTANCE.eResource();
 				// Workspace
 			} else {
-				mainResource = EMFModelFactory.getResourceSet().getResource(
+				mainResource = resourceSet.getResource(
 						URI.createPlatformResourceURI(path, false), true);
 			}
 		} else {
#P org.eclipse.m2m.atl.core.ui
Index: src/org/eclipse/m2m/atl/core/ui/launch/AtlLaunchConfigurationDelegate.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core.ui/src/org/eclipse/m2m/atl/core/ui/launch/AtlLaunchConfigurationDelegate.java,v
retrieving revision 1.1
diff -u -r1.1 AtlLaunchConfigurationDelegate.java
--- src/org/eclipse/m2m/atl/core/ui/launch/AtlLaunchConfigurationDelegate.java	9 Dec 2008 11:29:00 -0000	1.1
+++ src/org/eclipse/m2m/atl/core/ui/launch/AtlLaunchConfigurationDelegate.java	12 Dec 2008 14:25:43 -0000
@@ -89,9 +89,9 @@
 		Map<String, IInjector> injectors = new HashMap<String, IInjector>();
 
 		// Loading defaults
-		ModelFactory defaultModelfactory = launcher.getDefaultModelFactory();
-		IInjector defaultInjector = defaultModelfactory.getDefaultInjector();
-		IExtractor defaultExtractor = defaultModelfactory.getDefaultExtractor();
+		ModelFactory defaultModelfactory = CoreService.createModelFactory(launcher.getDefaultModelFactoryName());
+		IInjector defaultInjector = CoreService.getInjector(defaultModelfactory.getDefaultInjectorName());
+		IExtractor defaultExtractor = CoreService.getExtractor(defaultModelfactory.getDefaultExtractorName());
 
 		for (Iterator<String> iterator = modelPaths.keySet().iterator(); iterator.hasNext();) {
 			String modelName = iterator.next();
#P org.eclipse.m2m.atl.tests
Index: src/org/eclipse/m2m/atl/tests/unit/TestNonRegressionTransfo.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/tests/org.eclipse.m2m.atl.tests/src/org/eclipse/m2m/atl/tests/unit/TestNonRegressionTransfo.java,v
retrieving revision 1.22
diff -u -r1.22 TestNonRegressionTransfo.java
--- src/org/eclipse/m2m/atl/tests/unit/TestNonRegressionTransfo.java	9 Dec 2008 14:28:25 -0000	1.22
+++ src/org/eclipse/m2m/atl/tests/unit/TestNonRegressionTransfo.java	12 Dec 2008 14:25:45 -0000
@@ -232,9 +232,9 @@
 		Map<String, IExtractor> extractors = new HashMap<String, IExtractor>();
 		Map<String, IInjector> injectors = new HashMap<String, IInjector>();
 
-		ModelFactory modelfactory = launcher.getDefaultModelFactory();
-		IInjector injector = modelfactory.getDefaultInjector();
-		IExtractor extractor = modelfactory.getDefaultExtractor();
+		ModelFactory modelfactory = CoreService.createModelFactory(launcher.getDefaultModelFactoryName());
+		IInjector injector = CoreService.getInjector(modelfactory.getDefaultInjectorName());
+		IExtractor extractor = CoreService.getExtractor(modelfactory.getDefaultExtractorName());
 
 		for (Iterator<String> iterator = modelPaths.keySet().iterator(); iterator.hasNext();) {
 			String modelName = iterator.next();
#P org.eclipse.m2m.atl.core.ui.vm
Index: src/org/eclipse/m2m/atl/core/ui/vm/asm/ASMModelWrapper.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core.ui.vm/src/org/eclipse/m2m/atl/core/ui/vm/asm/ASMModelWrapper.java,v
retrieving revision 1.2
diff -u -r1.2 ASMModelWrapper.java
--- src/org/eclipse/m2m/atl/core/ui/vm/asm/ASMModelWrapper.java	9 Dec 2008 14:48:32 -0000	1.2
+++ src/org/eclipse/m2m/atl/core/ui/vm/asm/ASMModelWrapper.java	12 Dec 2008 14:25:46 -0000
@@ -16,6 +16,7 @@
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.m2m.atl.core.IModel;
 import org.eclipse.m2m.atl.core.IReferenceModel;
+import org.eclipse.m2m.atl.core.ModelFactory;
 import org.eclipse.m2m.atl.engine.vm.AtlModelHandler;
 import org.eclipse.m2m.atl.engine.vm.nativelib.ASMModel;
 
@@ -186,4 +187,14 @@
 		return false;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.m2m.atl.core.IModel#getModelFactory()
+	 * @deprecated unused in this implementation
+	 */
+	public ModelFactory getModelFactory() {
+		return null;
+	}
+
 }
Index: src/org/eclipse/m2m/atl/core/ui/vm/asm/ASMFactory.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core.ui.vm/src/org/eclipse/m2m/atl/core/ui/vm/asm/ASMFactory.java,v
retrieving revision 1.2
diff -u -r1.2 ASMFactory.java
--- src/org/eclipse/m2m/atl/core/ui/vm/asm/ASMFactory.java	9 Dec 2008 14:48:32 -0000	1.2
+++ src/org/eclipse/m2m/atl/core/ui/vm/asm/ASMFactory.java	12 Dec 2008 14:25:46 -0000
@@ -14,8 +14,6 @@
 import java.util.Map;
 
 import org.eclipse.m2m.atl.ATLLogger;
-import org.eclipse.m2m.atl.core.IExtractor;
-import org.eclipse.m2m.atl.core.IInjector;
 import org.eclipse.m2m.atl.core.IModel;
 import org.eclipse.m2m.atl.core.IReferenceModel;
 import org.eclipse.m2m.atl.core.ModelFactory;
@@ -41,6 +39,9 @@
 	/** The newModel boolean. */
 	public static final String OPTION_NEW_MODEL = "newModel"; //$NON-NLS-1$
 
+	/** The model factory name which is also the extractor/injector name. */
+	public static final String MODEL_FACTORY_NAME = "ASM"; //$NON-NLS-1$
+
 	private static Map<String, ASMModelWrapper> metametamodels = new HashMap<String, ASMModelWrapper>();
 
 	private static Map<String, ASMModelWrapper> builtin = new HashMap<String, ASMModelWrapper>();
@@ -48,26 +49,6 @@
 	private static final AtlModelHandler DEFAULT_MODEL_HANDLER = AtlModelHandler.getDefault("EMF"); //$NON-NLS-1$
 
 	/**
-	 * {@inheritDoc}
-	 * 
-	 * @see org.eclipse.m2m.atl.core.ModelFactory#getDefaultExtractor()
-	 */
-	@Override
-	public IExtractor getDefaultExtractor() {
-		return new ASMExtractor();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 * 
-	 * @see org.eclipse.m2m.atl.core.ModelFactory#getDefaultInjector()
-	 */
-	@Override
-	public IInjector getDefaultInjector() {
-		return new ASMInjector();
-	}
-
-	/**
 	 * {@inheritDoc} This method needs additional parameters to be launched, passed as options:
 	 * <ul>
 	 * <li>modelHandlerName: the name of the model handler.</li>
@@ -152,7 +133,8 @@
 	@Override
 	public IReferenceModel getBuiltInResource(String name) {
 		if (builtin.get(name) == null) {
-			ASMModelWrapper metamodel = new ASMModelWrapper(DEFAULT_MODEL_HANDLER.getBuiltInMetaModel(name), DEFAULT_MODEL_HANDLER);
+			ASMModelWrapper metamodel = new ASMModelWrapper(DEFAULT_MODEL_HANDLER.getBuiltInMetaModel(name),
+					DEFAULT_MODEL_HANDLER);
 			builtin.put(name, metamodel);
 		}
 		return builtin.get(name);
@@ -173,4 +155,24 @@
 		}
 		return metametamodels.get(modelHandlerName);
 	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.m2m.atl.core.ModelFactory#getDefaultExtractorName()
+	 */
+	@Override
+	public String getDefaultExtractorName() {
+		return MODEL_FACTORY_NAME;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.m2m.atl.core.ModelFactory#getDefaultInjectorName()
+	 */
+	@Override
+	public String getDefaultInjectorName() {
+		return MODEL_FACTORY_NAME;
+	}
 }
Index: src/org/eclipse/m2m/atl/core/ui/vm/RegularVMLauncher.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core.ui.vm/src/org/eclipse/m2m/atl/core/ui/vm/RegularVMLauncher.java,v
retrieving revision 1.2
diff -u -r1.2 RegularVMLauncher.java
--- src/org/eclipse/m2m/atl/core/ui/vm/RegularVMLauncher.java	9 Dec 2008 14:48:32 -0000	1.2
+++ src/org/eclipse/m2m/atl/core/ui/vm/RegularVMLauncher.java	12 Dec 2008 14:25:46 -0000
@@ -19,7 +19,6 @@
 import java.util.Map;
 import java.util.logging.Level;
 
-import org.eclipse.core.runtime.CoreException;
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.ILaunch;
 import org.eclipse.debug.core.ILaunchManager;
@@ -28,9 +27,8 @@
 import org.eclipse.m2m.atl.adt.debug.core.AtlDebugTarget;
 import org.eclipse.m2m.atl.adt.debug.core.AtlRunTarget;
 import org.eclipse.m2m.atl.core.IModel;
-import org.eclipse.m2m.atl.core.ModelFactory;
 import org.eclipse.m2m.atl.core.launch.ILauncher;
-import org.eclipse.m2m.atl.core.service.CoreService;
+import org.eclipse.m2m.atl.core.ui.vm.asm.ASMFactory;
 import org.eclipse.m2m.atl.core.ui.vm.asm.ASMModelWrapper;
 import org.eclipse.m2m.atl.drivers.emf4atl.ASMEMFModel;
 import org.eclipse.m2m.atl.engine.vm.ASM;
@@ -137,16 +135,11 @@
 
 	/**
 	 * {@inheritDoc}
-	 * 
-	 * @see org.eclipse.m2m.atl.core.launch.ILauncher#getDefaultModelFactory()
+	 *
+	 * @see org.eclipse.m2m.atl.core.launch.ILauncher#getDefaultModelFactoryName()
 	 */
-	public ModelFactory getDefaultModelFactory() {
-		try {
-			return CoreService.getModelFactory("ASM"); //$NON-NLS-1$
-		} catch (CoreException e) {
-			ATLLogger.log(Level.SEVERE, e.getLocalizedMessage(), e);
-		}
-		return null;
+	public String getDefaultModelFactoryName() {
+		return ASMFactory.MODEL_FACTORY_NAME;
 	}
 
 	/**
#P org.eclipse.m2m.atl.core
Index: src/org/eclipse/m2m/atl/core/service/CoreService.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core/src/org/eclipse/m2m/atl/core/service/CoreService.java,v
retrieving revision 1.3
diff -u -r1.3 CoreService.java
--- src/org/eclipse/m2m/atl/core/service/CoreService.java	11 Dec 2008 17:23:30 -0000	1.3
+++ src/org/eclipse/m2m/atl/core/service/CoreService.java	12 Dec 2008 14:25:47 -0000
@@ -53,8 +53,6 @@
 
 	private static Map<String, Object> extractorRegistry = new HashMap<String, Object>();
 
-	private static Map<String, Object> factoryRegistry = new HashMap<String, Object>();
-
 	private CoreService() {
 		super();
 	}
@@ -100,15 +98,14 @@
 	}
 
 	/**
-	 * Registers an factory in the factoryRegistry.
+	 * Creates a new {@link ModelFactory} with the given name.
 	 * 
 	 * @param name
 	 *            the factory name
-	 * @param factory
-	 *            the factory
+	 * @return the new ModelFactory
 	 */
-	public static void registerFactory(String name, ModelFactory factory) {
-		register(factoryRegistry, name, factory);
+	public static ModelFactory createModelFactory(String name) throws CoreException {
+		return (ModelFactory)getExtensionClass(MODELS_EXTENSION_POINT, "modelFactory", name);
 	}
 
 	private static Object getExtensionClass(String extensionId, String executableExtensionName,
@@ -116,18 +113,24 @@
 		if (registry.containsKey(extensionName)) {
 			return registry.get(extensionName);
 		} else {
-			if (Platform.isRunning()) {
-				final IExtension[] extensions = Platform.getExtensionRegistry()
-						.getExtensionPoint(extensionId).getExtensions();
-				for (int i = 0; i < extensions.length; i++) {
-					final IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
-					for (int j = 0; j < configElements.length; j++) {
-						if (configElements[j].getAttribute("name").equals(extensionName)) { //$NON-NLS-1$
-							Object executable = configElements[j]
-									.createExecutableExtension(executableExtensionName);
-							registry.put(extensionName, executable);
-							return executable;
-						}
+			Object executable = getExtensionClass(extensionId, executableExtensionName, extensionName);
+			registry.put(extensionName, executable);
+			return executable;
+		}
+	}
+
+	private static Object getExtensionClass(String extensionId, String executableExtensionName,
+			String extensionName) throws CoreException {
+		if (Platform.isRunning()) {
+			final IExtension[] extensions = Platform.getExtensionRegistry().getExtensionPoint(extensionId)
+					.getExtensions();
+			for (int i = 0; i < extensions.length; i++) {
+				final IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
+				for (int j = 0; j < configElements.length; j++) {
+					if (configElements[j].getAttribute("name").equals(extensionName)) { //$NON-NLS-1$
+						Object executable = configElements[j]
+								.createExecutableExtension(executableExtensionName);
+						return executable;
 					}
 				}
 			}
@@ -171,18 +174,6 @@
 		return (IExtractor)getExtensionClass(EXTRACTORS_EXTENSION_POINT, "class", name, extractorRegistry); //$NON-NLS-1$
 	}
 
-	/**
-	 * Returns the ModelFactory matching the given name.
-	 * 
-	 * @param name
-	 *            the ModelFactory name
-	 * @return the ModelFactory matching the given name
-	 * @throws CoreException
-	 */
-	public static ModelFactory getModelFactory(String name) throws CoreException {
-		return (ModelFactory)getExtensionClass(MODELS_EXTENSION_POINT, "modelFactory", name, factoryRegistry); //$NON-NLS-1$
-	}
-
 	private static String[] getExtensionsNames(String extensionId) {
 		List<String> launcherNames = new ArrayList<String>();
 		if (Platform.isRunning()) {
Index: src/org/eclipse/m2m/atl/core/IModel.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core/src/org/eclipse/m2m/atl/core/IModel.java,v
retrieving revision 1.1
diff -u -r1.1 IModel.java
--- src/org/eclipse/m2m/atl/core/IModel.java	9 Dec 2008 11:27:11 -0000	1.1
+++ src/org/eclipse/m2m/atl/core/IModel.java	12 Dec 2008 14:25:47 -0000
@@ -63,4 +63,11 @@
 	 * Deletes the model in memory.
 	 */
 	void dispose();
+	
+	/**
+	 * Returns the ModelFactory used to create the current model.
+	 * 
+	 * @return true if the model allows writing
+	 */
+	ModelFactory getModelFactory();
 }
Index: src/org/eclipse/m2m/atl/core/ModelFactory.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core/src/org/eclipse/m2m/atl/core/ModelFactory.java,v
retrieving revision 1.1
diff -u -r1.1 ModelFactory.java
--- src/org/eclipse/m2m/atl/core/ModelFactory.java	9 Dec 2008 11:27:11 -0000	1.1
+++ src/org/eclipse/m2m/atl/core/ModelFactory.java	12 Dec 2008 14:25:47 -0000
@@ -24,14 +24,14 @@
 	 * 
 	 * @return the default {@link IInjector}
 	 */
-	public abstract IInjector getDefaultInjector();
+	public abstract String getDefaultInjectorName();
 
 	/**
 	 * Returns a default {@link IExtractor} associated with the current factory.
 	 * 
 	 * @return the default {@link IExtractor}
 	 */
-	public abstract IExtractor getDefaultExtractor();
+	public abstract String getDefaultExtractorName();
 
 	/**
 	 * Creates a new {@link IReferenceModel} using default options.
Index: src/org/eclipse/m2m/atl/core/launch/ILauncher.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/plugins/org.eclipse.m2m.atl.core/src/org/eclipse/m2m/atl/core/launch/ILauncher.java,v
retrieving revision 1.1
diff -u -r1.1 ILauncher.java
--- src/org/eclipse/m2m/atl/core/launch/ILauncher.java	9 Dec 2008 11:27:11 -0000	1.1
+++ src/org/eclipse/m2m/atl/core/launch/ILauncher.java	12 Dec 2008 14:25:47 -0000
@@ -13,7 +13,6 @@
 import java.util.Map;
 
 import org.eclipse.m2m.atl.core.IModel;
-import org.eclipse.m2m.atl.core.ModelFactory;
 
 /**
  * The ILauncher interface defines a transformation launcher, and a set of associated options.
@@ -112,7 +111,7 @@
 	 * @return the transformation return result
 	 */
 	Object launch(String mode, Map<String, Object> options, Object... modules);
-	
+
 	/**
 	 * Launches the transformation using the given parameters and the given set of modules.
 	 * 
@@ -142,11 +141,12 @@
 	 * @return a previously added library with the given name
 	 */
 	Object getLibrary(String libraryName);
-	
+
 	/**
-	 * Returns the default {@link ModelFactory}.
-	 * @return the default {@link ModelFactory}
+	 * Returns the default ModelFactory name.
+	 * 
+	 * @return the default ModelFactory name
 	 */
-	ModelFactory getDefaultModelFactory();
+	String getDefaultModelFactoryName();
 
 }
#P org.eclipse.m2m.atl.examples.public2private.ui
Index: src/org/eclipse/m2m/atl/examples/public2private/ui/PrivatizeAction.java
===================================================================
RCS file: /cvsroot/modeling/org.eclipse.m2m/org.eclipse.m2m.atl/examples/org.eclipse.m2m.atl.examples.public2private.ui/src/org/eclipse/m2m/atl/examples/public2private/ui/PrivatizeAction.java,v
retrieving revision 1.2
diff -u -r1.2 PrivatizeAction.java
--- src/org/eclipse/m2m/atl/examples/public2private/ui/PrivatizeAction.java	11 Dec 2008 17:12:45 -0000	1.2
+++ src/org/eclipse/m2m/atl/examples/public2private/ui/PrivatizeAction.java	12 Dec 2008 14:25:49 -0000
@@ -39,8 +39,6 @@
  */
 public class PrivatizeAction implements IObjectActionDelegate {
 
-	private static ModelFactory factory;
-
 	private static IInjector injector;
 
 	private static IExtractor extractor;
@@ -57,20 +55,12 @@
 		// ATL public2private transformation
 		Bundle bundle = Platform.getBundle("org.eclipse.m2m.atl.examples.public2private"); //$NON-NLS-1$
 		asmURL = bundle.getEntry("transformation/Public2Private.asm"); //$NON-NLS-1$
-
-		// Defaults
 		try {
-			factory = CoreService.getModelFactory("EMF"); //$NON-NLS-1$
+			injector = CoreService.getInjector("EMF");
+			extractor = CoreService.getExtractor("EMF");			
 		} catch (CoreException e) {
 			e.printStackTrace();
-		}
-		injector = factory.getDefaultInjector();
-		extractor = factory.getDefaultExtractor();
-
-		// Metamodels
-		umlMetamodel = factory.newReferenceModel();
-		injector.inject(umlMetamodel, "uri:http://www.eclipse.org/uml2/2.1.0/UML";); //$NON-NLS-1$
-		refiningTraceMetamodel = factory.getBuiltInResource("RefiningTrace"); //$NON-NLS-1$
+		}		
 	}
 
 	/**
@@ -98,11 +88,23 @@
 		// Getting files from selection
 		IStructuredSelection iss = (IStructuredSelection)currentSelection;
 		for (Iterator<?> iterator = iss.iterator(); iterator.hasNext();) {
-			privatize((IFile)iterator.next());
+			try {
+				privatize((IFile)iterator.next());				
+			} catch (CoreException e) {
+				e.printStackTrace();
+			}
 		}
 	}
 
-	private void privatize(IFile file) {
+	private void privatize(IFile file) throws CoreException {
+		// Defaults
+		ModelFactory factory = CoreService.createModelFactory("EMF"); //$NON-NLS-1$
+
+		// Metamodels
+		umlMetamodel = factory.newReferenceModel();
+		injector.inject(umlMetamodel, "uri:http://www.eclipse.org/uml2/2.1.0/UML";); //$NON-NLS-1$
+		refiningTraceMetamodel = factory.getBuiltInResource("RefiningTrace"); //$NON-NLS-1$
+		
 		// Getting launcher
 		ILauncher launcher = null;
 		try {
begin:vcard
fn:William Piers
n:Piers;William
org:Obeo
adr:2 rue Robert Schumann;;lot 24;NANTES;;44408;France
email;internet:william.piers@xxxxxxx
title:MDA Consultant
tel;work:+33 (0)2 51 13 51 82
tel;cell:+33 (0)6 20 31 75 98
url:http://www.obeo.fr
version:2.1
end:vcard


Back to the top