[428843] test aspects generation unders xtend / xpand

Change-Id: I1ba2f8d393ea0b7ae59fd83014d94ce8cb5e2da5
diff --git a/plugins/org.eclipse.gmf.codegen.xtend.ui/src/org/eclipse/gmf/codegen/xtend/ui/handlers/CodegenEmittersWithXtend2.java b/plugins/org.eclipse.gmf.codegen.xtend.ui/src/org/eclipse/gmf/codegen/xtend/ui/handlers/CodegenEmittersWithXtend2.java
index 64e7727..7a4ee9a 100644
--- a/plugins/org.eclipse.gmf.codegen.xtend.ui/src/org/eclipse/gmf/codegen/xtend/ui/handlers/CodegenEmittersWithXtend2.java
+++ b/plugins/org.eclipse.gmf.codegen.xtend.ui/src/org/eclipse/gmf/codegen/xtend/ui/handlers/CodegenEmittersWithXtend2.java
@@ -104,8 +104,8 @@
 
 	public CodegenEmittersWithXtend2(boolean useBaseTemplatesOnly, String templateDirectory, boolean includeDynamicModelTemplates) {
 		super(useBaseTemplatesOnly, templateDirectory, includeDynamicModelTemplates);
-		if (!useBaseTemplatesOnly) {
-			myExtensionTemplateProvider = new ExtensionTemplatesProviderImpl(templateDirectory);
+		if (templateDirectory != null && !templateDirectory.isEmpty()) {
+			myExtensionTemplateProvider = new ExtensionTemplatesProviderImpl(templateDirectory,!useBaseTemplatesOnly);
 		}
 		myInjector = Guice.createInjector(new GMFGeneratorModule(myExtensionTemplateProvider));
 	}
@@ -746,18 +746,19 @@
 	@Override
 	protected TextEmitter newXpandEmitter(String definition) {
 		String[] parts = definition.split(PATH_SEPARATOR);
-		String templateFQN = createXpandPath(parts);
+		String templateFQN = getXtendClassFQN(parts);
 		return getXtendEmitter(templateFQN, parts[parts.length-1]);
 	}
 	
 	@Override
 	protected TextEmitter getQualifiedClassNameEmitterForPrimaryTemplate(String templateName) throws UnexpectedBehaviourException {
-		return getQualifiedClassNameEmitter(createXpandPath(templateName.split(PATH_SEPARATOR)));
+		return getQualifiedClassNameEmitter(getXtendClassFQN(templateName.split(PATH_SEPARATOR)));
 	}
 	
-	private String createXpandPath(String[] parts) {
+	private String getXtendClassFQN(String[] parts) {
+		int PARTS_FOR_METHOD_CALL = 1;
 		StringBuilder builder = new StringBuilder(parts[0]);
-		for( int i = 1 ; i < parts.length-2 ; i++ ) {
+		for( int i = 1 ; i < parts.length-PARTS_FOR_METHOD_CALL ; i++ ) {
 			builder.append(PATH_SEPARATOR);
 			builder.append(parts[i]);
 		}
diff --git a/plugins/org.eclipse.gmf.codegen.xtend.ui/src/org/eclipse/gmf/codegen/xtend/ui/handlers/GeneratorWithXtend2.java b/plugins/org.eclipse.gmf.codegen.xtend.ui/src/org/eclipse/gmf/codegen/xtend/ui/handlers/GeneratorWithXtend2.java
index 6b2833e..617627a 100644
--- a/plugins/org.eclipse.gmf.codegen.xtend.ui/src/org/eclipse/gmf/codegen/xtend/ui/handlers/GeneratorWithXtend2.java
+++ b/plugins/org.eclipse.gmf.codegen.xtend.ui/src/org/eclipse/gmf/codegen/xtend/ui/handlers/GeneratorWithXtend2.java
@@ -18,8 +18,11 @@
 	}
 
 	protected void customRun() throws InterruptedException, UnexpectedBehaviourException {
-		super.customRun();
-		hookGenerationCompleted();
+		try {
+			super.customRun();
+		} finally {
+			hookGenerationCompleted();
+		}
 	}
 
 	protected CodegenEmittersWithXtend2 getEmitters() {
@@ -27,7 +30,7 @@
 	}
 
 	protected void hookGenerationCompleted() {
-		//dispose emitters if needed 
+		myEmitters.disposeEmitters();
 	}
 
 }
diff --git a/plugins/org.eclipse.gmf.codegen.xtend/src/org/eclipse/gmf/codegen/util/ExtensionTemplatesProviderImpl.java b/plugins/org.eclipse.gmf.codegen.xtend/src/org/eclipse/gmf/codegen/util/ExtensionTemplatesProviderImpl.java
index 3cd98bc..28100dc 100644
--- a/plugins/org.eclipse.gmf.codegen.xtend/src/org/eclipse/gmf/codegen/util/ExtensionTemplatesProviderImpl.java
+++ b/plugins/org.eclipse.gmf.codegen.xtend/src/org/eclipse/gmf/codegen/util/ExtensionTemplatesProviderImpl.java
@@ -2,15 +2,13 @@
 
 import java.io.IOException;
 import java.net.MalformedURLException;
+import java.util.Enumeration;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.wiring.FrameworkWiring;
@@ -27,8 +25,6 @@
 
 	private final String myCustomTemplatePath;
 
-	private final IProject myProject;
-
 	private List<Class<?>> myDinamicClasses;
 
 	private List<Class<?>> myCustomClasses;
@@ -37,21 +33,45 @@
 
 	private final Bundle myBundle;
 
-	public ExtensionTemplatesProviderImpl(String customPath) {
-		if (customPath.startsWith(SLASH)) {
-			customPath = customPath.substring(1, customPath.length() - 1);
+	private final boolean myAspectsNeed;
+
+	private final boolean myUsePluginNotProject;
+
+	public ExtensionTemplatesProviderImpl(String customPath, boolean aspectsNeed) {
+		myUsePluginNotProject = customPath.startsWith("platform:/plugin/");
+		if (!myUsePluginNotProject) {
+			if (customPath.startsWith(SLASH)) {
+				customPath = customPath.substring(1, customPath.length() - 1);
+			}
+			String[] parts = customPath.split(SLASH);
+			IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(parts[0]);
+			myCustomTemplatePath = getTemplateEntryFromURL(customPath, 1);
+			ManifestUtil.createOrFillManifest(project);
+			try {
+				myBundle = loadBundle(project);
+			} catch (MalformedURLException e) {
+				throw new RuntimeException("Cannot create correct URL for Bundle.", e);
+			} catch (BundleException e) {
+				throw new RuntimeException("Error. Bundle was not load.", e);
+			}
+		} else {
+			myCustomTemplatePath = getTemplateEntryFromURL(customPath, 3);
+			myBundle = Platform.getBundle(getBundleNameFromURL(customPath));
 		}
-		String[] parts = customPath.split(SLASH);
-		myProject = ResourcesPlugin.getWorkspace().getRoot().getProject(parts[0]);
-		myCustomTemplatePath = concatWithoutFirst(parts);
-		ManifestUtil.createOrFillManifest(myProject);
-		try {
-			myBundle = loadBundle(myProject);
-		} catch (MalformedURLException e) {
-			throw new RuntimeException("Cannot create correct URL for Bundle.", e);
-		} catch (BundleException e) {
-			throw new RuntimeException("Error. Bundle was not load.", e);
+		myAspectsNeed = aspectsNeed;
+	}
+
+	private static String getBundleNameFromURL(String url) {
+		return url.split(SLASH)[2];
+	}
+
+	private static String getTemplateEntryFromURL(String url, int part) {
+		StringBuilder result = new StringBuilder();
+		String[] parts = url.split(SLASH);
+		for (int i = part; i < parts.length; i++) {
+			result.append(parts[i]).append(SLASH);
 		}
+		return result.toString();
 	}
 
 	private static Bundle loadBundle(IProject project) throws MalformedURLException, BundleException {
@@ -59,19 +79,11 @@
 		return CodegenXtendPlugin.getInstance().getContext().installBundle(url);
 	}
 
-	private static String concatWithoutFirst(String[] parts) {
-		StringBuilder builder = new StringBuilder();
-		for (int i = 1; i < parts.length; i++) {
-			builder.append(SLASH).append(parts[i]);
-		}
-		return builder.toString();
-	}
-
 	@Override
 	public List<Class<?>> getCustomTemplateClasses() {
 		if (myCustomClasses == null) {
 			myCustomClasses = new LinkedList<Class<?>>();
-			myCustomClasses.addAll(loadCustomClasses(EMPLTY_STRING, false));
+			myCustomClasses.addAll(loadClassesFromBundle(false));
 		}
 		return myCustomClasses;
 	}
@@ -80,7 +92,9 @@
 	public List<Class<?>> getDynamicTemplateClasses() {
 		if (myDinamicClasses == null) {
 			myDinamicClasses = new LinkedList<Class<?>>();
-			myDinamicClasses.addAll(loadCustomClasses(DEFAULT_DYNAMIC_TEMPLATES_FOLDER, true));
+			if (myAspectsNeed) {
+				myDinamicClasses.addAll(loadClassesFromBundle(true));
+			}
 		}
 		return myDinamicClasses;
 	}
@@ -90,86 +104,46 @@
 		return _class.getSuperclass();
 	}
 
-	private List<Class<?>> loadCustomClasses(String pathSuffix, boolean aspectNotCustom) {
-		return loadFolder(myProject.getFolder(myCustomTemplatePath + pathSuffix), aspectNotCustom ? "aspects" : "");
-	}
-
-	private List<Class<?>> loadFolder(IFolder parentFolder, String relativPath) {
-		List<Class<?>> result = new LinkedList<Class<?>>();
-		IFile[] files = null;
-		IFolder[] folders = null;
-		try {
-			files = (IFile[]) getSubResources(parentFolder, true);
-		} catch (CoreException e) {
-			e.printStackTrace();
-		}
-		if (files != null && files.length > 0) {
-			for (IFile fileToLoad : files) {
-				try {
-					result.add(loadClass(fileToLoad, relativPath));
-				} catch (ClassNotFoundException e) {
-					throw new RuntimeException("Error. Did not load " + fileToLoad.getName() + ". Class not found.", e);
-				} catch (IOException e) {
-					throw new RuntimeException("Error has occurred when try to load " + fileToLoad.getName(), e);
-				}
-			}
-		}
-		try {
-			folders = (IFolder[]) getSubResources(parentFolder, false);
-			if (folders != null && folders.length > 0) {
-				for (IFolder folderToLoad : folders) {
-					result.addAll(loadFolder(folderToLoad, createRelativPath(relativPath, folderToLoad.getName())));
-				}
-			}
-		} catch (CoreException e) {
-			throw new RuntimeException("Error.  Cannot load folder/package " + parentFolder.getName(), e);
-		}
-		return result;
-	}
-
-	private String createRelativPath(String relativePath, String child) {
-		return relativePath.length() > 0 ? relativePath + "." + child : child;
-	}
-
-	private IResource[] getSubResources(IFolder parentFolder, boolean filesNotFolders) throws CoreException {
-		List<IResource> result = new LinkedList<IResource>();
-		for (IResource res : parentFolder.members()) {
-			if (filesNotFolders) {
-				if (res instanceof IFile) {
-					IFile xtendFile = (IFile) res;
-					if (TEMPLATE_FILE_EXTENSIION.equals(xtendFile.getFileExtension())) {
-						result.add(xtendFile);
-					}
-				}
-			} else {
-				if (res instanceof IFolder) {
-					result.add((IFolder) res);
-				}
-			}
-		}
-		if (result.size() > 0) {
-			if (filesNotFolders) {
-				return result.toArray(new IFile[result.size()]);
-			}
-			return result.toArray(new IFolder[result.size()]);
-		}
-		return null;
-	}
-
-	private Class<?> loadClass(IFile classFile, String relativePath) throws ClassNotFoundException, IOException {
-		String className = createRelativPath(relativePath, classFile.getName().replace(POINT_SEPARATOR + TEMPLATE_FILE_EXTENSIION, EMPLTY_STRING));
+	private Class<?> loadClass(String className) throws ClassNotFoundException, IOException {
 		return myBundle.loadClass(className);
 	}
 
 	@Override
 	public void dispose() {
-		try {
-			Bundle systemBundle = CodegenXtendPlugin.getInstance().getContext().getBundle(0);
-			myBundle.uninstall();
-			FrameworkWiring frameworkWiring = systemBundle.adapt(FrameworkWiring.class);
-			frameworkWiring.refreshBundles(frameworkWiring.getRemovalPendingBundles());
-		} catch (BundleException e) {
-			throw new RuntimeException("Error while unloading bundle.", e);
+		if (!myUsePluginNotProject) {
+			try {
+				Bundle systemBundle = CodegenXtendPlugin.getInstance().getContext().getBundle(0);
+				myBundle.uninstall();
+				FrameworkWiring frameworkWiring = systemBundle.adapt(FrameworkWiring.class);
+				frameworkWiring.refreshBundles(frameworkWiring.getRemovalPendingBundles());
+			} catch (BundleException e) {
+				throw new RuntimeException("Error while unloading bundle.", e);
+			}
 		}
 	}
+
+	private List<Class<?>> loadClassesFromBundle(boolean aspectNotCustom) {
+		List<Class<?>> result = new LinkedList<Class<?>>();
+		Enumeration<java.net.URL> classsesURL = myBundle.findEntries(myCustomTemplatePath, "*.xtend", true);
+		while (classsesURL.hasMoreElements()) {
+			String classPath = classsesURL.nextElement().toString().trim();
+			classPath = classPath.substring(classPath.indexOf(myCustomTemplatePath), classPath.length()).replace(myCustomTemplatePath, EMPLTY_STRING).replace(POINT_SEPARATOR + TEMPLATE_FILE_EXTENSIION, EMPLTY_STRING);
+			try {
+				if (aspectNotCustom && classPath.startsWith("aspects")) {
+					result.add(loadClass(getFQCN(classPath)));
+				} else if (!aspectNotCustom && !classPath.startsWith("aspects")) {
+					result.add(loadClass(getFQCN(classPath)));
+				}
+			} catch (ClassNotFoundException e) {
+				throw new RuntimeException("Error. Did not load " + classPath + ". Class not found.", e);
+			} catch (IOException e) {
+				throw new RuntimeException("Error has occurred when try to load " + classPath, e);
+			}
+		}
+		return result;
+	}
+
+	private String getFQCN(String entryPath) {
+		return entryPath.replace(SLASH, POINT_SEPARATOR);
+	}
 }
diff --git a/test-examples/links/org.eclipse.gmf.tooling.examples.links/.classpath b/test-examples/links/org.eclipse.gmf.tooling.examples.links/.classpath
index 121e527..e413ef6 100644
--- a/test-examples/links/org.eclipse.gmf.tooling.examples.links/.classpath
+++ b/test-examples/links/org.eclipse.gmf.tooling.examples.links/.classpath
@@ -1,6 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
+	<classpathentry kind="src" path="xtend-gen"/>
 	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="xtend"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/test-examples/links/org.eclipse.gmf.tooling.examples.links/.gitignore b/test-examples/links/org.eclipse.gmf.tooling.examples.links/.gitignore
index 5e56e04..7985f5e 100644
--- a/test-examples/links/org.eclipse.gmf.tooling.examples.links/.gitignore
+++ b/test-examples/links/org.eclipse.gmf.tooling.examples.links/.gitignore
@@ -1 +1,3 @@
 /bin
+/xtend-gen
+*.java._trace
\ No newline at end of file
diff --git a/test-examples/links/org.eclipse.gmf.tooling.examples.links/META-INF/MANIFEST.MF b/test-examples/links/org.eclipse.gmf.tooling.examples.links/META-INF/MANIFEST.MF
index b1b25b3..2aea319 100644
--- a/test-examples/links/org.eclipse.gmf.tooling.examples.links/META-INF/MANIFEST.MF
+++ b/test-examples/links/org.eclipse.gmf.tooling.examples.links/META-INF/MANIFEST.MF
@@ -11,5 +11,10 @@
  org.eclipse.gmf.tooling.examples.links.impl,
  org.eclipse.gmf.tooling.examples.links.util
 Require-Bundle: org.eclipse.core.runtime,
- org.eclipse.emf.ecore;visibility:=reexport
+ org.eclipse.emf.ecore;visibility:=reexport,
+ org.eclipse.xtend.lib,
+ com.google.guava,
+ org.eclipse.gmf.codegen.xtend,
+ org.eclipse.gmf.codegen
 Bundle-ActivationPolicy: lazy
+
diff --git a/test-examples/links/org.eclipse.gmf.tooling.examples.links/build.properties b/test-examples/links/org.eclipse.gmf.tooling.examples.links/build.properties
index 71266a4..c237976 100644
--- a/test-examples/links/org.eclipse.gmf.tooling.examples.links/build.properties
+++ b/test-examples/links/org.eclipse.gmf.tooling.examples.links/build.properties
@@ -1,10 +1,13 @@
 bin.includes = .,\
                model/,\
                META-INF/,\
+               xtend/,\
                plugin.xml,\
                plugin.properties,\
                about.html
 jars.compile.order = .
-source.. = src/
+source.. = src/,\
+           xtend/,\
+           xtend-gen/
 output.. = bin/
 
diff --git a/test-examples/links/org.eclipse.gmf.tooling.examples.links/pom.xml b/test-examples/links/org.eclipse.gmf.tooling.examples.links/pom.xml
index 9d8a719..265e150 100644
--- a/test-examples/links/org.eclipse.gmf.tooling.examples.links/pom.xml
+++ b/test-examples/links/org.eclipse.gmf.tooling.examples.links/pom.xml
@@ -20,4 +20,24 @@
 	<relativePath>../</relativePath>
   </parent>
   
+  <build>
+		<plugins>
+			<plugin>
+				<groupId>org.eclipse.xtend</groupId>
+				<artifactId>xtend-maven-plugin</artifactId>
+				<version>2.4.3</version>
+				<executions>
+					<execution>
+						<goals>
+							<goal>compile</goal>
+						</goals>
+						<configuration>
+							<encoding>UTF-8</encoding>
+							<outputDirectory>xtend-gen</outputDirectory>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
 </project>
diff --git a/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/aspects/xpt/Common.xpt b/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/aspects/xpt/Common.xpt
new file mode 100644
index 0000000..8680759
--- /dev/null
+++ b/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/aspects/xpt/Common.xpt
@@ -0,0 +1,7 @@
+«IMPORT 'http://www.eclipse.org/gmf/2009/GenModel'»
+
+«AROUND generatedClassComment(comment : String) FOR OclAny-»
+/** comment generated by aspects.CommonExtended */«ENDAROUND»
+
+«AROUND generatedMemberComment(comment : String) FOR OclAny-»
+/** comment generated by aspects.CommonExtended */«ENDAROUND»
\ No newline at end of file
diff --git a/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/aspects/xpt/CommonExtended.xtend b/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/aspects/xpt/CommonExtended.xtend
new file mode 100644
index 0000000..233c0d7
--- /dev/null
+++ b/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/aspects/xpt/CommonExtended.xtend
@@ -0,0 +1,11 @@
+package aspects.xpt
+
+import xpt.Common
+
+class CommonExtended extends Common {
+	
+	override doGeneratedComment(String comment, String comment2) {
+		return "/** comment generated by aspects.CommonExtended */";
+	}
+	
+}
\ No newline at end of file
diff --git a/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/custom/CustomTemplate.xpt b/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/custom/CustomTemplate.xpt
new file mode 100644
index 0000000..531d1da
--- /dev/null
+++ b/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/custom/CustomTemplate.xpt
@@ -0,0 +1,15 @@
+«IMPORT 'http://www.eclipse.org/gmf/2009/GenModel'»
+
+«DEFINE qualifiedClassName FOR gmfgen::GenEditorGenerator»«EXPAND packageName».«EXPAND className»«ENDDEFINE»
+«DEFINE className FOR gmfgen::GenEditorGenerator»CustomClass«ENDDEFINE»
+«DEFINE packageName FOR gmfgen::GenEditorGenerator»custom«ENDDEFINE»
+«DEFINE CustomTemplate FOR gmfgen::GenEditorGenerator»
+	package «EXPAND packageName»;
+		
+	public class «EXPAND className» {
+			
+		private static String SOME_VAR = "TEST_PLUGIN_NAME = «self.plugin.name»";
+			
+		public void customClassMethod() {}
+	}
+«ENDDEFINE»
\ No newline at end of file
diff --git a/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/custom/CustomTemplate.xtend b/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/custom/CustomTemplate.xtend
new file mode 100644
index 0000000..3bfa1c1
--- /dev/null
+++ b/test-examples/links/org.eclipse.gmf.tooling.examples.links/xtend/custom/CustomTemplate.xtend
@@ -0,0 +1,25 @@
+package custom
+
+import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator
+
+class CustomTemplate {
+	
+	def packageName(GenEditorGenerator it) '''custom'''
+	
+	def className(GenEditorGenerator it) '''CustomClass'''
+	
+	def qualifiedClassName(GenEditorGenerator it) '''«packageName(it)».«className(it)»'''
+
+	def fullPath(GenEditorGenerator it) '''«qualifiedClassName(it)»'''
+	
+	def CustomTemplate(GenEditorGenerator it) '''
+		package «packageName(it)»;
+		
+		public class «className(it)» {
+			
+			private static String SOME_VAR = "TEST_PLUGIN_NAME = «it.plugin.name»";
+			
+			public void customClassMethod() {}
+		}
+	'''
+}
\ No newline at end of file
diff --git a/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/samples/BaseSampleTest.java b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/samples/BaseSampleTest.java
index a1a8426..7ac7085 100644
--- a/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/samples/BaseSampleTest.java
+++ b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/samples/BaseSampleTest.java
@@ -1,9 +1,5 @@
 package org.eclipse.gmf.tests.samples;
 
-import java.io.File;
-import java.io.IOException;
-import java.net.URISyntaxException;
-
 import junit.framework.TestCase;
 
 import org.eclipse.emf.common.util.URI;
@@ -13,24 +9,27 @@
 import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator;
 import org.eclipse.gmf.tests.Plugin;
 import org.eclipse.gmf.tests.setup.GenProjectBaseSetup;
-import org.eclipse.gmf.tests.setup.RuntimeBasedGeneratorConfiguration;
+import org.eclipse.gmf.tests.setup.GeneratorConfiguration;
 
 
 public abstract class BaseSampleTest extends TestCase {
 	
 	public final static String BASE_PATH = Plugin.getBundleContext().getBundle().getLocation().replaceFirst("reference:file:", "").replaceFirst("tests/org.eclipse.gmf.tests/", "");
 	
-	private final RuntimeBasedGeneratorConfiguration myGenConfiguration;
+	private final GeneratorConfiguration myGenConfiguration;
 	
-	public BaseSampleTest(String name, RuntimeBasedGeneratorConfiguration genConfig) {
+	public BaseSampleTest(String name, GeneratorConfiguration genConfig) {
 		super(name);
 		myGenConfiguration = genConfig;
 	}
 
 	protected abstract String getRelativeGMFGENPath();
 	
-	public void genAndCompile(String relativePath, RuntimeBasedGeneratorConfiguration genConfig) throws Exception {
-		GenEditorGenerator editorGen = loadGMFGENModel(relativePath);
+	public void genAndCompile(String relativePath, GeneratorConfiguration genConfig) throws Exception {
+		genAndCompile(loadGMFGENModel(relativePath), genConfig);
+	}
+	
+	public void genAndCompile(GenEditorGenerator editorGen, GeneratorConfiguration genConfig) throws Exception {
 		new GenProjectBaseSetup(genConfig).generateAndCompile(editorGen);
 	}
 	
@@ -38,16 +37,8 @@
 		return loadEditorGen(URI.createURI(getRelativeGMFGENPath())); //$NON-NLS-1$);
 	}
 	
-	private GenEditorGenerator loadEditorGen(String path) throws URISyntaxException, IOException {
-		GenEditorGenerator result = null;
-		File file = new File(path);
-		if (file.exists()) {
-			URI uriEditorGen = URI.createFileURI(file.getAbsolutePath());
-			if (uriEditorGen != null) {
-				result = loadEditorGen(uriEditorGen);
-			}
-		}
-		return result;
+	protected GeneratorConfiguration getGenerationConfiguration() {
+		return myGenConfiguration;
 	}
 	
 	private GenEditorGenerator loadEditorGen(URI u) {
diff --git a/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/samples/LinksSampleTest.java b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/samples/LinksSampleTest.java
index 555707f..197960b 100644
--- a/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/samples/LinksSampleTest.java
+++ b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/samples/LinksSampleTest.java
@@ -1,5 +1,16 @@
 package org.eclipse.gmf.tests.samples;
 
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.gmf.codegen.gmfgen.GMFGenFactory;
+import org.eclipse.gmf.codegen.gmfgen.GenCustomGeneratorExtension;
+import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator;
+import org.eclipse.gmf.codegen.gmfgen.GenTemplateInvocation;
 import org.eclipse.gmf.tests.setup.RuntimeBasedGeneratorConfiguration;
 
 
@@ -20,4 +31,64 @@
 		return GIT_GMFGEN_PATH;
 	}
 	
+	public void testAspects() throws Exception {
+		GenEditorGenerator editorGen = prepareCustomEditorGen("aspects", true);
+		genAndCompile(editorGen, getGenerationConfiguration());
+		IProject aspectsProject = ResourcesPlugin.getWorkspace().getRoot().getProject(editorGen.getPluginDirectory().split("/")[1]);
+		assertTrue(aspectsProject.exists());
+		IFile file = aspectsProject.getFile(new Path("src/org/eclipse/gmf/tooling/examples/links/diagram/aspects/edit/parts/ChildNodeBEditPart.java"));
+		assertTrue(file.exists());
+		BufferedReader classToTest = new BufferedReader(new InputStreamReader(file.getContents(), file.getCharset()));
+		boolean foundCommentExtendedCommon = false;
+		boolean foundCommentBaseCommon = false;
+		String line;
+		while ((line = classToTest.readLine()) != null) {
+			if (line.trim().startsWith("/** comment generated by aspects.CommonExtended */")) {
+				foundCommentExtendedCommon = true;
+			}
+			if (line.trim().startsWith("* @generated")) {
+				foundCommentBaseCommon = true;
+			}
+		}
+		assertTrue("Aspects code was not invoked.", foundCommentExtendedCommon);
+		assertFalse("Aspects code was not replase base code.", foundCommentBaseCommon);
+	}
+	
+	protected GenEditorGenerator prepareCustomEditorGen(String suffix, boolean useDynamicTemplates) throws Exception {
+		GenEditorGenerator editorGen = loadGMFGENModel(getRelativeGMFGENPath());
+		editorGen.setPackageNamePrefix(createPackageNamePrefix(editorGen, suffix));
+		editorGen.setPluginDirectory(createPluginDirectory(editorGen, suffix));
+		editorGen.getPlugin().setID(editorGen.getPlugin().getID() + "." + suffix);
+		editorGen.setTemplateDirectory("platform:/plugin/org.eclipse.gmf.tooling.examples.links/xtend/");
+		editorGen.setDynamicTemplates(useDynamicTemplates);
+		return editorGen;
+	}
+	
+	protected GenCustomGeneratorExtension createCustomExtension(GenEditorGenerator self) {
+		GenCustomGeneratorExtension result = GMFGenFactory.eINSTANCE.createGenCustomGeneratorExtension();
+		result.setRootInput(self);
+		GenTemplateInvocation t = GMFGenFactory.eINSTANCE.createGenTemplateInvocation();
+		t.setOclExpression("self");
+		t.setTemplateFqn("custom::CustomTemplate::CustomTemplate");
+		result.getInvocations().add(t);
+		return result;
+	}
+	
+	private String createPackageNamePrefix(GenEditorGenerator editorGen, String suffix) {
+		return editorGen.getPackageNamePrefix() + "." +suffix;
+	}
+	
+	private String createPluginDirectory(GenEditorGenerator editorGen, String suffix) {
+		String pluginDirectory = editorGen.getPluginDirectory();
+		if (pluginDirectory.startsWith("/")) {
+			pluginDirectory = pluginDirectory.substring(1);
+		}
+		String[] pluginDirectoryParts = pluginDirectory.split("/");
+		StringBuilder result = new StringBuilder("/").append(pluginDirectoryParts[0]);
+		result.append(".").append(suffix).append("/");
+		for (int i = 1; i < pluginDirectoryParts.length; i++) {
+			result.append(pluginDirectoryParts[i]).append("/");
+		}
+		return result.toString();
+	}
 }
diff --git a/tests/org.eclipse.gmf.tooling.tests.xtend/src/org/eclipse/gmf/tooling/tests/xtend/samples/LinksSampleTestXtend.java b/tests/org.eclipse.gmf.tooling.tests.xtend/src/org/eclipse/gmf/tooling/tests/xtend/samples/LinksSampleTestXtend.java
index 88ea73b..ffd5297 100644
--- a/tests/org.eclipse.gmf.tooling.tests.xtend/src/org/eclipse/gmf/tooling/tests/xtend/samples/LinksSampleTestXtend.java
+++ b/tests/org.eclipse.gmf.tooling.tests.xtend/src/org/eclipse/gmf/tooling/tests/xtend/samples/LinksSampleTestXtend.java
@@ -1,13 +1,38 @@
 package org.eclipse.gmf.tooling.tests.xtend.samples;
 
-import org.eclipse.gmf.tests.samples.LinksSampleTest;
-import org.eclipse.gmf.tests.setup.RuntimeBasedGeneratorConfiguration;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator;
+import org.eclipse.gmf.tests.samples.LinksSampleTest;
+import org.eclipse.gmf.tooling.tests.xtend.setup.RuntimeBasedGeneratorConfigurationXtend;
 
 public class LinksSampleTestXtend extends LinksSampleTest {
 
 	public LinksSampleTestXtend(String name) {
-		super(name, new RuntimeBasedGeneratorConfiguration());
+		super(name, new RuntimeBasedGeneratorConfigurationXtend());
 	}
 	
+	public void testCustomExtension() throws Exception {
+		GenEditorGenerator editorGen = prepareCustomEditorGen("custom", false);
+		editorGen.getExtensions().add(createCustomExtension(editorGen));
+		genAndCompile(editorGen, getGenerationConfiguration());
+		IProject aspectsProject = ResourcesPlugin.getWorkspace().getRoot().getProject(editorGen.getPluginDirectory().split("/")[1]);
+		assertTrue(aspectsProject.exists());
+		IFile file = aspectsProject.getFile(new Path("src/custom/CustomClass.java"));
+		assertTrue(file.exists());
+		BufferedReader classToTest = new BufferedReader(new InputStreamReader(file.getContents(), file.getCharset()));
+		String pluginID = null;
+		String line;
+		while ((line = classToTest.readLine()) != null) {
+			if (line.trim().startsWith("private static String SOME_VAR = \"TEST_PLUGIN_NAME = ")) {
+				pluginID = line.trim().replaceFirst("private static String SOME_VAR = \"TEST_PLUGIN_NAME = ", "").replace("\";", "");
+			}
+		}
+		assertEquals(pluginID, editorGen.getPlugin().getName());
+	}
 }