/******************************************************************************* * Copyright (c) 2010 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.databoard.method; import static org.objectweb.asm.Opcodes.AALOAD; import static org.objectweb.asm.Opcodes.AASTORE; import static org.objectweb.asm.Opcodes.ACC_ABSTRACT; import static org.objectweb.asm.Opcodes.ACC_FINAL; import static org.objectweb.asm.Opcodes.ACC_INTERFACE; import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_STATIC; import static org.objectweb.asm.Opcodes.ACC_SUPER; import static org.objectweb.asm.Opcodes.ALOAD; import static org.objectweb.asm.Opcodes.ANEWARRAY; import static org.objectweb.asm.Opcodes.ARETURN; import static org.objectweb.asm.Opcodes.ARRAYLENGTH; import static org.objectweb.asm.Opcodes.ASTORE; import static org.objectweb.asm.Opcodes.ATHROW; import static org.objectweb.asm.Opcodes.CHECKCAST; import static org.objectweb.asm.Opcodes.DLOAD; import static org.objectweb.asm.Opcodes.DRETURN; import static org.objectweb.asm.Opcodes.DUP; import static org.objectweb.asm.Opcodes.FLOAD; import static org.objectweb.asm.Opcodes.FRETURN; import static org.objectweb.asm.Opcodes.GETFIELD; import static org.objectweb.asm.Opcodes.GETSTATIC; import static org.objectweb.asm.Opcodes.GOTO; import static org.objectweb.asm.Opcodes.ICONST_0; import static org.objectweb.asm.Opcodes.IFEQ; import static org.objectweb.asm.Opcodes.IF_ICMPLT; import static org.objectweb.asm.Opcodes.ILOAD; import static org.objectweb.asm.Opcodes.INSTANCEOF; import static org.objectweb.asm.Opcodes.INVOKEINTERFACE; import static org.objectweb.asm.Opcodes.INVOKESPECIAL; import static org.objectweb.asm.Opcodes.INVOKESTATIC; import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; import static org.objectweb.asm.Opcodes.IRETURN; import static org.objectweb.asm.Opcodes.ISTORE; import static org.objectweb.asm.Opcodes.LLOAD; import static org.objectweb.asm.Opcodes.LRETURN; import static org.objectweb.asm.Opcodes.NEW; import static org.objectweb.asm.Opcodes.POP; import static org.objectweb.asm.Opcodes.PUTFIELD; import static org.objectweb.asm.Opcodes.PUTSTATIC; import static org.objectweb.asm.Opcodes.RETURN; import static org.objectweb.asm.Opcodes.V1_6; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Comparator; import java.util.HashSet; import java.util.Set; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.simantics.databoard.Bindings; import org.simantics.databoard.Methods; import org.simantics.databoard.adapter.AdaptException; import org.simantics.databoard.adapter.Adapter; import org.simantics.databoard.adapter.AdapterConstructionException; import org.simantics.databoard.binding.error.BindingConstructionException; import org.simantics.databoard.method.MethodInterface.AsyncResult; import org.simantics.databoard.method.MethodInterface.ExecutionError; public class MethodInterfaceUtil { /** * Bind an instance a to Method Interface * * @param * @param interfaze * @param obj * @return the method interface * @throws BindingConstructionException */ public static MethodInterface bindInterface(Class interfaze, final T obj) throws BindingConstructionException { final Interface interfaceType = Methods.getInterfaceType(interfaze); MethodInterface mi = bindInterface(interfaceType, obj); /* System.out.println("Created methodinterface for "+interfaze.getName()); for (MethodTypeDefinition k : mi.getInterface().methodDefinitions) { System.out.print(k); if (k.getType().requestType.getComponentCount()>0) { System.out.print(System.identityHashCode( k.getType().requestType.getComponentType(0) ) ); } System.out.println(); } */ return mi; } /** * Bind interface type to an instance * * @param * @param interfaceType * @param obj * @return the method interface * @throws BindingConstructionException */ public static MethodInterface bindInterface(final Interface interfaceType, final T obj) throws BindingConstructionException { // Find matching Java Method for each MethodTypeDefinition int len = interfaceType.getMethodDefinitions().length; final MethodTypeDefinition[] methodDefinitions = interfaceType.getMethodDefinitions(); final MethodTypeBinding[] methodBindings = new MethodTypeBinding[ len ]; final Method[] methods = new Method[ len ]; Class clazz = obj.getClass(); Method[] classMethods = clazz.getMethods(); for (int i=0; i T createProxy(Class interfaze, MethodInterface mi) throws BindingConstructionException { StubClassLoader cl = new StubClassLoader(interfaze.getClassLoader()); Class virhe; try { virhe = cl.loadClass(interfaze.getName()+"_Stub"); Constructor c = virhe.getConstructor(MethodInterface.class); return (T) c.newInstance(mi); } catch (ClassNotFoundException e) { System.err.println("Did you remember to include org.objectweb.asm ??"); throw new BindingConstructionException(e); } catch (SecurityException e) { throw new BindingConstructionException(e); } catch (NoSuchMethodException e) { throw new BindingConstructionException(e); } catch (IllegalArgumentException e) { throw new BindingConstructionException(e); } catch (InstantiationException e) { throw new BindingConstructionException(e); } catch (IllegalAccessException e) { throw new BindingConstructionException(e); } catch (InvocationTargetException e) { throw new BindingConstructionException(e.getCause()); } } public static Comparator methodComparator = new Comparator(){ @Override public int compare(java.lang.reflect.Method o1,java.lang.reflect.Method o2){ return o1.getName().compareTo(o2.getName());}}; public static MethodInterface adaptMethods(final MethodInterface mi, final MethodTypeDefinition[] rangeMethods) { //final MethodTypeDefinition[] domainMethods = mi.getInterface().getMethodDefinitions(); throw new IllegalArgumentException("To be implemented"); /* return new MethodInterface() { @Override public org.simantics.databoard.method.MethodInterface.Method getMethod( MethodDescription rangeDescription) throws MethodNotSupportedException { MethodDescription domainDescription = null; for (int i=0; i findClass(String name) throws ClassNotFoundException { if (name.endsWith("_Stub")) { Class interfaze = loadClass(name.substring(0, name.length()-5)); ClassWriter cw = new ClassWriter(0); createImpl(name, interfaze, cw); byte[] b = cw.toByteArray(); /* new ClassReader(b).accept( new ASMifierClassVisitor(new PrintWriter(System.out)), 0 ); */ Class clazz = defineClass(name, b, 0, b.length); return clazz; } return super.findClass(name); } static String toTypeDescriptor(Class clazz) { if (clazz==void.class) return "V"; if (clazz==boolean.class) return "Z"; if (clazz==char.class) return "C"; if (clazz==byte.class) return "B"; if (clazz==short.class) return "S"; if (clazz==int.class) return "I"; if (clazz==float.class) return "F"; if (clazz==long.class) return "J"; if (clazz==double.class) return "D"; if (clazz.isArray()) return clazz.getName().replaceAll("\\.", "/"); return "L"+clazz.getName().replaceAll("\\.", "/")+";"; } void createImpl(String className, Class interfaze, ClassWriter cw) { FieldVisitor fv; MethodVisitor mv; //AnnotationVisitor av0; java.lang.reflect.Method[] methods = interfaze.getMethods(); Arrays.sort(methods, MethodInterfaceUtil.methodComparator); String classResourceName = className.replaceAll("\\.", "/"); String classTypeDescriptor = "L"+classResourceName+";"; String interfaceResourceName = classResourceName.substring(0, classResourceName.length()-5); String interfaceTypeDescriptor = "L"+interfaceResourceName+";"; cw.visit(V1_6, ACC_SUPER | ACC_PUBLIC, classResourceName, null, "java/lang/Object", new String[] { interfaceResourceName }); // Imports Set> imports = new HashSet>(); imports.add(AsyncResult.class); imports.add(ExecutionError.class); imports.add(Method.class); imports.add(interfaze); for (java.lang.reflect.Method m : methods) { for (Class clazz : m.getExceptionTypes()) { imports.add(clazz); } for (Class clazz : m.getParameterTypes()) { imports.add(clazz); } imports.add(m.getReturnType()); } for (Class clazz : imports) { if (clazz.isPrimitive()) continue; String name = clazz.getName(); if (name.startsWith("java.lang")) continue; String resourceName = name.replaceAll("\\.", "/"); String outerName = resourceName.contains("$") ? resourceName.substring(0, resourceName.indexOf('$')) : null; String className_ = clazz.isArray() ? clazz.getSimpleName().substring(0, clazz.getSimpleName().length()-2) : clazz.getSimpleName(); int access = ACC_PUBLIC + ACC_STATIC + (clazz.isInterface() ? ACC_INTERFACE + ACC_ABSTRACT : 0); // System.out.printf("name=%s, outerName=%s, innerName=%s\n", resourceName, outerName, className_); cw.visitInnerClass(resourceName, outerName, className_, access); } // Fields { fv = cw.visitField(ACC_FINAL + ACC_STATIC, "interfaze", "Ljava/lang/Class;", "Ljava/lang/Class<*>;", null); fv.visitEnd(); } { fv = cw.visitField(ACC_FINAL + ACC_STATIC, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;", null, null); fv.visitEnd(); } { fv = cw.visitField(0, "mi", "Lorg/simantics/databoard/method/MethodInterface;", null, null); fv.visitEnd(); } { fv = cw.visitField(0, "methods", "[Lorg/simantics/databoard/method/MethodInterface$Method;", null, null); fv.visitEnd(); } // Init class - static {} { mv = cw.visitMethod(ACC_STATIC, "", "()V", null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitLdcInsn(Type.getType(interfaceTypeDescriptor)); mv.visitFieldInsn(PUTSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;"); Label l1 = new Label(); mv.visitLabel(l1); mv.visitFieldInsn(GETSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethods", "()[Ljava/lang/reflect/Method;"); mv.visitVarInsn(ASTORE, 0); Label l2 = new Label(); mv.visitLabel(l2); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETSTATIC, "org/simantics/databoard/method/MethodInterfaceUtil", "methodComparator", "Ljava/util/Comparator;"); mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "sort", "([Ljava/lang/Object;Ljava/util/Comparator;)V"); Label l3 = new Label(); mv.visitLabel(l3); mv.visitVarInsn(ALOAD, 0); mv.visitInsn(ARRAYLENGTH); mv.visitTypeInsn(ANEWARRAY, "org/simantics/databoard/method/MethodTypeBinding"); mv.visitFieldInsn(PUTSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;"); Label l4 = new Label(); mv.visitLabel(l4); mv.visitInsn(ICONST_0); mv.visitVarInsn(ISTORE, 1); Label l5 = new Label(); mv.visitLabel(l5); Label l6 = new Label(); mv.visitJumpInsn(GOTO, l6); Label l7 = new Label(); mv.visitLabel(l7); mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"[Ljava/lang/reflect/Method;", Opcodes.INTEGER}, 0, null); mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;"); mv.visitVarInsn(ILOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ILOAD, 1); mv.visitInsn(AALOAD); mv.visitMethodInsn(INVOKESTATIC, "org/simantics/databoard/Methods", "getMethodTypeBinding", "(Ljava/lang/reflect/Method;)Lorg/simantics/databoard/method/MethodTypeBinding;"); mv.visitInsn(AASTORE); Label l8 = new Label(); mv.visitLabel(l8); mv.visitIincInsn(1, 1); mv.visitLabel(l6); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ILOAD, 1); mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;"); mv.visitInsn(ARRAYLENGTH); mv.visitJumpInsn(IF_ICMPLT, l7); Label l9 = new Label(); mv.visitLabel(l9); mv.visitInsn(RETURN); Label l10 = new Label(); mv.visitLabel(l10); mv.visitLocalVariable("methods", "[Ljava/lang/reflect/Method;", null, l2, l10, 0); mv.visitLocalVariable("i", "I", null, l5, l9, 1); mv.visitMaxs(4, 2); mv.visitEnd(); } // Constructor { mv = cw.visitMethod(ACC_PUBLIC, "", "(Lorg/simantics/databoard/method/MethodInterface;)V", null, new String[] { "org/simantics/databoard/method/MethodNotSupportedException" }); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V"); Label l1 = new Label(); mv.visitLabel(l1); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitFieldInsn(PUTFIELD, classResourceName, "mi", "Lorg/simantics/databoard/method/MethodInterface;"); Label l2 = new Label(); mv.visitLabel(l2); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;"); mv.visitInsn(ARRAYLENGTH); mv.visitTypeInsn(ANEWARRAY, "org/simantics/databoard/method/MethodInterface$Method"); mv.visitFieldInsn(PUTFIELD, classResourceName, "methods", "[Lorg/simantics/databoard/method/MethodInterface$Method;"); Label l3 = new Label(); mv.visitLabel(l3); mv.visitInsn(ICONST_0); mv.visitVarInsn(ISTORE, 2); Label l4 = new Label(); mv.visitLabel(l4); Label l5 = new Label(); mv.visitJumpInsn(GOTO, l5); Label l6 = new Label(); mv.visitLabel(l6); mv.visitFrame(Opcodes.F_FULL, 3, new Object[] {classResourceName, "org/simantics/databoard/method/MethodInterface", Opcodes.INTEGER}, 0, new Object[] {}); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, classResourceName, "methods", "[Lorg/simantics/databoard/method/MethodInterface$Method;"); mv.visitVarInsn(ILOAD, 2); mv.visitVarInsn(ALOAD, 1); mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;"); mv.visitVarInsn(ILOAD, 2); mv.visitInsn(AALOAD); mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/databoard/method/MethodInterface", "getMethod", "(Lorg/simantics/databoard/method/MethodTypeBinding;)Lorg/simantics/databoard/method/MethodInterface$Method;"); mv.visitInsn(AASTORE); Label l7 = new Label(); mv.visitLabel(l7); mv.visitIincInsn(2, 1); mv.visitLabel(l5); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ILOAD, 2); mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;"); mv.visitInsn(ARRAYLENGTH); mv.visitJumpInsn(IF_ICMPLT, l6); Label l8 = new Label(); mv.visitLabel(l8); mv.visitInsn(RETURN); Label l9 = new Label(); mv.visitLabel(l9); mv.visitLocalVariable("this", classTypeDescriptor, null, l0, l9, 0); mv.visitLocalVariable("mi", "Lorg/simantics/databoard/method/MethodInterface;", null, l0, l9, 1); mv.visitLocalVariable("i", "I", null, l4, l8, 2); mv.visitMaxs(5, 3); mv.visitEnd(); } // Method int methodNumber = 0; for (java.lang.reflect.Method m : methods) { String typeDescription = ""; Class[] params = m.getParameterTypes(); for (int i=0; i[] exceptions = m.getExceptionTypes(); String[] exceptionResourceNames = new String[exceptions.length]; for (int i=0; i clazz = params[i]; argRegs++; if (clazz==long.class || clazz==double.class) argRegs++; } mv = cw.visitMethod(ACC_PUBLIC, m.getName(), typeDescription, null, exceptionResourceNames); mv.visitCode(); Label l0 = new Label(); Label l1 = new Label(); Label l2 = new Label(); mv.visitTryCatchBlock(l0, l1, l2, "org/simantics/databoard/method/MethodInterface$ExecutionError"); Label l3 = new Label(); mv.visitTryCatchBlock(l0, l1, l3, "java/lang/InterruptedException"); Label l4 = new Label(); mv.visitLabel(l4); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, classResourceName, "methods", "[Lorg/simantics/databoard/method/MethodInterface$Method;"); // Method m and puts into register mv.visitLdcInsn(Integer.valueOf(methodNumber)); mv.visitInsn(AALOAD); mv.visitVarInsn(ASTORE, argRegs+1); Label l5 = new Label(); mv.visitLabel(l5); mv.visitLdcInsn(Integer.valueOf(params.length)); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); int register = 1; // argument register for (int i=0; i clazz = params[i]; mv.visitInsn(DUP); mv.visitLdcInsn(Integer.valueOf(i)); if (clazz==byte.class) { mv.visitVarInsn(ILOAD, register++); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"); } else if (clazz==char.class) { mv.visitVarInsn(ILOAD, register++); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); } else if (clazz==boolean.class) { mv.visitVarInsn(ILOAD, register++); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); } else if (clazz==byte.class) { mv.visitVarInsn(ILOAD, register++); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"); } else if (clazz==int.class) { mv.visitVarInsn(ILOAD, register++); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); } else if (clazz==long.class) { mv.visitVarInsn(LLOAD, register); register += 2; mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(F)Ljava/lang/Long;"); } else if (clazz==float.class) { mv.visitVarInsn(FLOAD, register); register += 2; mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); } else if (clazz==double.class) { mv.visitVarInsn(DLOAD, register); register += 2; mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); } else { // Push argument to stack mv.visitVarInsn(ALOAD, register++); } mv.visitInsn(AASTORE); } // Store args to argRegs+2 mv.visitVarInsn(ASTORE, argRegs+2); Label l6 = new Label(); mv.visitLabel(l6); mv.visitVarInsn(ALOAD, argRegs+1 /* m */); mv.visitVarInsn(ALOAD, argRegs+2 /*args*/); mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/databoard/method/MethodInterface$Method", "invoke", "(Ljava/lang/Object;)Lorg/simantics/databoard/method/MethodInterface$AsyncResult;"); mv.visitVarInsn(ASTORE, argRegs+3); mv.visitLabel(l0); mv.visitVarInsn(ALOAD, argRegs+3); mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/databoard/method/MethodInterface$AsyncResult", "waitForResponse", "()Ljava/lang/Object;"); // TODO Return typecase result Class returnType = m.getReturnType(); if (returnType==void.class) { mv.visitInsn(POP); mv.visitLabel(l1); mv.visitInsn(RETURN); } else if (returnType==int.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I"); mv.visitLabel(l1); mv.visitInsn(IRETURN); } else if (returnType==byte.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Byte"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "B()"); mv.visitLabel(l1); mv.visitInsn(IRETURN); } else if (returnType==char.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); mv.visitLabel(l1); mv.visitInsn(IRETURN); } else if (returnType==boolean.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z"); mv.visitLabel(l1); mv.visitInsn(IRETURN); } else if (returnType==short.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Short"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S"); mv.visitLabel(l1); mv.visitInsn(IRETURN); } else if (returnType==long.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Long"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J"); mv.visitLabel(l1); mv.visitInsn(LRETURN); } else if (returnType==double.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Double"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D"); mv.visitLabel(l1); mv.visitInsn(DRETURN); } else if (returnType==float.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Float"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F"); mv.visitLabel(l1); mv.visitInsn(FRETURN); } else { // Object mv.visitTypeInsn(CHECKCAST, returnType.getName().replaceAll("\\.", "/")); mv.visitLabel(l1); mv.visitInsn(ARETURN); } // Handle exceptions mv.visitLabel(l2); mv.visitFrame(Opcodes.F_FULL, 5, new Object[] {classResourceName, "java/lang/Integer", "org/simantics/databoard/method/MethodInterface$Method", "[Ljava/lang/Object;", "org/simantics/databoard/method/MethodInterface$AsyncResult"}, 1, new Object[] {"org/simantics/databoard/method/MethodInterface$ExecutionError"}); mv.visitVarInsn(ASTORE, argRegs+4); Label l7 = new Label(); mv.visitLabel(l7); mv.visitVarInsn(ALOAD, argRegs+4); mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/method/MethodInterface$ExecutionError", "getError", "()Ljava/lang/Object;"); mv.visitVarInsn(ASTORE, argRegs+5); // argRegs+5 <- ExecutionError.cause Class[] exceptionClasses = m.getExceptionTypes(); Label nextException[] = new Label[exceptionClasses.length]; for (int i=0; i exceptionClass = exceptionClasses[i]; String exceptionClassResourceName = exceptionClass.getName().replaceAll("\\.", "/"); nextException[i] = new Label(); // If instanceof MyException Label l8 = new Label(); mv.visitLabel(l8); mv.visitVarInsn(ALOAD, argRegs+5); // Cause mv.visitTypeInsn(INSTANCEOF, exceptionClassResourceName); mv.visitJumpInsn(IFEQ, nextException[i]); // If not, go to ExecutionError // If so, throw it mv.visitVarInsn(ALOAD, argRegs+5); // e mv.visitTypeInsn(CHECKCAST, exceptionClassResourceName); mv.visitInsn(ATHROW); mv.visitLabel(nextException[i]); } // ExecutionError mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"org/simantics/databoard/method/MethodInterface$ExecutionError", "java/lang/Object"}, 0, null); mv.visitTypeInsn(NEW, "java/lang/RuntimeException"); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, argRegs+4); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "", "(Ljava/lang/Throwable;)V"); mv.visitInsn(ATHROW); // InteruptedException mv.visitLabel(l3); mv.visitFrame(Opcodes.F_FULL, 5, new Object[] {classResourceName, "java/lang/Integer", "org/simantics/databoard/method/MethodInterface$Method", "[Ljava/lang/Object;", "org/simantics/databoard/method/MethodInterface$AsyncResult"}, 1, new Object[] {"java/lang/InterruptedException"}); mv.visitVarInsn(ASTORE, argRegs+4); Label l10 = new Label(); mv.visitLabel(l10); mv.visitTypeInsn(NEW, "java/lang/RuntimeException"); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, argRegs+4); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "", "(Ljava/lang/Throwable;)V"); mv.visitInsn(ATHROW); Label l11 = new Label(); mv.visitLabel(l11); mv.visitLocalVariable("this", classTypeDescriptor, null, l4, l11, 0); // mv.visitLocalVariable("arg1", "Ljava/lang/Integer;", null, l4, l11, 1); register = 1; for (int i=0; i clazz = params[i]; mv.visitLocalVariable("arg"+(i+1), toTypeDescriptor(clazz), null, l4, l11, register); register++; if (clazz==long.class || clazz==double.class) argRegs++; } mv.visitLocalVariable("m", "Lorg/simantics/databoard/method/MethodInterface$Method;", null, l5, l11, argRegs+1); mv.visitLocalVariable("args", "[Ljava/lang/Object;", null, l6, l11, argRegs+2); mv.visitLocalVariable("result", "Lorg/simantics/databoard/method/MethodInterface$AsyncResult;", null, l0, l11, argRegs+3); mv.visitLocalVariable("e", "Lorg/simantics/databoard/method/MethodInterface$ExecutionError;", null, l7, l3, argRegs+4); mv.visitLocalVariable("cause", "Ljava/lang/Object;", null, l7, l3, argRegs+5); mv.visitLocalVariable("e", "Ljava/lang/InterruptedException;", null, l10, l11, argRegs+4); mv.visitMaxs(argRegs+3, argRegs+6); mv.visitEnd(); methodNumber++; } cw.visitEnd(); } } }