Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/jit/ByteCodeSwitch.java61
-rw-r--r--plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/EMFTVMUtil.java67
-rw-r--r--tests/org.eclipse.m2m.atl.emftvm.tests/launch/Bug461445.launch19
-rw-r--r--tests/org.eclipse.m2m.atl.emftvm.tests/launch/EmftvmAllTests.launch2
-rw-r--r--tests/org.eclipse.m2m.atl.emftvm.tests/src/org/eclipse/m2m/atl/emftvm/tests/integration/IntegrationTest.java49
-rw-r--r--tests/org.eclipse.m2m.atl.emftvm.tests/test-data/Regression/Bug461445.atl4
-rw-r--r--tests/org.eclipse.m2m.atl.emftvm.tests/test-data/Regression/Bug461445.emftvmbin0 -> 888 bytes
7 files changed, 139 insertions, 63 deletions
diff --git a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/jit/ByteCodeSwitch.java b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/jit/ByteCodeSwitch.java
index 1ad77166..ce4f2b3d 100644
--- a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/jit/ByteCodeSwitch.java
+++ b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/jit/ByteCodeSwitch.java
@@ -11,13 +11,11 @@
package org.eclipse.m2m.atl.emftvm.jit;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -664,7 +662,7 @@ public class ByteCodeSwitch extends EmftvmSwitch<MethodVisitor> implements Opcod
localVariable("body", CodeBlock.class, bodyStart, ifOpNull, bodyIdx);
}
// Generate native method invocation code here
- final Method method = findRootMethod(object.getNativeMethod());
+ final Method method = EMFTVMUtil.findRootMethod(object.getNativeMethod());
if (method != null) { // native method recorded - try first
// Labels
final Label subframeStart = new Label();
@@ -849,7 +847,7 @@ public class ByteCodeSwitch extends EmftvmSwitch<MethodVisitor> implements Opcod
localVariable("body", CodeBlock.class, bodyStart, ifOpNull, bodyIdx);
}
// Generate native method invocation code here
- final Method method = findRootMethod(object.getNativeMethod());
+ final Method method = EMFTVMUtil.findRootMethod(object.getNativeMethod());
if (method != null) { // native method recorded - try first
// Labels
final Label subframeStart = new Label();
@@ -1085,61 +1083,6 @@ public class ByteCodeSwitch extends EmftvmSwitch<MethodVisitor> implements Opcod
}
/**
- * Finds the root {@link Class} in which <code>method</code> was declared.
- * @param method the method for which to find the root {@link Class}
- * @return the root {@link Class} in which <code>method</code> was declared
- */
- private Method findRootMethod(Method method) {
- if (method == null) {
- return null;
- }
- final int methodModifiers = getRelevantModifiers(method);
- Class<?> dc = method.getDeclaringClass();
- java.util.Set<Class<?>> dis = new LinkedHashSet<Class<?>>(
- Arrays.asList(dc.getInterfaces()));
- while ((dc = dc.getSuperclass()) != null) {
- try {
- Method superMethod = dc.getDeclaredMethod(method.getName(), method.getParameterTypes());
- if (getRelevantModifiers(superMethod) == methodModifiers) {
- method = superMethod;
- } else {
- break;
- }
- } catch (SecurityException e) {
- } catch (NoSuchMethodException e) {
- }
- dis.addAll(Arrays.asList(dc.getInterfaces()));
- }
- while (!dis.isEmpty()) {
- java.util.Set<Class<?>> newDis = new LinkedHashSet<Class<?>>();
- for (Class<?> di : dis) {
- try {
- // Only replace by method declared in a super-interface
- if (di.isAssignableFrom(method.getDeclaringClass())) {
- method = di.getDeclaredMethod(method.getName(), method.getParameterTypes());
- }
- } catch (SecurityException e) {
- } catch (NoSuchMethodException e) {
- }
- newDis.addAll(Arrays.asList(di.getInterfaces()));
- }
- newDis.removeAll(dis);
- dis = newDis;
- }
- return method;
- }
-
- /**
- * Returns the relevant modifiers (visibility and static) for the given method.
- * @param method the method for which to return the modifiers
- * @return the relevant modifiers (visibility and static) for the given method
- */
- private int getRelevantModifiers(final Method method) {
- final int methodModifiers = method.getModifiers();
- return methodModifiers & (Modifier.PRIVATE + Modifier.PROTECTED + Modifier.PUBLIC + Modifier.STATIC);
- }
-
- /**
* {@inheritDoc}
*/
@Override
diff --git a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/EMFTVMUtil.java b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/EMFTVMUtil.java
index d7a9164e..8365df2d 100644
--- a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/EMFTVMUtil.java
+++ b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/EMFTVMUtil.java
@@ -1109,7 +1109,9 @@ public final class EMFTVMUtil {
* the method arguments
* @return the method result
*/
- public static Object invokeNative(final StackFrame frame, final Object self, final Method method, final Object[] args) {
+ public static Object invokeNative(final StackFrame frame, final Object self, Method method, final Object[] args) {
+ // Fix for Bug # 461445: EMFTVM cannot invoke Java methods on instances of private classes:
+ method = findRootMethod(method);
final StackFrame subFrame = frame.prepareNativeArgs(method, self, args);
try {
return emf2vm(frame.getEnv(), self instanceof EObject ? (EObject) self : null, method.invoke(self, args));
@@ -1163,7 +1165,9 @@ public final class EMFTVMUtil {
* the method argument
* @return the method result
*/
- public static Object invokeNative(final StackFrame frame, final Object self, final Method method, Object arg) {
+ public static Object invokeNative(final StackFrame frame, final Object self, Method method, Object arg) {
+ // Fix for Bug # 461445: EMFTVM cannot invoke Java methods on instances of private classes:
+ method = findRootMethod(method);
StackFrame subFrame = frame.prepareNativeContext(method, self);
if (arg instanceof CodeBlock) {
if (subFrame == null) {
@@ -1220,7 +1224,9 @@ public final class EMFTVMUtil {
* the method
* @return the method result
*/
- public static Object invokeNative(final StackFrame frame, final Object self, final Method method) {
+ public static Object invokeNative(final StackFrame frame, final Object self, Method method) {
+ // Fix for Bug # 461445: EMFTVM cannot invoke Java methods on instances of private classes:
+ method = findRootMethod(method);
final StackFrame subFrame = frame.prepareNativeContext(method, self);
try {
return emf2vm(frame.getEnv(), self instanceof EObject ? (EObject) self : null, method.invoke(self));
@@ -2425,4 +2431,59 @@ public final class EMFTVMUtil {
}
}
+ /**
+ * Finds the root {@link Class} declaration for the given <code>method</code>.
+ * @param method the method for which to find the root declaration
+ * @return the root {@link Method}
+ */
+ public static Method findRootMethod(Method method) {
+ if (method == null) {
+ return null;
+ }
+ final int methodModifiers = getRelevantModifiers(method);
+ Class<?> dc = method.getDeclaringClass();
+ java.util.Set<Class<?>> dis = new LinkedHashSet<Class<?>>(
+ Arrays.asList(dc.getInterfaces()));
+ while ((dc = dc.getSuperclass()) != null) {
+ try {
+ Method superMethod = dc.getDeclaredMethod(method.getName(), method.getParameterTypes());
+ if (getRelevantModifiers(superMethod) == methodModifiers) {
+ method = superMethod;
+ } else {
+ break;
+ }
+ } catch (SecurityException e) {
+ } catch (NoSuchMethodException e) {
+ }
+ dis.addAll(Arrays.asList(dc.getInterfaces()));
+ }
+ while (!dis.isEmpty()) {
+ java.util.Set<Class<?>> newDis = new LinkedHashSet<Class<?>>();
+ for (Class<?> di : dis) {
+ try {
+ // Only replace by method declared in a super-interface
+ if (di.isAssignableFrom(method.getDeclaringClass())) {
+ method = di.getDeclaredMethod(method.getName(), method.getParameterTypes());
+ }
+ } catch (SecurityException e) {
+ } catch (NoSuchMethodException e) {
+ }
+ newDis.addAll(Arrays.asList(di.getInterfaces()));
+ }
+ newDis.removeAll(dis);
+ dis = newDis;
+ }
+ return method;
+ }
+
+ /**
+ * Returns the relevant modifiers (visibility and static) for the given method.
+ * @param method the method for which to return the modifiers
+ * @return the relevant modifiers (visibility and static) for the given method
+ */
+ private static int getRelevantModifiers(final Method method) {
+ final int methodModifiers = method.getModifiers();
+ return methodModifiers & (Modifier.PRIVATE + Modifier.PROTECTED + Modifier.PUBLIC + Modifier.STATIC);
+ }
+
}
diff --git a/tests/org.eclipse.m2m.atl.emftvm.tests/launch/Bug461445.launch b/tests/org.eclipse.m2m.atl.emftvm.tests/launch/Bug461445.launch
new file mode 100644
index 00000000..6b308e80
--- /dev/null
+++ b/tests/org.eclipse.m2m.atl.emftvm.tests/launch/Bug461445.launch
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.m2m.atl.emftvm.launcher.EMFTVMTransformation">
+<stringAttribute key="ATL File Name" value="//org.eclipse.m2m.atl.emftvm.tests/test-data/Regression/Bug461445.atl"/>
+<booleanAttribute key="Disable JIT compiler" value="false"/>
+<booleanAttribute key="Display Profiling Data" value="false"/>
+<booleanAttribute key="Display Timing Data" value="true"/>
+<mapAttribute key="Inout Model Options"/>
+<mapAttribute key="Inout Models"/>
+<mapAttribute key="Inout Models Output Locations"/>
+<mapAttribute key="Input Model Options"/>
+<mapAttribute key="Input Models"/>
+<mapAttribute key="Metamodel Options"/>
+<mapAttribute key="Metamodels"/>
+<stringAttribute key="Module Name" value="Regression::Bug461445"/>
+<stringAttribute key="Module Path" value="/org.eclipse.m2m.atl.emftvm.tests/test-data/"/>
+<mapAttribute key="Output Model Options"/>
+<mapAttribute key="Output Models"/>
+<listAttribute key="Superimpose"/>
+</launchConfiguration>
diff --git a/tests/org.eclipse.m2m.atl.emftvm.tests/launch/EmftvmAllTests.launch b/tests/org.eclipse.m2m.atl.emftvm.tests/launch/EmftvmAllTests.launch
index 836b1d6e..48a62148 100644
--- a/tests/org.eclipse.m2m.atl.emftvm.tests/launch/EmftvmAllTests.launch
+++ b/tests/org.eclipse.m2m.atl.emftvm.tests/launch/EmftvmAllTests.launch
@@ -24,7 +24,7 @@
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/java-1.7.0-openjdk-1.7.0.71-2.5.3.0.fc19.x86_64"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.m2m.atl.emftvm.tests.EmftvmAllTests"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.m2m.atl.emftvm.tests"/>
diff --git a/tests/org.eclipse.m2m.atl.emftvm.tests/src/org/eclipse/m2m/atl/emftvm/tests/integration/IntegrationTest.java b/tests/org.eclipse.m2m.atl.emftvm.tests/src/org/eclipse/m2m/atl/emftvm/tests/integration/IntegrationTest.java
index 537d20ac..ab79a88d 100644
--- a/tests/org.eclipse.m2m.atl.emftvm.tests/src/org/eclipse/m2m/atl/emftvm/tests/integration/IntegrationTest.java
+++ b/tests/org.eclipse.m2m.atl.emftvm.tests/src/org/eclipse/m2m/atl/emftvm/tests/integration/IntegrationTest.java
@@ -11,14 +11,24 @@
*******************************************************************************/
package org.eclipse.m2m.atl.emftvm.tests.integration;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
+import java.util.Collections;
import java.util.logging.Level;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.m2m.atl.common.ATLLogger;
+import org.eclipse.m2m.atl.core.ATLCoreException;
+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.emftvm.EmftvmFactory;
import org.eclipse.m2m.atl.emftvm.EmftvmPackage;
import org.eclipse.m2m.atl.emftvm.ExecEnv;
@@ -28,6 +38,7 @@ import org.eclipse.m2m.atl.emftvm.tests.EMFTVMTest;
import org.eclipse.m2m.atl.emftvm.trace.TracePackage;
import org.eclipse.m2m.atl.emftvm.util.LazyList;
import org.eclipse.m2m.atl.emftvm.util.TimingData;
+import org.eclipse.m2m.atl.engine.parser.AtlParser;
/**
* @author <a href="dwagelaar@gmail.com">Dennis Wagelaar</a>
@@ -360,6 +371,44 @@ public class IntegrationTest extends EMFTVMTest {
}
/**
+ * Tests regression of <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=461445">Bug # 461445</a>.
+ */
+ public void testBug461445() {
+ final ExecEnv env = EmftvmFactory.eINSTANCE.createExecEnv();
+ final TimingData td = new TimingData();
+ env.loadModule(createTestModuleResolver(), "Regression::Bug461445");
+ td.finishLoading();
+ final Object result = env.run(td);
+ td.finish();
+
+ assertEquals("value", result);
+ }
+
+ public void testATLAPI() throws ATLCoreException, IOException {
+
+ ModelFactory mf = AtlParser.getDefault().getModelFactory();
+ IReferenceModel atlMM = AtlParser.getDefault().getAtlMetamodel();
+ IModel atlM = mf.newModel(atlMM);
+
+ EObject module = (EObject) atlM.newElement(atlMM.getMetaElementByName("Module"));
+ module.eSet(module.eClass().getEStructuralFeature("name"), "testmodule");
+ EObject rule = (EObject) atlM.newElement(atlMM.getMetaElementByName("MatchedRule"));
+ rule.eSet(rule.eClass().getEStructuralFeature("name"), "Test");
+ EList<EObject> moduleElements = (EList<EObject>) module.eGet(module.eClass().getEStructuralFeature("elements"));
+ moduleElements.add(rule);
+
+ FileOutputStream fos = new FileOutputStream("testmodule.atl");
+ try {
+ AtlParser.getDefault().extract(atlM, fos, Collections.emptyMap());
+ } finally {
+ if (fos != null) {
+ fos.close();
+ }
+ }
+
+ }
+
+ /**
* Tests "ToStringTest.atl".
*/
public void testToString() {
diff --git a/tests/org.eclipse.m2m.atl.emftvm.tests/test-data/Regression/Bug461445.atl b/tests/org.eclipse.m2m.atl.emftvm.tests/test-data/Regression/Bug461445.atl
new file mode 100644
index 00000000..6fb9e980
--- /dev/null
+++ b/tests/org.eclipse.m2m.atl.emftvm.tests/test-data/Regression/Bug461445.atl
@@ -0,0 +1,4 @@
+-- @atlcompiler emftvm
+query "Regression::Bug461445" = "#native"!"java::util::Collections"
+ .refInvokeStaticOperation('unmodifiableMap', Sequence{Map{('key', 'value')}})
+ .get('key').debug('Bug');
diff --git a/tests/org.eclipse.m2m.atl.emftvm.tests/test-data/Regression/Bug461445.emftvm b/tests/org.eclipse.m2m.atl.emftvm.tests/test-data/Regression/Bug461445.emftvm
new file mode 100644
index 00000000..88f4dc95
--- /dev/null
+++ b/tests/org.eclipse.m2m.atl.emftvm.tests/test-data/Regression/Bug461445.emftvm
Binary files differ

Back to the top