--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.databoard.binding.reflection;\r
+\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Modifier;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.objectweb.asm.AnnotationVisitor;\r
+import org.objectweb.asm.ClassVisitor;\r
+import org.objectweb.asm.ClassWriter;\r
+import org.objectweb.asm.FieldVisitor;\r
+import org.objectweb.asm.Label;\r
+import org.objectweb.asm.MethodVisitor;\r
+import org.objectweb.asm.Opcodes;\r
+import org.objectweb.asm.Type;\r
+import org.simantics.databoard.binding.error.BindingConstructionException;\r
+\r
+public class AsmBindingClassLoader extends ClassLoader implements Opcodes {\r
+\r
+ Map<String, Class<?>> map = new HashMap<String, Class<?>>();\r
+ \r
+ public AsmBindingClassLoader() {\r
+ super(Thread.currentThread().getContextClassLoader());\r
+ }\r
+\r
+ public AsmBindingClassLoader(ClassLoader parent) {\r
+ super(parent);\r
+ } \r
+ \r
+ public String toBindingClassName( String targetClassName )\r
+ {\r
+ if ( targetClassName.startsWith("java" ) ) {\r
+ return "x"+targetClassName+".Binding";\r
+ }\r
+ return targetClassName+".Binding";\r
+ }\r
+ \r
+ public String toTargetClassName( String bindingClassName )\r
+ {\r
+ if (!bindingClassName.endsWith(".Binding")) return null;\r
+ if (bindingClassName.substring(1,5).equals("java")) {\r
+ return bindingClassName.substring(1, bindingClassName.length()-8);\r
+ } else {\r
+ return bindingClassName.substring(0, bindingClassName.length()-8);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ protected synchronized Class<?> findClass(String bindingClassName) \r
+ throws ClassNotFoundException \r
+ {\r
+ Class<?> c = map.get(bindingClassName);\r
+ if ( c!= null) return c;\r
+ \r
+ try {\r
+ String targetClassName = toTargetClassName(bindingClassName);\r
+ if ( targetClassName == null ) {\r
+// try {\r
+ return super.findClass(bindingClassName);\r
+// } catch( ClassNotFoundException e ) {\r
+// e.printStackTrace();\r
+// throw e;\r
+// }\r
+ }\r
+ \r
+ ClassLoader cl = getParent();\r
+ if (cl==null) { \r
+ cl = Thread.currentThread().getContextClassLoader();\r
+ }\r
+ Class<?> targetClass = cl.loadClass( targetClassName );\r
+ ClassInfo ci = ClassInfo.getInfo( targetClass );\r
+ byte[] data = createBindingClass( ci, bindingClassName );\r
+ Class<?> bindingClass = defineClass( bindingClassName, data, 0, data.length );\r
+ map.put(bindingClassName, bindingClass);\r
+ return bindingClass;\r
+ } catch (BindingConstructionException e) {\r
+ throw new ClassNotFoundException( e.getMessage(), e.getCause() );\r
+ } \r
+ } \r
+ \r
+ public synchronized Class<?> getBindingClass(Class<?> targetClass)\r
+ throws ClassNotFoundException\r
+ {\r
+ String targetClassName = targetClass.getName();\r
+ String bindingClassName = toBindingClassName(targetClassName);\r
+ Class<?> c = map.get(bindingClassName);\r
+ if ( c!= null) return c;\r
+ \r
+ try {\r
+ ClassInfo ci = ClassInfo.getInfo( targetClass );\r
+ byte[] data = createBindingClass( ci, bindingClassName );\r
+ Class<?> bindingClass = defineClass( bindingClassName, data, 0, data.length );\r
+ map.put(bindingClassName, bindingClass);\r
+ return bindingClass;\r
+ } catch (BindingConstructionException e) {\r
+ throw new ClassNotFoundException( e.getMessage(), e.getCause() );\r
+ } \r
+ \r
+ }\r
+\r
+ public byte[] createBindingClass(ClassInfo ci, String bindingClassName)\r
+ {\r
+ //System.out.println("BindingFactory: "+bindingClassName+" (for "+ci.clazz.getClassLoader()+")");\r
+ int count = ci.fields.length;\r
+ ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS );\r
+ ClassVisitor cv = cw;//new CheckClassAdapter(cw);\r
+ \r
+ FieldVisitor fv;\r
+ MethodVisitor mv;\r
+ AnnotationVisitor av0; \r
+ \r
+ String className = ci.clazz.getName().replaceAll("\\.", "/"); \r
+ bindingClassName = bindingClassName.replaceAll("\\.", "/");\r
+ Object[] classNameX = new Object[] {className};\r
+ String signature = "L"+bindingClassName+";";\r
+ \r
+ // Constructor\r
+ String superClass = "org/simantics/databoard/binding/reflection/ClassBinding";\r
+ cv.visit(V1_6, ACC_PUBLIC + ACC_SUPER, bindingClassName, null, superClass, null); \r
+\r
+ // Constructor\r
+ {\r
+ mv = cv.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/simantics/databoard/type/RecordType;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingConstructionException" });\r
+ \r
+ mv.visitCode();\r
+ Label l0 = new Label(); \r
+ mv.visitLabel(l0);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitLdcInsn(Type.getType("L"+className+";")); \r
+ mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "(Ljava/lang/Class;)V");\r
+ \r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitFieldInsn(PUTFIELD, bindingClassName, "type", "Lorg/simantics/databoard/type/Datatype;");\r
+\r
+ Label l2 = new Label();\r
+ mv.visitLabel(l2);\r
+ mv.visitInsn(RETURN);\r
+\r
+ Label l3 = new Label();\r
+ mv.visitLabel(l3);\r
+ mv.visitLocalVariable("this", signature, null, l0, l3, 0);\r
+ mv.visitLocalVariable("type", "Lorg/simantics/databoard/type/RecordType;", null, l0, l3, 1);\r
+ mv.visitMaxs(2, 2);\r
+ mv.visitEnd();\r
+ }\r
+ \r
+ // getComponent\r
+ {\r
+ mv = cv.visitMethod(ACC_PUBLIC, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitTypeInsn(CHECKCAST, className);\r
+ mv.visitVarInsn(ASTORE, 3);\r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+\r
+ Label caseLabels[] = createFieldLabels( ci );\r
+ Label elseLabel = new Label();\r
+ \r
+ if ( count > 0 ) {\r
+ // Switch\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitTableSwitchInsn(0, count-1, elseLabel, caseLabels);\r
+ \r
+ // case i: x.field = value[i]\r
+ for (int i=0; i<count; i++) {\r
+ Label label = caseLabels[i];\r
+ Field field = ci.fields[i];\r
+ String fieldName = field.getName();\r
+ Class<?> fieldClass = ci.fields[i].getType();\r
+ String typeDescriptor = toTypeDescriptor( fieldClass );\r
+ \r
+ Method getter = ci.getters[i];\r
+ boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter!=null;\r
+ \r
+ mv.visitLabel( label );\r
+ if ( i==0 ) {\r
+ mv.visitFrame(Opcodes.F_APPEND,1, classNameX, 0, null);\r
+ } else {\r
+ mv.visitFrame(Opcodes.F_SAME,0, null, 0, null);\r
+ }\r
+ \r
+ // Read instance argument\r
+ mv.visitVarInsn(ALOAD, 3);\r
+ \r
+ if ( useGetter ) {\r
+ // call getField\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()"+typeDescriptor);\r
+ } else {\r
+ // Read field\r
+ mv.visitFieldInsn(GETFIELD, className, fieldName, typeDescriptor);\r
+ }\r
+ \r
+ // Box \r
+ box(mv, fieldClass);\r
+ \r
+ mv.visitInsn(ARETURN);\r
+ }\r
+ \r
+ }\r
+ \r
+ mv.visitLabel(elseLabel);\r
+ if (count>0) {\r
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+ } \r
+ mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
+ mv.visitInsn(DUP);\r
+ mv.visitLdcInsn("Illegal field index");\r
+ mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
+ mv.visitInsn(ATHROW); \r
+ \r
+ // End \r
+ Label l19 = new Label();\r
+ mv.visitLabel(l19);\r
+ mv.visitLocalVariable("this", "L"+className+";", null, l0, l19, 0);\r
+ mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l19, 1);\r
+ mv.visitLocalVariable("index", "I", null, l0, l19, 2);\r
+ //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, l1, l19, 3);\r
+ mv.visitMaxs(3, 4);\r
+ mv.visitEnd();\r
+ }\r
+ \r
+ // Create\r
+ {\r
+ mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+ if ( ci.beanConstructor != null ) {\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitTypeInsn(NEW, className);\r
+ mv.visitInsn(DUP);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");\r
+ mv.visitVarInsn(ASTORE, 2);\r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 2);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V");\r
+ Label l2 = new Label();\r
+ mv.visitLabel(l2);\r
+ mv.visitVarInsn(ALOAD, 2);\r
+ mv.visitInsn(ARETURN);\r
+ Label l3 = new Label();\r
+ mv.visitLabel(l3);\r
+ mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l3, 0);\r
+ mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);\r
+ //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);\r
+ mv.visitMaxs(3, 3);\r
+ mv.visitEnd(); \r
+ } else if ( ci.argsConstructor != null ) {\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitTypeInsn(NEW, className);\r
+ mv.visitInsn(DUP);\r
+ \r
+ String constArgsDescriptor = "(";\r
+ Class<?>[] args = ci.argsConstructor.getParameterTypes();\r
+ for (int i=0; i<count; i++) {\r
+ Label label = new Label();\r
+ Class<?> field = args[i];\r
+ String fieldName = field.getName();\r
+ Method getter = ci.getters[i];\r
+ Class<?> fieldClass = ci.fields[i].getType();\r
+ Class<?> boxClass = getBoxClass(fieldClass);\r
+ String typeDescriptor = toTypeDescriptor( fieldClass );\r
+ String boxTypeDescriptor = toTypeDescriptor( boxClass );\r
+ constArgsDescriptor += typeDescriptor;\r
+ \r
+ mv.visitLabel(label);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ if (i<6) {\r
+ mv.visitInsn(ICONST_0 + i);\r
+ } else {\r
+ mv.visitIntInsn(BIPUSH, i); \r
+ }\r
+\r
+ mv.visitInsn(AALOAD);\r
+ mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));\r
+ unbox(mv, fieldClass); \r
+ }\r
+\r
+ Label l17 = new Label();\r
+ mv.visitLabel(l17);\r
+ constArgsDescriptor += ")V";\r
+ mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", constArgsDescriptor);\r
+ mv.visitInsn(ARETURN);\r
+ Label l18 = new Label();\r
+ mv.visitLabel(l18);\r
+ mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l18, 0);\r
+ mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l18, 1);\r
+ mv.visitMaxs(21, 2);\r
+ mv.visitEnd();\r
+ \r
+ } else {\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitTypeInsn(NEW, className);\r
+ mv.visitInsn(DUP);\r
+ mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");\r
+ mv.visitVarInsn(ASTORE, 2);\r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 2);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V");\r
+ Label l2 = new Label();\r
+ mv.visitLabel(l2);\r
+ mv.visitVarInsn(ALOAD, 2);\r
+ mv.visitInsn(ARETURN);\r
+ Label l3 = new Label();\r
+ mv.visitLabel(l3);\r
+ mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l3, 0);\r
+ mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);\r
+ //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);\r
+ mv.visitMaxs(3, 3);\r
+ mv.visitEnd(); \r
+ }\r
+ }\r
+ \r
+ // CreatePartial\r
+ mv = cv.visitMethod(ACC_PUBLIC, "createPartial", "()Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+ if (ci.beanConstructor!=null)\r
+ { \r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitTypeInsn(NEW, className);\r
+ mv.visitInsn(DUP);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");\r
+ mv.visitInsn(ARETURN);\r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+ mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l1, 0);\r
+ mv.visitMaxs(3, 1);\r
+ mv.visitEnd(); \r
+ } else if (ci.noArgsConstructor != null)\r
+ {\r
+ // return new MyClass();\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitTypeInsn(NEW, className);\r
+ mv.visitInsn(DUP);\r
+ mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");\r
+ mv.visitInsn(ARETURN);\r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+ mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l1, 0);\r
+ mv.visitMaxs(2, 1);\r
+ mv.visitEnd(); \r
+ } else {\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitIntInsn(BIPUSH, count);\r
+ mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");\r
+ mv.visitVarInsn(ASTORE, 1);\r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+ mv.visitInsn(ICONST_0);\r
+ mv.visitVarInsn(ISTORE, 2);\r
+ Label l2 = new Label();\r
+ mv.visitLabel(l2);\r
+ Label l3 = new Label();\r
+ mv.visitJumpInsn(GOTO, l3);\r
+ Label l4 = new Label();\r
+ mv.visitLabel(l4);\r
+ mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"[Ljava/lang/Object;", Opcodes.INTEGER}, 0, null);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitInsn(AALOAD);\r
+ mv.visitVarInsn(ASTORE, 3);\r
+ Label l5 = new Label();\r
+ mv.visitLabel(l5);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitVarInsn(ALOAD, 3);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/Binding", "createDefault", "()Ljava/lang/Object;");\r
+ mv.visitInsn(AASTORE);\r
+ Label l6 = new Label();\r
+ mv.visitLabel(l6);\r
+ mv.visitIincInsn(2, 1);\r
+ mv.visitLabel(l3);\r
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitInsn(ARRAYLENGTH);\r
+ mv.visitJumpInsn(IF_ICMPLT, l4);\r
+ Label l7 = new Label();\r
+ mv.visitLabel(l7);\r
+ mv.visitLineNumber(109, l7);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "create", "([Ljava/lang/Object;)Ljava/lang/Object;");\r
+ mv.visitInsn(ARETURN);\r
+ Label l8 = new Label();\r
+ mv.visitLabel(l8);\r
+ mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l8, 0);\r
+ mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l1, l8, 1);\r
+ mv.visitLocalVariable("i", "I", null, l2, l7, 2);\r
+ mv.visitLocalVariable("fb", "Lorg/simantics/databoard/binding/Binding;", null, l5, l6, 3);\r
+ mv.visitMaxs(3, 4);\r
+ mv.visitEnd(); \r
+ }\r
+ \r
+ // setComponent\r
+ {\r
+ mv = cv.visitMethod(ACC_PUBLIC, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitTypeInsn(CHECKCAST, className);\r
+ mv.visitVarInsn(ASTORE, 4);\r
+ Label endLabel = new Label();\r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+ \r
+ Label elseLabel = new Label();\r
+ Label labels[] = new Label[ count ]; \r
+ for (int i=0; i<count; i++) labels[i] = new Label();\r
+ \r
+ if (count>0) {\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitTableSwitchInsn(0, count-1, elseLabel, labels);\r
+ \r
+ for (int i=0; i<count; i++) {\r
+ Label label = labels[ i ];\r
+ mv.visitLabel(label);\r
+ Field field = ci.fields[i];\r
+ String fieldName = field.getName();\r
+ Class<?> fieldClass = ci.fields[i].getType();\r
+ Class<?> boxClass = getBoxClass(fieldClass);\r
+ String typeDescriptor = toTypeDescriptor( fieldClass );\r
+ String boxTypeDescriptor = toTypeDescriptor( boxClass );\r
+ \r
+ Method setter = ci.setters[i];\r
+ Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;\r
+ boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;\r
+ \r
+ if (i==0) {\r
+ mv.visitFrame(Opcodes.F_APPEND,1, classNameX, 0, null);\r
+ } else {\r
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+ }\r
+ mv.visitVarInsn(ALOAD, 4);\r
+ mv.visitVarInsn(ALOAD, 3);\r
+ mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));\r
+ \r
+ if (useSetter) {\r
+ unbox(mv, setterClass);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");\r
+ } else {\r
+ unbox(mv, fieldClass);\r
+ mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor); \r
+ }\r
+ mv.visitInsn(RETURN);\r
+ }\r
+ }\r
+ \r
+ mv.visitLabel(elseLabel);\r
+ mv.visitLineNumber(178, elseLabel);\r
+ if (count>0) {\r
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+ } \r
+ mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
+ mv.visitInsn(DUP);\r
+ mv.visitLdcInsn("Illegal field index");\r
+ mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
+ mv.visitInsn(ATHROW);\r
+\r
+ mv.visitLabel(endLabel);\r
+ mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, endLabel, 0);\r
+ mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);\r
+ mv.visitLocalVariable("index", "I", null, l0, endLabel, 2);\r
+ mv.visitLocalVariable("value", "Ljava/lang/Object;", null, l0, endLabel, 3);\r
+ //mv.visitLocalVariable("x", "L"+className+";", null, l1, endLabel, 4);\r
+ mv.visitMaxs(3, 5);\r
+ mv.visitEnd(); \r
+ }\r
+ \r
+ // IsImmutable\r
+ {\r
+ mv = cv.visitMethod(ACC_PUBLIC, "isImmutable", "()Z", null, null);\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitInsn(ICONST_0);\r
+ mv.visitInsn(IRETURN);\r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+ mv.visitLocalVariable("this", "L"+className+";", null, l0, l1, 0);\r
+ mv.visitMaxs(1, 1);\r
+ mv.visitEnd();\r
+ }\r
+\r
+ // IsInstance\r
+ {\r
+ mv = cv.visitMethod(ACC_PUBLIC, "isInstance", "(Ljava/lang/Object;)Z", null, null);\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitTypeInsn(INSTANCEOF, className);\r
+ mv.visitInsn(IRETURN);\r
+ Label l1 = new Label();\r
+ mv.visitLabel(l1);\r
+ mv.visitLocalVariable("this", "L"+className+";", null, l0, l1, 0);\r
+ mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l1, 1);\r
+ mv.visitMaxs(1, 2);\r
+ mv.visitEnd();\r
+ }\r
+\r
+ // SetComponents\r
+ { \r
+ mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+ mv.visitCode();\r
+ Label l0 = new Label();\r
+ mv.visitLabel(l0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitTypeInsn(CHECKCAST, className);\r
+ mv.visitVarInsn(ASTORE, 3);\r
+ Label firstLabel = l0;\r
+ \r
+ for (int i=0; i<count; i++) {\r
+ Label label = new Label();\r
+ if (firstLabel==l0) firstLabel = label;\r
+ Field field = ci.fields[i];\r
+ String fieldName = field.getName();\r
+ Class<?> fieldClass = ci.fields[i].getType();\r
+ Class<?> boxClass = getBoxClass(fieldClass);\r
+ String typeDescriptor = toTypeDescriptor( fieldClass );\r
+ String boxTypeDescriptor = toTypeDescriptor( boxClass );\r
+\r
+ Method setter = ci.setters[i];\r
+ Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;\r
+ boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;\r
+ \r
+ mv.visitLabel(label);\r
+ mv.visitVarInsn(ALOAD, 3);\r
+ mv.visitVarInsn(ALOAD, 2);\r
+ if (i<6) {\r
+ mv.visitInsn(ICONST_0 + i);\r
+ } else {\r
+ mv.visitIntInsn(BIPUSH, i); \r
+ }\r
+ mv.visitInsn(AALOAD);\r
+ mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));\r
+ \r
+ if (useSetter) {\r
+ unbox(mv, setterClass);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");\r
+ } else {\r
+ unbox(mv, fieldClass);\r
+ mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);\r
+ }\r
+ \r
+ }\r
+ Label l17 = new Label();\r
+ mv.visitLabel(l17);\r
+ mv.visitInsn(RETURN);\r
+ Label endLabel = new Label();\r
+ mv.visitLabel(endLabel);\r
+ mv.visitLocalVariable("this", "L"+className+";", null, l0, endLabel, 0);\r
+ mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);\r
+ mv.visitLocalVariable("value", "[Ljava/lang/Object;", null, l0, endLabel, 2);\r
+ //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, firstLabel, endLabel, 3);\r
+ mv.visitMaxs(3, 4);\r
+ mv.visitEnd();\r
+ }\r
+ \r
+ // Add primitive setters\r
+ {\r
+ addGetSetPrimitive(ci, cv, "Boolean", "Z", bindingClassName);\r
+ addGetSetPrimitive(ci, cv, "Byte", "B", bindingClassName);\r
+ addGetSetPrimitive(ci, cv, "Int", "I", bindingClassName);\r
+ addGetSetPrimitive(ci, cv, "Long", "J", bindingClassName);\r
+ addGetSetPrimitive(ci, cv, "Float", "F", bindingClassName);\r
+ addGetSetPrimitive(ci, cv, "Double", "D", bindingClassName);\r
+ }\r
+ \r
+ cv.visitEnd();\r
+ return cw.toByteArray();\r
+ }\r
+ \r
+ private void addGetSetPrimitive(ClassInfo ci, ClassVisitor cv, String setterName, String signature, String bindingClassName)\r
+ {\r
+ String className = ci.clazz.getName().replaceAll("\\.", "/");\r
+ \r
+ Label firstLabel = new Label();\r
+ Label secondLabel = new Label();\r
+ Label errorLabel = new Label();\r
+ Label exitLabel = new Label();\r
+ Label lastLabel = new Label();\r
+ \r
+ boolean oneByte = !signature.equals("J") && !signature.equals("D");\r
+ \r
+ int c = 0;\r
+ for (Field f : ci.fields) {\r
+ if ( toTypeDescriptor(getPrimitiveClass(f.getType())).equals( signature ) ) c++; \r
+ }\r
+ \r
+ int[] indices = new int[ c ];\r
+ Label[] caseLabel = new Label[ c ];\r
+\r
+ c = 0;\r
+ for (int i=0; i<ci.fields.length; i++) \r
+ {\r
+ Class<?> fieldClass = ci.fields[i].getType();\r
+ fieldClass = getPrimitiveClass(fieldClass);\r
+ String s = toTypeDescriptor(fieldClass);\r
+ if ( !s.equals( signature ) ) continue;\r
+ \r
+ indices[c] = i;\r
+ caseLabel[c] = new Label();\r
+ c++;\r
+ }\r
+ \r
+ //////////////////\r
+ /// Setter\r
+ ///\r
+ MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "set"+setterName, "(Ljava/lang/Object;I"+signature+")V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+ mv.visitCode();\r
+ mv.visitLabel(firstLabel);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitTypeInsn(CHECKCAST, className);\r
+ mv.visitVarInsn(ASTORE, oneByte?4:5);\r
+\r
+ mv.visitLabel(secondLabel);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+\r
+ // switch\r
+ mv.visitLookupSwitchInsn(errorLabel, indices, caseLabel);\r
+\r
+ // case 1:\r
+ if ( c>0 ) {\r
+ for (int i=0; i<c; i++) {\r
+ int index = indices[i];\r
+ Method setter = ci.setters[index];\r
+ Field field = ci.fields[index];\r
+ Class<?> fieldClass = field.getType();\r
+ Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;\r
+ boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;\r
+ String typeDescriptor = toTypeDescriptor( useSetter ? setterClass : fieldClass );\r
+ \r
+ mv.visitLabel(caseLabel[i]);\r
+ if ( i == 0 ) {\r
+ mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {className}, 0, null);\r
+ } else {\r
+ mv.visitFrame(Opcodes.F_SAME, 0, new Object[] {className}, 0, null);\r
+ }\r
+ if ( signature.equals("F") ) {\r
+ mv.visitVarInsn(ALOAD, 4);\r
+ mv.visitVarInsn(FLOAD, 3);\r
+ } else if ( signature.equals("D") ) {\r
+ mv.visitVarInsn(ALOAD, 5);\r
+ mv.visitVarInsn(DLOAD, 3);\r
+ } else if ( signature.equals("J") ) {\r
+ mv.visitVarInsn(ALOAD, 5);\r
+ mv.visitVarInsn(LLOAD, 3);\r
+ } else {\r
+ mv.visitVarInsn(ALOAD, 4);\r
+ mv.visitVarInsn(ILOAD, 3);\r
+ }\r
+ \r
+ if ( useSetter ) {\r
+ boxTo(mv, setterClass);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");\r
+ } else {\r
+ boxTo(mv, fieldClass);\r
+ mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);\r
+ }\r
+ mv.visitJumpInsn(GOTO, exitLabel);\r
+ }\r
+ } else {\r
+ mv.visitInsn(POP); \r
+ }\r
+\r
+ // default: (error)\r
+ /*\r
+ mv.visitLabel(errorLabel);\r
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+ mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
+ mv.visitInsn(DUP);\r
+ mv.visitLdcInsn("Field is not "+setterName);\r
+ mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
+ mv.visitInsn(ATHROW);\r
+ */\r
+ \r
+ // default: setComponent\r
+ mv.visitLabel(errorLabel);\r
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitInsn(AALOAD);\r
+ if ( signature.equals("F") ) {\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/FloatBinding");\r
+ mv.visitVarInsn(FLOAD, 3);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/FloatBinding", "create", "(F)Ljava/lang/Object;");\r
+ } else if ( signature.equals("D") ) {\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/DoubleBinding");\r
+ mv.visitVarInsn(DLOAD, 3);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/DoubleBinding", "create", "(D)Ljava/lang/Object;");\r
+ } else if ( signature.equals("J") ) {\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/LongBinding");\r
+ mv.visitVarInsn(LLOAD, 3);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/LongBinding", "create", "(J)Ljava/lang/Object;");\r
+ } else if ( signature.equals("Z") ){\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/BooleanBinding");\r
+ mv.visitVarInsn(ILOAD, 3);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/BooleanBinding", "create", "(Z)Ljava/lang/Object;");\r
+ } else if ( signature.equals("I") ){\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/IntBinding");\r
+ mv.visitVarInsn(ILOAD, 3);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/IntBinding", "create", "(I)Ljava/lang/Object;");\r
+ } else if ( signature.equals("B") ){\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/ByteBinding");\r
+ mv.visitVarInsn(ILOAD, 3);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/ByteBinding", "create", "(B)Ljava/lang/Object;");\r
+ } \r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V");\r
+\r
+ // return\r
+ mv.visitLabel(exitLabel);\r
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+ mv.visitInsn(RETURN);\r
+\r
+ // Something at the end\r
+ mv.visitLabel(lastLabel);\r
+// mv.visitLocalVariable("this", "L"+bindingClassName+";", null, firstLabel, lastLabel, 0);\r
+// mv.visitLocalVariable("r", "Ljava/lang/Object;", null, firstLabel, lastLabel, 1);\r
+// mv.visitLocalVariable("index", "I", null, firstLabel, lastLabel, 2);\r
+// mv.visitLocalVariable("z", signature, null, firstLabel, lastLabel, 3);\r
+// mv.visitLocalVariable("x", "L"+className+";", null, secondLabel, lastLabel, 4);\r
+ mv.visitMaxs(oneByte?5:6, oneByte?5:6);\r
+ mv.visitEnd();\r
+ \r
+ \r
+ //////////////////\r
+ /// Getter\r
+ ///\r
+ firstLabel = new Label();\r
+ secondLabel = new Label();\r
+ errorLabel = new Label();\r
+ exitLabel = new Label();\r
+ lastLabel = new Label();\r
+ for (int i=0; i<c; i++) caseLabel[i] = new Label();\r
+ mv = cv.visitMethod(ACC_PUBLIC, "get"+setterName, "(Ljava/lang/Object;I)"+signature, null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+ mv.visitCode();\r
+ mv.visitLabel(firstLabel);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitTypeInsn(CHECKCAST, className);\r
+ mv.visitVarInsn(ASTORE, 3);\r
+\r
+ mv.visitLabel(secondLabel);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+\r
+ // switch\r
+ if ( c>0 ) {\r
+ mv.visitLookupSwitchInsn(errorLabel, indices, caseLabel);\r
+ \r
+ // case i:\r
+ for (int i=0; i<c; i++) {\r
+ int index = indices[i];\r
+ Method getter = ci.getters[index];\r
+ Field field = ci.fields[index];\r
+ Class<?> fieldClass = field.getType();\r
+ Class<?> getterClass = getter!=null?getter.getReturnType():null;\r
+ boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter!=null;\r
+ String typeDescriptor = toTypeDescriptor( useGetter ? getterClass : fieldClass );\r
+ \r
+ mv.visitLabel(caseLabel[i]);\r
+ if ( i == 0 ) {\r
+ mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {className}, 0, null);\r
+ } else {\r
+ mv.visitFrame(Opcodes.F_SAME, 0, new Object[] {className}, 0, null);\r
+ }\r
+ \r
+ mv.visitVarInsn(ALOAD, 3);\r
+ \r
+ if ( useGetter ) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()"+typeDescriptor);\r
+ unboxFrom(mv, getterClass);\r
+ } else {\r
+ mv.visitFieldInsn(GETFIELD, className, field.getName(), typeDescriptor);\r
+ unboxFrom(mv, fieldClass);\r
+ }\r
+ \r
+ if ( signature.equals("F") ) {\r
+ mv.visitInsn(FRETURN);\r
+ } else if ( signature.equals("D") ) {\r
+ mv.visitInsn(DRETURN);\r
+ } else if ( signature.equals("J") ) {\r
+ mv.visitInsn(LRETURN);\r
+ } else {\r
+ mv.visitInsn(IRETURN);\r
+ }\r
+ }\r
+ } else {\r
+ mv.visitInsn(POP); \r
+ }\r
+\r
+ // default: (error)\r
+ /*\r
+ mv.visitLabel(errorLabel);\r
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+ mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
+ mv.visitInsn(DUP);\r
+ mv.visitLdcInsn("Field is not "+setterName);\r
+ mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
+ mv.visitInsn(ATHROW);\r
+ */\r
+ \r
+ // default:\r
+ mv.visitLabel(errorLabel);\r
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitInsn(AALOAD);\r
+ if ( signature.equals("Z") ) {\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/BooleanBinding");\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/BooleanBinding", "getValue_", "(Ljava/lang/Object;)Z");\r
+ mv.visitInsn(IRETURN);\r
+ } else if ( signature.equals("B") ) {\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/ByteBinding");\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/ByteBinding", "getValue_", "(Ljava/lang/Object;)B");\r
+ mv.visitInsn(IRETURN);\r
+ } else if ( signature.equals("I") ) {\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/IntBinding");\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/IntBinding", "getValue_", "(Ljava/lang/Object;)I");\r
+ mv.visitInsn(IRETURN);\r
+ } else if ( signature.equals("J") ) {\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/LongBinding");\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/LongBinding", "getValue_", "(Ljava/lang/Object;)J");\r
+ mv.visitInsn(LRETURN);\r
+ } else if ( signature.equals("F") ) {\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/FloatBinding");\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/FloatBinding", "getValue_", "(Ljava/lang/Object;)F");\r
+ mv.visitInsn(FRETURN);\r
+ } else if ( signature.equals("D") ) {\r
+ mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/DoubleBinding");\r
+ mv.visitVarInsn(ALOAD, 0);\r
+ mv.visitVarInsn(ALOAD, 1);\r
+ mv.visitVarInsn(ILOAD, 2);\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/DoubleBinding", "getValue_", "(Ljava/lang/Object;)D");\r
+ mv.visitInsn(DRETURN);\r
+ } \r
+\r
+ // Something at the end\r
+ mv.visitLabel(lastLabel);\r
+// mv.visitLocalVariable("this", "Lorg/simantics/databoard/binding/reflection/MyBinding;", null, firstLabel, lastLabel, 0);\r
+// mv.visitLocalVariable("r", "Ljava/lang/Object;", null, firstLabel, lastLabel, 1);\r
+// mv.visitLocalVariable("index", "I", null, firstLabel, lastLabel, 2);\r
+// mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, secondLabel, lastLabel, 3);\r
+ mv.visitMaxs(4, 4);\r
+ mv.visitEnd(); \r
+ \r
+ }\r
+\r
+\r
+ public static Label[] createFieldLabels(ClassInfo ci) \r
+ {\r
+ Label caseLabels[] = new Label[ ci.fields.length ];\r
+ for (int i=0; i<ci.fields.length; i++) caseLabels[i] = new Label();\r
+ return caseLabels;\r
+ }\r
+ \r
+ public static String toTypeDescriptor(Class<?> clazz) {\r
+ if (clazz==void.class) return "V";\r
+ if (clazz==boolean.class) return "Z";\r
+ if (clazz==char.class) return "C";\r
+ if (clazz==byte.class) return "B";\r
+ if (clazz==short.class) return "S";\r
+ if (clazz==int.class) return "I";\r
+ if (clazz==float.class) return "F";\r
+ if (clazz==long.class) return "J";\r
+ if (clazz==double.class) return "D";\r
+ if (clazz.isArray()) return clazz.getName().replaceAll("\\.", "/"); \r
+ return "L"+clazz.getName().replaceAll("\\.", "/")+";";\r
+ }\r
+ \r
+ /**\r
+ * Get respective boxed class\r
+ * @param clazz\r
+ * @return box-class\r
+ */\r
+ public static Class<?> getBoxClass(Class<?> clazz) {\r
+ if (clazz==void.class) return null;\r
+ if (clazz==boolean.class) return Boolean.class;\r
+ if (clazz==char.class) return Character.class;\r
+ if (clazz==byte.class) return Byte.class;\r
+ if (clazz==short.class) return Short.class;\r
+ if (clazz==int.class) return Integer.class;\r
+ if (clazz==float.class) return Float.class;\r
+ if (clazz==long.class) return Long.class;\r
+ if (clazz==double.class) return Double.class;\r
+ return clazz;\r
+ }\r
+ \r
+ /**\r
+ * Get respective primitive class\r
+ * @param clazz\r
+ * @return primitive-class\r
+ */\r
+ public static Class<?> getPrimitiveClass(Class<?> clazz) {\r
+ if (clazz==Boolean.class) return boolean.class;\r
+ if (clazz==Character.class) return char.class;\r
+ if (clazz==Byte.class) return byte.class;\r
+ if (clazz==Short.class) return short.class;\r
+ if (clazz==Integer.class) return int.class;\r
+ if (clazz==Float.class) return float.class;\r
+ if (clazz==Long.class) return long.class;\r
+ if (clazz==Double.class) return double.class;\r
+ return clazz;\r
+ } \r
+ \r
+ public static boolean isPrimitive(Class<?> clazz) {\r
+ return clazz==boolean.class || clazz==char.class || clazz==byte.class ||\r
+ clazz==short.class || clazz==int.class || clazz==float.class ||\r
+ clazz==long.class || clazz==double.class;\r
+ }\r
+ \r
+ public static void unbox(MethodVisitor mv, Class<?> clazz) {\r
+ if (clazz==boolean.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");\r
+ } else if (clazz==char.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); // C?\r
+ } else if (clazz==byte.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");\r
+ } else if (clazz==short.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");\r
+ } else if (clazz==int.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");\r
+ } else if (clazz==float.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");\r
+ } else if (clazz==long.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");\r
+ } else if (clazz==double.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");\r
+ } \r
+ }\r
+\r
+ public static void box(MethodVisitor mv, Class<?> clazz) {\r
+ if (clazz==boolean.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); \r
+ } else if (clazz==char.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); \r
+ } else if (clazz==byte.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"); \r
+ } else if (clazz==short.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"); \r
+ } else if (clazz==int.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); \r
+ } else if (clazz==float.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); \r
+ } else if (clazz==long.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;"); \r
+ } else if (clazz==double.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); \r
+ } \r
+ }\r
+ \r
+ public static void boxTo(MethodVisitor mv, Class<?> clazz) {\r
+ if (clazz==Boolean.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); \r
+ } else if (clazz==Character.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); \r
+ } else if (clazz==Byte.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"); \r
+ } else if (clazz==Short.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"); \r
+ } else if (clazz==Integer.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); \r
+ } else if (clazz==Float.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); \r
+ } else if (clazz==Long.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;"); \r
+ } else if (clazz==Double.class) {\r
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); \r
+ } \r
+ }\r
+ \r
+ public static void unboxFrom(MethodVisitor mv, Class<?> clazz) {\r
+ if (clazz==Boolean.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");\r
+ } else if (clazz==Character.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); // C?\r
+ } else if (clazz==Byte.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");\r
+ } else if (clazz==Short.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");\r
+ } else if (clazz==Integer.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");\r
+ } else if (clazz==Float.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");\r
+ } else if (clazz==Long.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");\r
+ } else if (clazz==Double.class) {\r
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");\r
+ } \r
+ } \r
+ \r
+ \r
+ public static String toClassCanonicalName(Class<?> clazz)\r
+ {\r
+ return clazz.getName().replaceAll("\\.", "/");\r
+ }\r
+\r
+ \r
+ \r
+}\r