]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/testcases/org/simantics/databoard/tests/testASM.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / testcases / org / simantics / databoard / tests / testASM.java
1 /*******************************************************************************
2  *  Copyright (c) 2010 Association for Decentralized Information Management in
3  *  Industry THTH ry.
4  *  All rights reserved. This program and the accompanying materials
5  *  are made available under the terms of the Eclipse Public License v1.0
6  *  which accompanies this distribution, and is available at
7  *  http://www.eclipse.org/legal/epl-v10.html
8  *
9  *  Contributors:
10  *      VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.tests;
13
14 import static org.objectweb.asm.Opcodes.AALOAD;
15 import static org.objectweb.asm.Opcodes.AASTORE;
16 import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
17 import static org.objectweb.asm.Opcodes.ACC_FINAL;
18 import static org.objectweb.asm.Opcodes.ACC_INTERFACE;
19 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
20 import static org.objectweb.asm.Opcodes.ACC_STATIC;
21 import static org.objectweb.asm.Opcodes.ACC_SUPER;
22 import static org.objectweb.asm.Opcodes.ALOAD;
23 import static org.objectweb.asm.Opcodes.ANEWARRAY;
24 import static org.objectweb.asm.Opcodes.ARETURN;
25 import static org.objectweb.asm.Opcodes.ARRAYLENGTH;
26 import static org.objectweb.asm.Opcodes.ASTORE;
27 import static org.objectweb.asm.Opcodes.ATHROW;
28 import static org.objectweb.asm.Opcodes.CHECKCAST;
29 import static org.objectweb.asm.Opcodes.DLOAD;
30 import static org.objectweb.asm.Opcodes.DRETURN;
31 import static org.objectweb.asm.Opcodes.DUP;
32 import static org.objectweb.asm.Opcodes.FLOAD;
33 import static org.objectweb.asm.Opcodes.FRETURN;
34 import static org.objectweb.asm.Opcodes.GETFIELD;
35 import static org.objectweb.asm.Opcodes.GETSTATIC;
36 import static org.objectweb.asm.Opcodes.GOTO;
37 import static org.objectweb.asm.Opcodes.ICONST_0;
38 import static org.objectweb.asm.Opcodes.IFEQ;
39 import static org.objectweb.asm.Opcodes.IF_ICMPLT;
40 import static org.objectweb.asm.Opcodes.ILOAD;
41 import static org.objectweb.asm.Opcodes.INSTANCEOF;
42 import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
43 import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
44 import static org.objectweb.asm.Opcodes.INVOKESTATIC;
45 import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
46 import static org.objectweb.asm.Opcodes.IRETURN;
47 import static org.objectweb.asm.Opcodes.ISTORE;
48 import static org.objectweb.asm.Opcodes.LLOAD;
49 import static org.objectweb.asm.Opcodes.LRETURN;
50 import static org.objectweb.asm.Opcodes.NEW;
51 import static org.objectweb.asm.Opcodes.POP;
52 import static org.objectweb.asm.Opcodes.PUTFIELD;
53 import static org.objectweb.asm.Opcodes.PUTSTATIC;
54 import static org.objectweb.asm.Opcodes.RETURN;
55 import static org.objectweb.asm.Opcodes.V1_6;
56
57 import java.lang.reflect.Constructor;
58 import java.util.Arrays;
59 import java.util.HashSet;
60 import java.util.Set;
61
62 import org.objectweb.asm.AnnotationVisitor;
63 import org.objectweb.asm.ClassWriter;
64 import org.objectweb.asm.FieldVisitor;
65 import org.objectweb.asm.Label;
66 import org.objectweb.asm.MethodVisitor;
67 import org.objectweb.asm.Opcodes;
68 import org.objectweb.asm.Type;
69 import org.simantics.databoard.Methods;
70 import org.simantics.databoard.binding.error.BindingConstructionException;
71 import org.simantics.databoard.method.InvokeException;
72 import org.simantics.databoard.method.MethodInterface;
73 import org.simantics.databoard.method.MethodInterface.AsyncResult;
74 import org.simantics.databoard.method.MethodInterface.ExecutionError;
75 import org.simantics.databoard.method.MethodInterface.Method;
76 import org.simantics.databoard.method.MethodInterfaceUtil;
77 import org.simantics.databoard.method.MethodNotSupportedException;
78 import org.simantics.databoard.method.MethodTypeBinding;
79 import org.simantics.databoard.method.RuntimeInvokeException;
80
81 public class testASM {
82
83         public interface Abu {
84                 
85                 Integer x(Integer i) throws testASM.MyException, testASM.RandomException, InvokeException;
86                 double y();
87                 String hello(int[] args) throws testASM.MyException, InvokeException;
88                 
89         }       
90         
91         public interface Rajapinta {
92                 
93                 void m0();
94                 int m1();
95                 int m2(int arg0);
96                 int m3(int arg0, int arg1);
97                 Integer m10(int color, String name) throws InvokeException, ExecutionError;
98                 int m11(int color, String name) throws InvokeException, ExecutionError;
99         }
100         
101         static class Toteutus implements Rajapinta {
102                 Method _10, _11;
103                 
104                 public Integer m10(int color, String name)
105                 throws InvokeException, ExecutionError
106                 {                       
107                         AsyncResult result = _10.invoke(new Object[] {color, name});
108                         try {
109                                 return (Integer) result.waitForResponse();
110                         } catch (InterruptedException e) {
111                                 throw new RuntimeException(e);
112                         }
113                 }
114                 
115                 public int m11(int color, String name)
116                 throws InvokeException, ExecutionError
117                 {
118                         AsyncResult result = _11.invoke(new Object[] {color, name});
119                         try {
120                                 return (Integer) result.waitForResponse();
121                         } catch (InterruptedException e) {
122                                 throw new RuntimeException(e);
123                         }
124                 }
125
126                 @Override
127                 public void m0() {
128                         // TODO Auto-generated method stub
129                         
130                 }
131
132                 @Override
133                 public int m1() {
134                         // TODO Auto-generated method stub
135                         return 666;
136                 }
137
138                 @Override
139                 public int m2(int arg0) {
140                         // TODO Auto-generated method stub
141                         return 0;
142                 }
143
144                 @Override
145                 public int m3(int arg0, int arg1) {
146                         // TODO Auto-generated method stub
147                         return 0;
148                 }
149                 
150                 
151         }
152
153         
154         public static byte[] dump () throws Exception {
155                 ClassWriter cw = new ClassWriter(0);
156                 FieldVisitor fv;
157                 MethodVisitor mv;
158                 AnnotationVisitor av0;
159
160                 cw.visit(V1_6, ACC_SUPER, "org/simantics/data/Virhe", null, "java/lang/Object", null);
161
162                 cw.visitSource("testASM.java", null);
163
164                 {
165                 mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
166                 mv.visitCode();
167                 Label l0 = new Label();
168                 mv.visitLabel(l0);
169                 mv.visitLineNumber(157, l0);
170                 mv.visitVarInsn(ALOAD, 0);
171                 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
172                 mv.visitInsn(RETURN);
173                 Label l1 = new Label();
174                 mv.visitLabel(l1);
175                 mv.visitLocalVariable("this", "Lorg/simantics/data/Virhe;", null, l0, l1, 0);
176                 mv.visitMaxs(1, 1);
177                 mv.visitEnd();
178                 }
179                 cw.visitEnd();
180
181                 return cw.toByteArray();
182         }
183         
184         public static class MyException extends Exception {
185                 String msg;
186                 public MyException(String msg) {
187                         this.msg = msg;
188                 }
189         }
190         public static class RandomException extends Exception {
191                 String msg;
192                 public RandomException(String msg) {
193                         this.msg = msg;
194                 }
195         }       
196         
197         public static void main(String[] args) throws Exception {
198                 System.out.println(Object[][].class.getName());
199                 
200                 System.out.println(Abu.class.getName());
201                 System.out.println(void.class.getName());
202                 System.out.println(int.class.getName());
203                 
204                 try {
205                         Toteutus t = new Toteutus();
206
207                         Virhe3 server = new Virhe3();
208                         MethodInterface serverMi = MethodInterfaceUtil.bindInterface(Abu.class, server);
209                 
210                         StubClassLoader cl = new StubClassLoader();
211                         Class<?> virhe = cl.loadClass("org.simantics.data.testASM$Abu_Stub");
212 //                      Class<?> virhe = cl.loadClass("org.simantics.data.Virhe2");
213
214                         Constructor<?> c = virhe.getConstructor(MethodInterface.class);
215                         Abu client = (Abu) c.newInstance(serverMi);
216 //                      client = new Virhe2(serverMi);
217                 
218                         System.out.println(client);
219                         System.out.println(client.hello(new int[] {0,5,0}));
220                         System.out.println(client.y());
221                         System.out.println(client.x(5));
222                 } catch (testASM.MyException e) { 
223                         System.err.printf("MyException = %s", e.msg);
224                 }
225                 
226         }
227         
228 }
229
230
231 class Virhe3 implements testASM.Abu {
232         @Override
233         public Integer x(Integer i) throws testASM.MyException, testASM.RandomException, InvokeException {
234 //                      throw new testASM.MyException("XYZ");
235                         throw new testASM.RandomException("XYZ");
236 //              return 7;
237         }
238         @Override
239         public double y() {
240                 return 5;
241         }
242         @Override
243         public String hello(int[] args) throws testASM.MyException, InvokeException {
244                 return "World "+ Arrays.toString(args);
245         }
246         
247 }
248
249 class Virhe2 implements testASM.Abu {
250 //      static final MethodBinding x = new MethodBinding("x", DataTypes.getBinding(int.class), DataTypes.getBinding(void.class), DataTypes.getErrorBinding());
251         static final Class<?> interfaze = testASM.Abu.class;
252         static final MethodTypeBinding[] bindings;
253         
254         static {
255                 java.lang.reflect.Method[] methods = interfaze.getMethods();
256                 Arrays.sort(methods, MethodInterfaceUtil.methodComparator);
257                 
258                 bindings = new MethodTypeBinding[methods.length];
259                 for (int i=0; i<bindings.length; i++) {
260                         try {
261                                 bindings[i] = Methods.getMethodTypeBinding(methods[i]);
262                         } catch (BindingConstructionException e) {
263                                 throw new RuntimeException(e);
264                         }
265                 }
266         }
267         
268         MethodInterface mi;
269         Method[] methods;
270         public Virhe2(MethodInterface mi) 
271         throws MethodNotSupportedException 
272         {
273                 this.mi = mi;
274                 methods = new Method[bindings.length];          
275                 for (int i=0; i<bindings.length; i++) {
276                         methods[i] = mi.getMethod(bindings[i]);
277                 }               
278         }
279         
280         public Integer x(Integer arg1) throws InvokeException, testASM.MyException {
281                 Method m = methods[1];
282                 
283                 Object args[] = new Object[] {arg1};
284                 
285                 AsyncResult result = m.invoke(args);
286                 try {
287                         return (Integer) result.waitForResponse();
288                 } catch (ExecutionError e) {
289                         Object cause = e.getError();
290                         if (cause instanceof testASM.MyException) 
291                                 throw (testASM.MyException) cause;
292                         throw new RuntimeException(e);
293                 } catch (InterruptedException e) {
294                         throw new RuntimeException(e);
295                 }
296         }
297         public double y() {
298                 Method m = methods[2];
299                 
300                 Object args[] = new Object[] {};
301                 
302                 AsyncResult result = m.invoke(args);
303                 try {
304                         return (Double) result.waitForResponse();
305                 } catch (InvokeException e) {
306                         throw new RuntimeInvokeException(e);
307                 } catch (ExecutionError e) {
308                         Object cause = e.getError();
309                         throw new RuntimeException(e);
310                 } catch (InterruptedException e) {
311                         throw new RuntimeException(e);
312                 }               
313         }
314
315         @Override
316         public String hello(int[] args) throws testASM.MyException, InvokeException {
317                 return null;
318         }
319 }
320
321 class StubClassLoader extends ClassLoader {
322         
323         public StubClassLoader() {
324                 super();
325         }
326
327         public StubClassLoader(ClassLoader parent) {
328                 super(parent);
329         }
330
331         @Override
332         protected Class<?> findClass(String name) throws ClassNotFoundException {
333                 if (name.endsWith("_Stub")) {
334                         Class<?> interfaze = loadClass(name.substring(0, name.length()-5));
335                         ClassWriter cw = new ClassWriter(0);
336                         createImpl(name, interfaze, cw);
337                         byte[] b = cw.toByteArray();
338                         Class<?> clazz = defineClass(name, b, 0, b.length);
339                         return clazz;
340                 }
341                 return super.findClass(name);
342         }
343
344         static String classToTypeDescriptor(Class<?> clazz) {
345                 if (clazz==void.class) return "V";
346                 if (clazz==boolean.class) return "Z";
347                 if (clazz==char.class) return "C";
348                 if (clazz==byte.class) return "B";
349                 if (clazz==short.class) return "S";
350                 if (clazz==int.class) return "I";
351                 if (clazz==float.class) return "F";
352                 if (clazz==long.class) return "J";
353                 if (clazz==double.class) return "D";
354                 if (clazz==void.class) return "V";
355                 if (clazz.isArray()) return clazz.getName();            
356                 return "L"+clazz.getName().replaceAll("\\.", "/")+";";
357         }
358         
359         void createImpl(String className, Class<?> interfaze, ClassWriter cw) {
360                 FieldVisitor fv;
361                 MethodVisitor mv;
362                 AnnotationVisitor av0;
363                 
364                 java.lang.reflect.Method[] methods = interfaze.getMethods();
365                 Arrays.sort(methods, MethodInterfaceUtil.methodComparator);
366
367                 String classResourceName = className.replaceAll("\\.", "/");
368                 String classTypeDescriptor = "L"+classResourceName+";";
369                 String interfaceResourceName = classResourceName.substring(0, classResourceName.length()-5);
370                 String interfaceTypeDescriptor = "L"+interfaceResourceName+";";
371                 
372                 cw.visit(V1_6, ACC_SUPER | ACC_PUBLIC, classResourceName, null, "java/lang/Object", new String[] { interfaceResourceName });
373
374                 // Imports
375                 Set<Class<?>> imports = new HashSet<Class<?>>();
376                 imports.add(AsyncResult.class);
377                 imports.add(ExecutionError.class);
378                 imports.add(Method.class);
379                 imports.add(interfaze);
380                 
381                 for (java.lang.reflect.Method m : methods) {
382                         for (Class<?> clazz : m.getExceptionTypes()) {
383                                 imports.add(clazz);
384                         }
385                         for (Class<?> clazz : m.getParameterTypes()) {
386                                 imports.add(clazz);                             
387                         }
388                         imports.add(m.getReturnType());                 
389                 }
390                 
391                 for (Class<?> clazz : imports) {
392                         if (clazz.isPrimitive()) continue;
393                         String name = clazz.getName();
394                         if (name.startsWith("java.lang")) continue;
395                         String resourceName = name.replaceAll("\\.", "/");
396                         String outerName = resourceName.contains("$") ? resourceName.substring(0, resourceName.indexOf('$')) : null;
397                         String className_ = clazz.isArray() ? clazz.getSimpleName().substring(0, clazz.getSimpleName().length()-2) : clazz.getSimpleName();
398                         int access = ACC_PUBLIC + ACC_STATIC + (clazz.isInterface() ? ACC_INTERFACE + ACC_ABSTRACT : 0);
399 //                      System.out.printf("name=%s, outerName=%s, innerName=%s\n", resourceName, outerName, className_);
400                         cw.visitInnerClass(resourceName, outerName, className_, access);                        
401                 }
402                 
403                 // Fields
404                 {
405                 fv = cw.visitField(ACC_FINAL + ACC_STATIC, "interfaze", "Ljava/lang/Class;", "Ljava/lang/Class<*>;", null);
406                 fv.visitEnd();
407                 }
408                 {
409                 fv = cw.visitField(ACC_FINAL + ACC_STATIC, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;", null, null);
410                 fv.visitEnd();
411                 }
412                 {
413                 fv = cw.visitField(0, "mi", "Lorg/simantics/data/session/MethodInterface;", null, null);
414                 fv.visitEnd();
415                 }
416                 {
417                 fv = cw.visitField(0, "methods", "[Lorg/simantics/data/session/MethodInterface$Method;", null, null);
418                 fv.visitEnd();
419                 }
420                 
421                 // Init class - static {}
422                 {
423                 mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
424                 mv.visitCode();
425                 Label l0 = new Label();
426                 mv.visitLabel(l0);
427                 mv.visitLdcInsn(Type.getType(interfaceTypeDescriptor));
428                 mv.visitFieldInsn(PUTSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;");
429                 Label l1 = new Label();
430                 mv.visitLabel(l1);
431                 mv.visitFieldInsn(GETSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;");
432                 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethods", "()[Ljava/lang/reflect/Method;");
433                 mv.visitVarInsn(ASTORE, 0);
434                 Label l2 = new Label();
435                 mv.visitLabel(l2);
436                 mv.visitVarInsn(ALOAD, 0);
437                 mv.visitFieldInsn(GETSTATIC, "org/simantics/data/network/MethodInterfaceUtil", "methodComparator", "Ljava/util/Comparator;");
438                 mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "sort", "([Ljava/lang/Object;Ljava/util/Comparator;)V");
439                 Label l3 = new Label();
440                 mv.visitLabel(l3);
441                 mv.visitVarInsn(ALOAD, 0);
442                 mv.visitInsn(ARRAYLENGTH);
443                 mv.visitTypeInsn(ANEWARRAY, "org/simantics/databoard/method/MethodBinding");
444                 mv.visitFieldInsn(PUTSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;");
445                 Label l4 = new Label();
446                 mv.visitLabel(l4);
447                 mv.visitInsn(ICONST_0);
448                 mv.visitVarInsn(ISTORE, 1);
449                 Label l5 = new Label();
450                 mv.visitLabel(l5);
451                 Label l6 = new Label();
452                 mv.visitJumpInsn(GOTO, l6);
453                 Label l7 = new Label();
454                 mv.visitLabel(l7);
455                 mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"[Ljava/lang/reflect/Method;", Opcodes.INTEGER}, 0, null);
456                 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;");
457                 mv.visitVarInsn(ILOAD, 1);
458                 mv.visitVarInsn(ALOAD, 0);
459                 mv.visitVarInsn(ILOAD, 1);
460                 mv.visitInsn(AALOAD);
461                 mv.visitMethodInsn(INVOKESTATIC, "org/simantics/databoard/DataTypes", "getMethodBinding", "(Ljava/lang/reflect/Method;)Lorg/simantics/databoard/method/MethodBinding;");
462                 mv.visitInsn(AASTORE);
463                 Label l8 = new Label();
464                 mv.visitLabel(l8);
465                 mv.visitIincInsn(1, 1);
466                 mv.visitLabel(l6);
467                 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
468                 mv.visitVarInsn(ILOAD, 1);
469                 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;");
470                 mv.visitInsn(ARRAYLENGTH);
471                 mv.visitJumpInsn(IF_ICMPLT, l7);
472                 Label l9 = new Label();
473                 mv.visitLabel(l9);
474                 mv.visitInsn(RETURN);
475                 Label l10 = new Label();
476                 mv.visitLabel(l10);
477                 mv.visitLocalVariable("methods", "[Ljava/lang/reflect/Method;", null, l2, l10, 0);
478                 mv.visitLocalVariable("i", "I", null, l5, l9, 1);
479                 mv.visitMaxs(4, 2);
480                 mv.visitEnd();
481                 }
482                 
483                 // Constructor
484                 {
485                 mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/simantics/data/session/MethodInterface;)V", null, new String[] { "org/simantics/data/error/MethodNotSupportedException" });
486                 mv.visitCode();
487                 Label l0 = new Label();
488                 mv.visitLabel(l0);
489                 mv.visitVarInsn(ALOAD, 0);
490                 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
491                 Label l1 = new Label();
492                 mv.visitLabel(l1);
493                 mv.visitVarInsn(ALOAD, 0);
494                 mv.visitVarInsn(ALOAD, 1);
495                 mv.visitFieldInsn(PUTFIELD, classResourceName, "mi", "Lorg/simantics/data/session/MethodInterface;");
496                 Label l2 = new Label();
497                 mv.visitLabel(l2);
498                 mv.visitVarInsn(ALOAD, 0);
499                 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;");
500                 mv.visitInsn(ARRAYLENGTH);
501                 mv.visitTypeInsn(ANEWARRAY, "org/simantics/data/session/MethodInterface$Method");
502                 mv.visitFieldInsn(PUTFIELD, classResourceName, "methods", "[Lorg/simantics/data/session/MethodInterface$Method;");
503                 Label l3 = new Label();
504                 mv.visitLabel(l3);
505                 mv.visitInsn(ICONST_0);
506                 mv.visitVarInsn(ISTORE, 2);
507                 Label l4 = new Label();
508                 mv.visitLabel(l4);
509                 Label l5 = new Label();
510                 mv.visitJumpInsn(GOTO, l5);
511                 Label l6 = new Label();
512                 mv.visitLabel(l6);
513                 mv.visitFrame(Opcodes.F_FULL, 3, new Object[] {classResourceName, "org/simantics/data/session/MethodInterface", Opcodes.INTEGER}, 0, new Object[] {});
514                 mv.visitVarInsn(ALOAD, 0);
515                 mv.visitFieldInsn(GETFIELD, classResourceName, "methods", "[Lorg/simantics/data/session/MethodInterface$Method;");
516                 mv.visitVarInsn(ILOAD, 2);
517                 mv.visitVarInsn(ALOAD, 1);
518                 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;");
519                 mv.visitVarInsn(ILOAD, 2);
520                 mv.visitInsn(AALOAD);
521                 mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/data/session/MethodInterface", "getMethod", "(Lorg/simantics/databoard/method/MethodBinding;)Lorg/simantics/data/session/MethodInterface$Method;");
522                 mv.visitInsn(AASTORE);
523                 Label l7 = new Label();
524                 mv.visitLabel(l7);
525                 mv.visitIincInsn(2, 1);
526                 mv.visitLabel(l5);
527                 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
528                 mv.visitVarInsn(ILOAD, 2);
529                 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;");
530                 mv.visitInsn(ARRAYLENGTH);
531                 mv.visitJumpInsn(IF_ICMPLT, l6);
532                 Label l8 = new Label();
533                 mv.visitLabel(l8);
534                 mv.visitInsn(RETURN);
535                 Label l9 = new Label();
536                 mv.visitLabel(l9);
537                 mv.visitLocalVariable("this", classTypeDescriptor, null, l0, l9, 0);
538                 mv.visitLocalVariable("mi", "Lorg/simantics/data/session/MethodInterface;", null, l0, l9, 1);
539                 mv.visitLocalVariable("i", "I", null, l4, l8, 2);
540                 mv.visitMaxs(5, 3);
541                 mv.visitEnd();
542                 }
543                 
544                 // Method
545                 int methodNumber = 0;
546                 for (java.lang.reflect.Method m : methods)
547                 {
548                 String typeDescription = "";
549                 Class<?>[] params = m.getParameterTypes();
550                 for (int i=0; i<params.length; i++) {
551                         if (i>0) typeDescription += ";";
552                         typeDescription += classToTypeDescriptor(params[i]);
553                 }
554                 typeDescription = "("+typeDescription+")"+classToTypeDescriptor(m.getReturnType());
555                 System.out.println(typeDescription+" "+m.getName());
556                         
557                 Class<?>[] exceptions = m.getExceptionTypes();
558                 String[] exceptionResourceNames = new String[exceptions.length];
559                 for (int i=0; i<exceptionResourceNames.length; i++) {
560                         exceptionResourceNames[i] = exceptions[i].getName().replaceAll("\\.", "/");
561                 }
562                 
563                 // Registers
564                 // 0 - this
565                 // 1..argRegs args
566                 // argRegs+1 - method
567                 // argRegs+2 - args (the array)
568                 // argRegs+3 - AsyncResult
569                 // argRegs+4 - e
570                 // argRegs+5 - ExecutionError.cause
571                 // argRegs+6 - e
572                 
573                 int argRegs = 0;
574                 for (int i=0; i<params.length; i++) {
575                         Class<?> clazz = params[i];
576                         argRegs++;
577                         if (clazz==long.class || clazz==float.class || clazz==Double.class) argRegs++;
578                 }               
579                 
580                 mv = cw.visitMethod(ACC_PUBLIC, m.getName(), typeDescription, null, exceptionResourceNames);
581                 mv.visitCode();
582                 Label l0 = new Label();
583                 Label l1 = new Label();
584                 Label l2 = new Label();
585                 mv.visitTryCatchBlock(l0, l1, l2, "org/simantics/data/session/MethodInterface$ExecutionError");
586                 Label l3 = new Label();
587                 mv.visitTryCatchBlock(l0, l1, l3, "java/lang/InterruptedException");
588                 Label l4 = new Label();
589                 mv.visitLabel(l4);
590                 mv.visitVarInsn(ALOAD, 0);
591                 mv.visitFieldInsn(GETFIELD, classResourceName, "methods", "[Lorg/simantics/data/session/MethodInterface$Method;");
592                 // Method m and puts into register 
593                 mv.visitLdcInsn(Integer.valueOf(methodNumber));
594                 mv.visitInsn(AALOAD);
595                 mv.visitVarInsn(ASTORE, argRegs+1);
596                 Label l5 = new Label();
597                 mv.visitLabel(l5);
598                 mv.visitLdcInsn(Integer.valueOf(params.length));
599                 mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
600                 
601                 int register = 1; // argument register  
602                 for (int i=0; i<params.length; i++) {
603                         Class<?> clazz = params[i];
604                         mv.visitInsn(DUP);
605                         mv.visitLdcInsn(Integer.valueOf(i));
606                         
607                         if (clazz==byte.class) {
608                                 mv.visitVarInsn(ILOAD, register++);
609                                 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");                           
610                         } else if (clazz==char.class) {
611                                 mv.visitVarInsn(ILOAD, register++);
612                                 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");                         
613                         } else if (clazz==boolean.class) {
614                                 mv.visitVarInsn(ILOAD, register++);
615                                 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");                             
616                         } else if (clazz==byte.class) {
617                                 mv.visitVarInsn(ILOAD, register++);
618                                 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");                         
619                         } else if (clazz==int.class) {
620                                 mv.visitVarInsn(ILOAD, register++);
621                                 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");                             
622                         } else if (clazz==long.class) {
623                                 mv.visitVarInsn(LLOAD, register); register += 2;
624                                 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(F)Ljava/lang/Long;");                           
625                         } else if (clazz==float.class) {
626                                 mv.visitVarInsn(FLOAD, register); register += 2;
627                                 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");                         
628                         } else if (clazz==Double.class) {
629                                 mv.visitVarInsn(DLOAD, register); register += 2;
630                                 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
631                         } else {                                
632                                 // Push argument to stack 
633                                 mv.visitVarInsn(ALOAD, register++); 
634                         }                       
635                         mv.visitInsn(AASTORE);
636                 }
637                 
638                 // Store args to argRegs+2
639                 mv.visitVarInsn(ASTORE, argRegs+2);
640                 Label l6 = new Label();
641                 mv.visitLabel(l6);
642                 mv.visitVarInsn(ALOAD, argRegs+1 /* m */);
643                 mv.visitVarInsn(ALOAD, argRegs+2 /*args*/);
644                 mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/data/session/MethodInterface$Method", "invoke", "(Ljava/lang/Object;)Lorg/simantics/data/session/MethodInterface$AsyncResult;");
645                 mv.visitVarInsn(ASTORE, argRegs+3);
646                 mv.visitLabel(l0);
647                 mv.visitVarInsn(ALOAD, argRegs+3);
648                 mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/data/session/MethodInterface$AsyncResult", "waitForResponse", "()Ljava/lang/Object;");
649                 // TODO Return typecase result
650                 Class<?> returnType = m.getReturnType();                
651                 
652                 if (returnType==void.class) {
653                         mv.visitInsn(POP);
654                         mv.visitInsn(RETURN);                   
655                 } else if (returnType==int.class) {
656                         mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
657                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
658                         mv.visitLabel(l1);
659                         mv.visitInsn(IRETURN);                  
660                 } else if (returnType==byte.class) {
661                         mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
662                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "B()");
663                         mv.visitLabel(l1);
664                         mv.visitInsn(IRETURN);                  
665                 } else if (returnType==char.class) {
666                         mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
667                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
668                         mv.visitLabel(l1);
669                         mv.visitInsn(IRETURN);                  
670                 } else if (returnType==boolean.class) {
671                         mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
672                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
673                         mv.visitLabel(l1);
674                         mv.visitInsn(IRETURN);                  
675                 } else if (returnType==short.class) {
676                         mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
677                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
678                         mv.visitLabel(l1);
679                         mv.visitInsn(IRETURN);                  
680                 } else if (returnType==long.class) {
681                         mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
682                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
683                         mv.visitLabel(l1);
684                         mv.visitInsn(LRETURN);                  
685                 } else if (returnType==double.class) {
686                         mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
687                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
688                         mv.visitLabel(l1);
689                         mv.visitInsn(DRETURN);                  
690                 } else if (returnType==float.class) {
691                         mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
692                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
693                         mv.visitLabel(l1);
694                         mv.visitInsn(FRETURN);                  
695                 } else {
696                         // Object
697                         mv.visitTypeInsn(CHECKCAST, returnType.getName().replaceAll("\\.", "/"));
698                         mv.visitLabel(l1);
699                         mv.visitInsn(ARETURN);                  
700                 }
701                 
702                 
703                 // Handle exceptions
704                 mv.visitLabel(l2);
705                 mv.visitFrame(Opcodes.F_FULL, argRegs+4, new Object[] {classResourceName, "java/lang/Integer", "org/simantics/data/session/MethodInterface$Method", "[Ljava/lang/Object;", "org/simantics/data/session/MethodInterface$AsyncResult"}, 1, new Object[] {"org/simantics/data/session/MethodInterface$ExecutionError"});
706                 mv.visitVarInsn(ASTORE, argRegs+4);
707                 Label l7 = new Label();
708                 mv.visitLabel(l7);
709                 mv.visitVarInsn(ALOAD, argRegs+4);
710                 mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/data/session/MethodInterface$ExecutionError", "getError", "()Ljava/lang/Object;");
711                 mv.visitVarInsn(ASTORE, argRegs+5); // argRegs+5 <- ExecutionError.cause
712                                 
713                 Class<?>[] exceptionClasses = m.getExceptionTypes();
714                 Label nextException[] = new Label[exceptionClasses.length];             
715                 for (int i=0; i<exceptionClasses.length; i++)
716                 {                       
717                         Class<?> exceptionClass = exceptionClasses[i];
718                         String exceptionClassResourceName = exceptionClass.getName().replaceAll("\\.", "/");
719                         nextException[i] = new Label();
720                         // If instanceof MyException
721                         Label l8 = new Label();
722                         mv.visitLabel(l8);
723                         mv.visitVarInsn(ALOAD, argRegs+5); // Cause
724                         mv.visitTypeInsn(INSTANCEOF, exceptionClassResourceName);
725                         mv.visitJumpInsn(IFEQ, nextException[i]); // If not, go to ExecutionError
726                         // If so, throw it
727                         mv.visitVarInsn(ALOAD, argRegs+5); // e
728                         mv.visitTypeInsn(CHECKCAST, exceptionClassResourceName);
729                         mv.visitInsn(ATHROW);
730                         mv.visitLabel(nextException[i]);
731                 }
732                 
733                 // ExecutionError
734                 mv.visitFrame(Opcodes.F_APPEND,argRegs+1, new Object[] {"org/simantics/data/session/MethodInterface$ExecutionError", "java/lang/Object"}, 0, null);
735                 mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
736                 mv.visitInsn(DUP);
737                 mv.visitVarInsn(ALOAD, argRegs+4);
738                 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V");
739                 mv.visitInsn(ATHROW);
740                 
741                 // InteruptedException
742                 mv.visitLabel(l3);
743                 mv.visitFrame(Opcodes.F_FULL, argRegs+4, new Object[] {classResourceName, "java/lang/Integer", "org/simantics/data/session/MethodInterface$Method", "[Ljava/lang/Object;", "org/simantics/data/session/MethodInterface$AsyncResult"}, 1, new Object[] {"java/lang/InterruptedException"});
744                 mv.visitVarInsn(ASTORE, argRegs+4);
745                 Label l10 = new Label();
746                 mv.visitLabel(l10);
747                 mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
748                 mv.visitInsn(DUP);
749                 mv.visitVarInsn(ALOAD, argRegs+4);
750                 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V");
751                 mv.visitInsn(ATHROW);
752                 
753                 Label l11 = new Label();
754                 mv.visitLabel(l11);
755                 mv.visitLocalVariable("this", classTypeDescriptor, null, l4, l11, 0);
756 //              mv.visitLocalVariable("arg1", "Ljava/lang/Integer;", null, l4, l11, 1);
757                 register = 1;
758                 for (int i=0; i<params.length; i++) {
759                         Class<?> clazz = params[i];
760                         mv.visitLocalVariable("arg"+(i+1), classToTypeDescriptor(clazz), null, l4, l11, register);
761                         register++;
762                         if (clazz==long.class || clazz==float.class || clazz==Double.class) argRegs++;
763                 }
764                 mv.visitLocalVariable("m", "Lorg/simantics/data/session/MethodInterface$Method;", null, l5, l11, argRegs+1);
765                 mv.visitLocalVariable("args", "[Ljava/lang/Object;", null, l6, l11, argRegs+2);
766                 mv.visitLocalVariable("result", "Lorg/simantics/data/session/MethodInterface$AsyncResult;", null, l0, l11, argRegs+3);
767                 mv.visitLocalVariable("e", "Lorg/simantics/data/session/MethodInterface$ExecutionError;", null, l7, l3, argRegs+4);
768                 mv.visitLocalVariable("cause", "Ljava/lang/Object;", null, l7, l3, argRegs+5);
769                 mv.visitLocalVariable("e", "Ljava/lang/InterruptedException;", null, l10, l11, argRegs+4);
770                 mv.visitMaxs(argRegs+3, argRegs+6);
771                 mv.visitEnd();
772                 methodNumber++;
773                 }
774
775                 cw.visitEnd();          
776         }
777         
778 }
779