1 /*******************************************************************************
\r
2 * Copyright (c) 2010 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.databoard.method;
14 import static org.objectweb.asm.Opcodes.AALOAD;
\r
15 import static org.objectweb.asm.Opcodes.AASTORE;
\r
16 import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
\r
17 import static org.objectweb.asm.Opcodes.ACC_FINAL;
\r
18 import static org.objectweb.asm.Opcodes.ACC_INTERFACE;
\r
19 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
\r
20 import static org.objectweb.asm.Opcodes.ACC_STATIC;
\r
21 import static org.objectweb.asm.Opcodes.ACC_SUPER;
\r
22 import static org.objectweb.asm.Opcodes.ALOAD;
\r
23 import static org.objectweb.asm.Opcodes.ANEWARRAY;
\r
24 import static org.objectweb.asm.Opcodes.ARETURN;
\r
25 import static org.objectweb.asm.Opcodes.ARRAYLENGTH;
\r
26 import static org.objectweb.asm.Opcodes.ASTORE;
\r
27 import static org.objectweb.asm.Opcodes.ATHROW;
\r
28 import static org.objectweb.asm.Opcodes.CHECKCAST;
\r
29 import static org.objectweb.asm.Opcodes.DLOAD;
\r
30 import static org.objectweb.asm.Opcodes.DRETURN;
\r
31 import static org.objectweb.asm.Opcodes.DUP;
\r
32 import static org.objectweb.asm.Opcodes.FLOAD;
\r
33 import static org.objectweb.asm.Opcodes.FRETURN;
\r
34 import static org.objectweb.asm.Opcodes.GETFIELD;
\r
35 import static org.objectweb.asm.Opcodes.GETSTATIC;
\r
36 import static org.objectweb.asm.Opcodes.GOTO;
\r
37 import static org.objectweb.asm.Opcodes.ICONST_0;
\r
38 import static org.objectweb.asm.Opcodes.IFEQ;
\r
39 import static org.objectweb.asm.Opcodes.IF_ICMPLT;
\r
40 import static org.objectweb.asm.Opcodes.ILOAD;
\r
41 import static org.objectweb.asm.Opcodes.INSTANCEOF;
\r
42 import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
\r
43 import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
\r
44 import static org.objectweb.asm.Opcodes.INVOKESTATIC;
\r
45 import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
\r
46 import static org.objectweb.asm.Opcodes.IRETURN;
\r
47 import static org.objectweb.asm.Opcodes.ISTORE;
\r
48 import static org.objectweb.asm.Opcodes.LLOAD;
\r
49 import static org.objectweb.asm.Opcodes.LRETURN;
\r
50 import static org.objectweb.asm.Opcodes.NEW;
\r
51 import static org.objectweb.asm.Opcodes.POP;
\r
52 import static org.objectweb.asm.Opcodes.PUTFIELD;
\r
53 import static org.objectweb.asm.Opcodes.PUTSTATIC;
\r
54 import static org.objectweb.asm.Opcodes.RETURN;
\r
55 import static org.objectweb.asm.Opcodes.V1_6;
\r
57 import java.lang.reflect.Constructor;
\r
58 import java.lang.reflect.InvocationTargetException;
\r
59 import java.lang.reflect.Method;
\r
60 import java.util.Arrays;
\r
61 import java.util.Comparator;
\r
62 import java.util.HashSet;
\r
63 import java.util.Set;
\r
65 import org.objectweb.asm.ClassWriter;
\r
66 import org.objectweb.asm.FieldVisitor;
\r
67 import org.objectweb.asm.Label;
\r
68 import org.objectweb.asm.MethodVisitor;
\r
69 import org.objectweb.asm.Opcodes;
\r
70 import org.objectweb.asm.Type;
\r
71 import org.simantics.databoard.Bindings;
\r
72 import org.simantics.databoard.Methods;
\r
73 import org.simantics.databoard.adapter.AdaptException;
\r
74 import org.simantics.databoard.adapter.Adapter;
\r
75 import org.simantics.databoard.adapter.AdapterConstructionException;
\r
76 import org.simantics.databoard.binding.error.BindingConstructionException;
\r
77 import org.simantics.databoard.method.MethodInterface.AsyncResult;
\r
78 import org.simantics.databoard.method.MethodInterface.ExecutionError;
\r
80 public class MethodInterfaceUtil {
83 * Bind an instance a to Method Interface
88 * @return the method interface
89 * @throws BindingConstructionException
91 public static <T> MethodInterface bindInterface(Class<T> interfaze, final T obj) throws BindingConstructionException
93 final Interface interfaceType = Methods.getInterfaceType(interfaze);
94 MethodInterface mi = bindInterface(interfaceType, obj);
\r
96 System.out.println("Created methodinterface for "+interfaze.getName());
\r
97 for (MethodTypeDefinition k : mi.getInterface().methodDefinitions) {
\r
98 System.out.print(k);
\r
99 if (k.getType().requestType.getComponentCount()>0) {
\r
100 System.out.print(System.identityHashCode( k.getType().requestType.getComponentType(0) ) );
\r
102 System.out.println();
\r
109 * Bind interface type to an instance
112 * @param interfaceType
114 * @return the method interface
115 * @throws BindingConstructionException
117 public static <T> MethodInterface bindInterface(final Interface interfaceType, final T obj) throws BindingConstructionException
119 // Find matching Java Method for each MethodTypeDefinition
120 int len = interfaceType.getMethodDefinitions().length;
121 final MethodTypeDefinition[] methodDefinitions = interfaceType.getMethodDefinitions();
122 final MethodTypeBinding[] methodBindings = new MethodTypeBinding[ len ];
123 final Method[] methods = new Method[ len ];
124 Class<?> clazz = obj.getClass();
125 Method[] classMethods = clazz.getMethods();
126 for (int i=0; i<len; i++)
128 MethodTypeDefinition def = methodDefinitions[i];
129 MethodType type = def.getType();
130 String name = def.getName();
132 // Find the MethodType from the class methods
133 for (Method m : classMethods) {
134 // Verify name matchs
135 if ( !m.getName().equals(name) ) continue;
136 MethodTypeBinding classMethodTypeBinding = Methods.getMethodTypeBinding(m);
137 if ( !classMethodTypeBinding.getMethodType().equals( type) ) continue;
139 m.setAccessible(true);
140 methodBindings[i] = classMethodTypeBinding;
145 // We did not find suitable method in clazz
146 if (methods[i]==null) {
147 throw new BindingConstructionException("Could not find method "+def+" in "+clazz.getSimpleName());
151 // Read method definitions into an array
153 MethodInterface mi = new MethodInterface() {
155 public org.simantics.databoard.method.MethodInterface.Method getMethod(
156 MethodTypeDefinition description)
157 throws org.simantics.databoard.method.MethodNotSupportedException {
159 for (int i=0; i<methodDefinitions.length; i++) {
160 if (methodDefinitions[i].equals(description)) {
165 if (index<0) throw new org.simantics.databoard.method.MethodNotSupportedException(description.getName());
166 final MethodTypeBinding binding = methodBindings[index];
167 final java.lang.reflect.Method method = methods[index];
169 Method m = new Method() {
171 public MethodTypeBinding getMethodBinding() {
176 public AsyncResult invoke(Object request) {
177 AsyncResultImpl result = new AsyncResultImpl();
179 Object response = method.invoke(obj, (Object[]) request);
180 if (response != null) result.setResponse(response);
\r
181 else result.setInvokeException(new org.simantics.databoard.method.InvokeException(new NullPointerException()));
182 } catch(InvocationTargetException t) {
\r
183 Throwable e = t.getTargetException();
\r
184 if (e instanceof RuntimeException) {
\r
185 result.setInvokeException(new org.simantics.databoard.method.InvokeException( (Exception) e));
\r
187 result.setExecutionError(e);
\r
189 } catch(IllegalArgumentException e) {
190 result.setInvokeException(new org.simantics.databoard.method.InvokeException(e));
191 } catch (IllegalAccessException e) {
192 result.setInvokeException(new org.simantics.databoard.method.InvokeException(e));
201 public org.simantics.databoard.method.MethodInterface.Method getMethod(
202 MethodTypeBinding binding) throws org.simantics.databoard.method.MethodNotSupportedException {
203 MethodTypeDefinition description = binding.getMethodDefinition();
205 for (int i=0; i<methodDefinitions.length; i++) {
206 if (methodDefinitions[i].equals(description)) {
211 if (index<0) throw new org.simantics.databoard.method.MethodNotSupportedException(description.getName());
212 final MethodTypeBinding producerBinding = methodBindings[index];
213 final MethodTypeBinding consumerBinding = binding;
215 final Adapter requestAdapter = Bindings.getTypeAdapter(consumerBinding.getRequestBinding(), producerBinding.getRequestBinding());
216 final Adapter responseAdapter = Bindings.getTypeAdapter(producerBinding.getResponseBinding(), consumerBinding.getResponseBinding());
217 final Adapter errorAdapter = Bindings.getTypeAdapter(producerBinding.getErrorBinding(), consumerBinding.getErrorBinding());
218 final java.lang.reflect.Method method = methods[index];
220 Method m = new Method() {
222 public MethodTypeBinding getMethodBinding() {
223 return consumerBinding;
227 public AsyncResult invoke(Object request) {
228 AsyncResultImpl result = new AsyncResultImpl();
231 request = requestAdapter.adapt(request);
232 Object response = method.invoke(obj, (Object[]) request);
233 response = responseAdapter.adapt(response);
234 result.setResponse(response);
235 } catch (AdaptException e1) {
236 result.setInvokeException(new InvokeException(e1));
237 } catch (InvocationTargetException t) {
240 error = errorAdapter.adapt(t.getCause());
241 result.setExecutionError(error);
242 } catch (AdaptException e) {
243 result.setInvokeException( new InvokeException(e) );
245 } catch (IllegalArgumentException e) {
246 result.setInvokeException(new org.simantics.databoard.method.InvokeException(e));
247 } catch (IllegalAccessException e) {
248 result.setInvokeException(new org.simantics.databoard.method.InvokeException(e));
256 } catch (AdapterConstructionException e1) {
257 throw new MethodNotSupportedException("Could not adapt method "+e1.getMessage(), e1);
263 public Interface getInterface() {
264 return interfaceType;
270 @SuppressWarnings("unchecked")
271 public static <T> T createProxy(Class<T> interfaze, MethodInterface mi)
272 throws BindingConstructionException
274 StubClassLoader cl = new StubClassLoader(interfaze.getClassLoader());
277 virhe = cl.loadClass(interfaze.getName()+"_Stub");
278 Constructor<?> c = virhe.getConstructor(MethodInterface.class);
279 return (T) c.newInstance(mi);
280 } catch (ClassNotFoundException e) {
281 System.err.println("Did you remember to include org.objectweb.asm ??");
282 throw new BindingConstructionException(e);
283 } catch (SecurityException e) {
284 throw new BindingConstructionException(e);
285 } catch (NoSuchMethodException e) {
286 throw new BindingConstructionException(e);
287 } catch (IllegalArgumentException e) {
288 throw new BindingConstructionException(e);
289 } catch (InstantiationException e) {
290 throw new BindingConstructionException(e);
291 } catch (IllegalAccessException e) {
292 throw new BindingConstructionException(e);
293 } catch (InvocationTargetException e) {
294 throw new BindingConstructionException(e.getCause());
298 public static Comparator<java.lang.reflect.Method> methodComparator = new Comparator<java.lang.reflect.Method>(){
299 @Override public int compare(java.lang.reflect.Method o1,java.lang.reflect.Method o2){
300 return o1.getName().compareTo(o2.getName());}};
302 public static MethodInterface adaptMethods(final MethodInterface mi, final MethodTypeDefinition[] rangeMethods)
304 //final MethodTypeDefinition[] domainMethods = mi.getInterface().getMethodDefinitions();
305 throw new IllegalArgumentException("To be implemented");
307 return new MethodInterface() {
309 public org.simantics.databoard.method.MethodInterface.Method getMethod(
310 MethodDescription rangeDescription)
311 throws MethodNotSupportedException {
312 MethodDescription domainDescription = null;
313 for (int i=0; i<rangeMethods.length; i++) {
314 if (rangeMethods[i].equals(rangeDescription)) {
315 domainDescription = domainMethods[i];
318 if (domainDescription==null)
319 throw new MethodNotSupportedException();
321 return new org.simantics.databoard.method.MethodInterface.Method() {
323 public MethodBinding getMethodBinding() {
327 public AsyncResult invoke(Object request) {
333 public org.simantics.databoard.method.MethodInterface.Method getMethod(
334 MethodBinding binding) throws MethodNotSupportedException {
338 public MethodDescription[] getMethodDescriptions() {
345 static class StubClassLoader extends ClassLoader {
347 public StubClassLoader() {
348 super(Thread.currentThread().getContextClassLoader());
351 public StubClassLoader(ClassLoader parent) {
356 protected Class<?> findClass(String name) throws ClassNotFoundException {
357 if (name.endsWith("_Stub")) {
358 Class<?> interfaze = loadClass(name.substring(0, name.length()-5));
359 ClassWriter cw = new ClassWriter(0);
360 createImpl(name, interfaze, cw);
361 byte[] b = cw.toByteArray();
\r
363 new ClassReader(b).accept(
\r
364 new ASMifierClassVisitor(new PrintWriter(System.out)),
\r
368 Class<?> clazz = defineClass(name, b, 0, b.length);
371 return super.findClass(name);
374 static String toTypeDescriptor(Class<?> clazz) {
375 if (clazz==void.class) return "V";
376 if (clazz==boolean.class) return "Z";
377 if (clazz==char.class) return "C";
378 if (clazz==byte.class) return "B";
379 if (clazz==short.class) return "S";
380 if (clazz==int.class) return "I";
381 if (clazz==float.class) return "F";
382 if (clazz==long.class) return "J";
383 if (clazz==double.class) return "D";
384 if (clazz.isArray()) return clazz.getName().replaceAll("\\.", "/");
385 return "L"+clazz.getName().replaceAll("\\.", "/")+";";
388 void createImpl(String className, Class<?> interfaze, ClassWriter cw) {
391 //AnnotationVisitor av0;
393 java.lang.reflect.Method[] methods = interfaze.getMethods();
394 Arrays.sort(methods, MethodInterfaceUtil.methodComparator);
396 String classResourceName = className.replaceAll("\\.", "/");
397 String classTypeDescriptor = "L"+classResourceName+";";
398 String interfaceResourceName = classResourceName.substring(0, classResourceName.length()-5);
399 String interfaceTypeDescriptor = "L"+interfaceResourceName+";";
401 cw.visit(V1_6, ACC_SUPER | ACC_PUBLIC, classResourceName, null, "java/lang/Object", new String[] { interfaceResourceName });
404 Set<Class<?>> imports = new HashSet<Class<?>>();
405 imports.add(AsyncResult.class);
406 imports.add(ExecutionError.class);
407 imports.add(Method.class);
408 imports.add(interfaze);
410 for (java.lang.reflect.Method m : methods) {
411 for (Class<?> clazz : m.getExceptionTypes()) {
414 for (Class<?> clazz : m.getParameterTypes()) {
417 imports.add(m.getReturnType());
420 for (Class<?> clazz : imports) {
421 if (clazz.isPrimitive()) continue;
422 String name = clazz.getName();
423 if (name.startsWith("java.lang")) continue;
424 String resourceName = name.replaceAll("\\.", "/");
425 String outerName = resourceName.contains("$") ? resourceName.substring(0, resourceName.indexOf('$')) : null;
426 String className_ = clazz.isArray() ? clazz.getSimpleName().substring(0, clazz.getSimpleName().length()-2) : clazz.getSimpleName();
427 int access = ACC_PUBLIC + ACC_STATIC + (clazz.isInterface() ? ACC_INTERFACE + ACC_ABSTRACT : 0);
428 // System.out.printf("name=%s, outerName=%s, innerName=%s\n", resourceName, outerName, className_);
429 cw.visitInnerClass(resourceName, outerName, className_, access);
434 fv = cw.visitField(ACC_FINAL + ACC_STATIC, "interfaze", "Ljava/lang/Class;", "Ljava/lang/Class<*>;", null);
438 fv = cw.visitField(ACC_FINAL + ACC_STATIC, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;", null, null);
442 fv = cw.visitField(0, "mi", "Lorg/simantics/databoard/method/MethodInterface;", null, null);
446 fv = cw.visitField(0, "methods", "[Lorg/simantics/databoard/method/MethodInterface$Method;", null, null);
450 // Init class - static {}
452 mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
454 Label l0 = new Label();
456 mv.visitLdcInsn(Type.getType(interfaceTypeDescriptor));
457 mv.visitFieldInsn(PUTSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;");
458 Label l1 = new Label();
460 mv.visitFieldInsn(GETSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;");
461 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethods", "()[Ljava/lang/reflect/Method;");
462 mv.visitVarInsn(ASTORE, 0);
463 Label l2 = new Label();
465 mv.visitVarInsn(ALOAD, 0);
466 mv.visitFieldInsn(GETSTATIC, "org/simantics/databoard/method/MethodInterfaceUtil", "methodComparator", "Ljava/util/Comparator;");
467 mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "sort", "([Ljava/lang/Object;Ljava/util/Comparator;)V");
468 Label l3 = new Label();
470 mv.visitVarInsn(ALOAD, 0);
471 mv.visitInsn(ARRAYLENGTH);
472 mv.visitTypeInsn(ANEWARRAY, "org/simantics/databoard/method/MethodTypeBinding");
473 mv.visitFieldInsn(PUTSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;");
474 Label l4 = new Label();
476 mv.visitInsn(ICONST_0);
477 mv.visitVarInsn(ISTORE, 1);
478 Label l5 = new Label();
480 Label l6 = new Label();
481 mv.visitJumpInsn(GOTO, l6);
482 Label l7 = new Label();
484 mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"[Ljava/lang/reflect/Method;", Opcodes.INTEGER}, 0, null);
485 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;");
486 mv.visitVarInsn(ILOAD, 1);
487 mv.visitVarInsn(ALOAD, 0);
488 mv.visitVarInsn(ILOAD, 1);
489 mv.visitInsn(AALOAD);
490 mv.visitMethodInsn(INVOKESTATIC, "org/simantics/databoard/Methods", "getMethodTypeBinding", "(Ljava/lang/reflect/Method;)Lorg/simantics/databoard/method/MethodTypeBinding;");
491 mv.visitInsn(AASTORE);
492 Label l8 = new Label();
494 mv.visitIincInsn(1, 1);
496 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
497 mv.visitVarInsn(ILOAD, 1);
498 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;");
499 mv.visitInsn(ARRAYLENGTH);
500 mv.visitJumpInsn(IF_ICMPLT, l7);
501 Label l9 = new Label();
503 mv.visitInsn(RETURN);
504 Label l10 = new Label();
506 mv.visitLocalVariable("methods", "[Ljava/lang/reflect/Method;", null, l2, l10, 0);
507 mv.visitLocalVariable("i", "I", null, l5, l9, 1);
514 mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/simantics/databoard/method/MethodInterface;)V", null, new String[] { "org/simantics/databoard/method/MethodNotSupportedException" });
516 Label l0 = new Label();
518 mv.visitVarInsn(ALOAD, 0);
519 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
520 Label l1 = new Label();
522 mv.visitVarInsn(ALOAD, 0);
523 mv.visitVarInsn(ALOAD, 1);
524 mv.visitFieldInsn(PUTFIELD, classResourceName, "mi", "Lorg/simantics/databoard/method/MethodInterface;");
525 Label l2 = new Label();
527 mv.visitVarInsn(ALOAD, 0);
528 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;");
529 mv.visitInsn(ARRAYLENGTH);
530 mv.visitTypeInsn(ANEWARRAY, "org/simantics/databoard/method/MethodInterface$Method");
531 mv.visitFieldInsn(PUTFIELD, classResourceName, "methods", "[Lorg/simantics/databoard/method/MethodInterface$Method;");
532 Label l3 = new Label();
534 mv.visitInsn(ICONST_0);
535 mv.visitVarInsn(ISTORE, 2);
536 Label l4 = new Label();
538 Label l5 = new Label();
539 mv.visitJumpInsn(GOTO, l5);
540 Label l6 = new Label();
542 mv.visitFrame(Opcodes.F_FULL, 3, new Object[] {classResourceName, "org/simantics/databoard/method/MethodInterface", Opcodes.INTEGER}, 0, new Object[] {});
543 mv.visitVarInsn(ALOAD, 0);
544 mv.visitFieldInsn(GETFIELD, classResourceName, "methods", "[Lorg/simantics/databoard/method/MethodInterface$Method;");
545 mv.visitVarInsn(ILOAD, 2);
546 mv.visitVarInsn(ALOAD, 1);
547 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;");
548 mv.visitVarInsn(ILOAD, 2);
549 mv.visitInsn(AALOAD);
550 mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/databoard/method/MethodInterface", "getMethod", "(Lorg/simantics/databoard/method/MethodTypeBinding;)Lorg/simantics/databoard/method/MethodInterface$Method;");
551 mv.visitInsn(AASTORE);
552 Label l7 = new Label();
554 mv.visitIincInsn(2, 1);
556 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
557 mv.visitVarInsn(ILOAD, 2);
558 mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodTypeBinding;");
559 mv.visitInsn(ARRAYLENGTH);
560 mv.visitJumpInsn(IF_ICMPLT, l6);
561 Label l8 = new Label();
563 mv.visitInsn(RETURN);
564 Label l9 = new Label();
566 mv.visitLocalVariable("this", classTypeDescriptor, null, l0, l9, 0);
567 mv.visitLocalVariable("mi", "Lorg/simantics/databoard/method/MethodInterface;", null, l0, l9, 1);
568 mv.visitLocalVariable("i", "I", null, l4, l8, 2);
574 int methodNumber = 0;
575 for (java.lang.reflect.Method m : methods)
577 String typeDescription = "";
578 Class<?>[] params = m.getParameterTypes();
579 for (int i=0; i<params.length; i++) {
580 typeDescription += toTypeDescriptor(params[i]);
582 typeDescription = "("+typeDescription+")"+toTypeDescriptor(m.getReturnType());
583 // System.out.println(typeDescription+" "+m.getName());
585 Class<?>[] exceptions = m.getExceptionTypes();
586 String[] exceptionResourceNames = new String[exceptions.length];
587 for (int i=0; i<exceptionResourceNames.length; i++) {
588 exceptionResourceNames[i] = exceptions[i].getName().replaceAll("\\.", "/");
594 // argRegs+1 - method
595 // argRegs+2 - args (the array)
596 // argRegs+3 - AsyncResult
598 // argRegs+5 - ExecutionError.cause
602 for (int i=0; i<params.length; i++) {
603 Class<?> clazz = params[i];
605 if (clazz==long.class || clazz==double.class) argRegs++;
608 mv = cw.visitMethod(ACC_PUBLIC, m.getName(), typeDescription, null, exceptionResourceNames);
610 Label l0 = new Label();
611 Label l1 = new Label();
612 Label l2 = new Label();
613 mv.visitTryCatchBlock(l0, l1, l2, "org/simantics/databoard/method/MethodInterface$ExecutionError");
614 Label l3 = new Label();
615 mv.visitTryCatchBlock(l0, l1, l3, "java/lang/InterruptedException");
616 Label l4 = new Label();
618 mv.visitVarInsn(ALOAD, 0);
619 mv.visitFieldInsn(GETFIELD, classResourceName, "methods", "[Lorg/simantics/databoard/method/MethodInterface$Method;");
620 // Method m and puts into register
621 mv.visitLdcInsn(Integer.valueOf(methodNumber));
622 mv.visitInsn(AALOAD);
623 mv.visitVarInsn(ASTORE, argRegs+1);
624 Label l5 = new Label();
626 mv.visitLdcInsn(Integer.valueOf(params.length));
627 mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
629 int register = 1; // argument register
630 for (int i=0; i<params.length; i++) {
631 Class<?> clazz = params[i];
633 mv.visitLdcInsn(Integer.valueOf(i));
635 if (clazz==byte.class) {
636 mv.visitVarInsn(ILOAD, register++);
637 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
638 } else if (clazz==char.class) {
639 mv.visitVarInsn(ILOAD, register++);
640 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
641 } else if (clazz==boolean.class) {
642 mv.visitVarInsn(ILOAD, register++);
643 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
644 } else if (clazz==byte.class) {
645 mv.visitVarInsn(ILOAD, register++);
646 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
647 } else if (clazz==int.class) {
648 mv.visitVarInsn(ILOAD, register++);
649 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
650 } else if (clazz==long.class) {
651 mv.visitVarInsn(LLOAD, register); register += 2;
652 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(F)Ljava/lang/Long;");
653 } else if (clazz==float.class) {
654 mv.visitVarInsn(FLOAD, register); register += 2;
655 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
656 } else if (clazz==double.class) {
657 mv.visitVarInsn(DLOAD, register); register += 2;
658 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
660 // Push argument to stack
661 mv.visitVarInsn(ALOAD, register++);
663 mv.visitInsn(AASTORE);
666 // Store args to argRegs+2
667 mv.visitVarInsn(ASTORE, argRegs+2);
668 Label l6 = new Label();
670 mv.visitVarInsn(ALOAD, argRegs+1 /* m */);
671 mv.visitVarInsn(ALOAD, argRegs+2 /*args*/);
672 mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/databoard/method/MethodInterface$Method", "invoke", "(Ljava/lang/Object;)Lorg/simantics/databoard/method/MethodInterface$AsyncResult;");
673 mv.visitVarInsn(ASTORE, argRegs+3);
675 mv.visitVarInsn(ALOAD, argRegs+3);
676 mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/databoard/method/MethodInterface$AsyncResult", "waitForResponse", "()Ljava/lang/Object;");
677 // TODO Return typecase result
678 Class<?> returnType = m.getReturnType();
680 if (returnType==void.class) {
683 mv.visitInsn(RETURN);
684 } else if (returnType==int.class) {
685 mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
686 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
688 mv.visitInsn(IRETURN);
689 } else if (returnType==byte.class) {
690 mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
691 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "B()");
693 mv.visitInsn(IRETURN);
694 } else if (returnType==char.class) {
695 mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
696 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
698 mv.visitInsn(IRETURN);
699 } else if (returnType==boolean.class) {
700 mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
701 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
703 mv.visitInsn(IRETURN);
704 } else if (returnType==short.class) {
705 mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
706 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
708 mv.visitInsn(IRETURN);
709 } else if (returnType==long.class) {
710 mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
711 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
713 mv.visitInsn(LRETURN);
714 } else if (returnType==double.class) {
715 mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
716 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
718 mv.visitInsn(DRETURN);
719 } else if (returnType==float.class) {
720 mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
721 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
723 mv.visitInsn(FRETURN);
726 mv.visitTypeInsn(CHECKCAST, returnType.getName().replaceAll("\\.", "/"));
728 mv.visitInsn(ARETURN);
734 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"});
735 mv.visitVarInsn(ASTORE, argRegs+4);
736 Label l7 = new Label();
738 mv.visitVarInsn(ALOAD, argRegs+4);
739 mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/method/MethodInterface$ExecutionError", "getError", "()Ljava/lang/Object;");
740 mv.visitVarInsn(ASTORE, argRegs+5); // argRegs+5 <- ExecutionError.cause
742 Class<?>[] exceptionClasses = m.getExceptionTypes();
743 Label nextException[] = new Label[exceptionClasses.length];
744 for (int i=0; i<exceptionClasses.length; i++)
746 Class<?> exceptionClass = exceptionClasses[i];
747 String exceptionClassResourceName = exceptionClass.getName().replaceAll("\\.", "/");
748 nextException[i] = new Label();
749 // If instanceof MyException
750 Label l8 = new Label();
752 mv.visitVarInsn(ALOAD, argRegs+5); // Cause
753 mv.visitTypeInsn(INSTANCEOF, exceptionClassResourceName);
754 mv.visitJumpInsn(IFEQ, nextException[i]); // If not, go to ExecutionError
756 mv.visitVarInsn(ALOAD, argRegs+5); // e
757 mv.visitTypeInsn(CHECKCAST, exceptionClassResourceName);
758 mv.visitInsn(ATHROW);
759 mv.visitLabel(nextException[i]);
763 mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"org/simantics/databoard/method/MethodInterface$ExecutionError", "java/lang/Object"}, 0, null);
764 mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
766 mv.visitVarInsn(ALOAD, argRegs+4);
767 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V");
768 mv.visitInsn(ATHROW);
770 // InteruptedException
772 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"});
773 mv.visitVarInsn(ASTORE, argRegs+4);
774 Label l10 = new Label();
776 mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
778 mv.visitVarInsn(ALOAD, argRegs+4);
779 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V");
780 mv.visitInsn(ATHROW);
782 Label l11 = new Label();
784 mv.visitLocalVariable("this", classTypeDescriptor, null, l4, l11, 0);
785 // mv.visitLocalVariable("arg1", "Ljava/lang/Integer;", null, l4, l11, 1);
787 for (int i=0; i<params.length; i++) {
788 Class<?> clazz = params[i];
789 mv.visitLocalVariable("arg"+(i+1), toTypeDescriptor(clazz), null, l4, l11, register);
791 if (clazz==long.class || clazz==double.class) argRegs++;
793 mv.visitLocalVariable("m", "Lorg/simantics/databoard/method/MethodInterface$Method;", null, l5, l11, argRegs+1);
794 mv.visitLocalVariable("args", "[Ljava/lang/Object;", null, l6, l11, argRegs+2);
795 mv.visitLocalVariable("result", "Lorg/simantics/databoard/method/MethodInterface$AsyncResult;", null, l0, l11, argRegs+3);
796 mv.visitLocalVariable("e", "Lorg/simantics/databoard/method/MethodInterface$ExecutionError;", null, l7, l3, argRegs+4);
797 mv.visitLocalVariable("cause", "Ljava/lang/Object;", null, l7, l3, argRegs+5);
798 mv.visitLocalVariable("e", "Ljava/lang/InterruptedException;", null, l10, l11, argRegs+4);
799 mv.visitMaxs(argRegs+3, argRegs+6);