]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/AsmBindingClassLoader.java
Fixing several binding-related bugs
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / reflection / AsmBindingClassLoader.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2011 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.binding.reflection;
13
14 import java.lang.reflect.Field;
15 import java.lang.reflect.Method;
16 import java.lang.reflect.Modifier;
17 import java.util.HashMap;
18 import java.util.Map;
19
20 import org.objectweb.asm.AnnotationVisitor;
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.ClassWriter;
23 import org.objectweb.asm.FieldVisitor;
24 import org.objectweb.asm.Label;
25 import org.objectweb.asm.MethodVisitor;
26 import org.objectweb.asm.Opcodes;
27 import org.objectweb.asm.Type;
28 import org.simantics.databoard.binding.error.BindingConstructionException;
29
30 public class AsmBindingClassLoader extends ClassLoader implements Opcodes {
31
32         Map<String, Class<?>> map = new HashMap<String, Class<?>>();
33         
34         public AsmBindingClassLoader() {
35                 super(Thread.currentThread().getContextClassLoader());
36         }
37
38         public AsmBindingClassLoader(ClassLoader parent) {
39                 super(parent);
40         }       
41         
42         public String toBindingClassName( String targetClassName )
43         {
44                 if ( targetClassName.startsWith("java" ) ) {
45                         return "x"+targetClassName+".Binding";
46                 }
47                 return targetClassName+".Binding";
48         }
49         
50         public String toTargetClassName( String bindingClassName )
51         {
52                 if (!bindingClassName.endsWith(".Binding")) return null;
53                 if (bindingClassName.substring(1,5).equals("java")) {
54                         return bindingClassName.substring(1, bindingClassName.length()-8);
55                 } else {
56                         return bindingClassName.substring(0, bindingClassName.length()-8);
57                 }
58         }
59         
60         @Override
61         protected synchronized Class<?> findClass(String bindingClassName) 
62         throws ClassNotFoundException 
63         {
64                 Class<?> c = map.get(bindingClassName);
65                 if ( c!= null) return c;
66                                 
67                 try {
68                         String targetClassName = toTargetClassName(bindingClassName);
69                         if ( targetClassName == null ) {
70 //                              try {
71                                         return super.findClass(bindingClassName);
72 //                              } catch( ClassNotFoundException e ) {
73 //                                      e.printStackTrace();
74 //                                      throw e;
75 //                              }
76                         }
77                         
78                         ClassLoader cl = getParent();
79                         if (cl==null) { 
80                                 cl = Thread.currentThread().getContextClassLoader();
81                         }
82                         Class<?> targetClass = cl.loadClass( targetClassName );
83                         ClassInfo ci = ClassInfo.getInfo( targetClass );
84                         byte[] data = createBindingClass( ci, bindingClassName );
85                         Class<?> bindingClass = defineClass( bindingClassName, data, 0, data.length );
86                         map.put(bindingClassName, bindingClass);
87                         return bindingClass;
88                 } catch (BindingConstructionException e) {
89                         throw new ClassNotFoundException( e.getMessage(), e.getCause() );
90                 }               
91         }       
92         
93         public synchronized Class<?> getBindingClass(Class<?> targetClass)
94         throws ClassNotFoundException
95         {
96                 String targetClassName = targetClass.getName();
97                 String bindingClassName = toBindingClassName(targetClassName);
98                 Class<?> c = map.get(bindingClassName);
99                 if ( c!= null) return c;
100                                 
101                 try {
102                         ClassInfo ci = ClassInfo.getInfo( targetClass );
103                         byte[] data = createBindingClass( ci, bindingClassName );
104                         Class<?> bindingClass = defineClass( bindingClassName, data, 0, data.length );
105                         map.put(bindingClassName, bindingClass);
106                         return bindingClass;
107                 } catch (BindingConstructionException e) {
108                         throw new ClassNotFoundException( e.getMessage(), e.getCause() );
109                 }               
110                 
111         }
112
113         public byte[] createBindingClass(ClassInfo ci, String bindingClassName)
114         {
115                 //System.out.println("BindingFactory: "+bindingClassName+" (for "+ci.clazz.getClassLoader()+")");
116                 int count = ci.fields.length;
117                 ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS );
118                 ClassVisitor cv = cw;//new CheckClassAdapter(cw);
119                 
120                 FieldVisitor fv;
121                 MethodVisitor mv;
122                 AnnotationVisitor av0;          
123         
124                 String className = ci.clazz.getName().replaceAll("\\.", "/");           
125                 bindingClassName = bindingClassName.replaceAll("\\.", "/");
126                 Object[] classNameX = new Object[] {className};
127                 String signature = "L"+bindingClassName+";";
128                 
129                 // Constructor
130                 String superClass = "org/simantics/databoard/binding/reflection/ClassBinding";
131                 cv.visit(V1_6, ACC_PUBLIC + ACC_SUPER, bindingClassName, null, superClass, null);       
132
133                 // Constructor
134                 {
135                         mv = cv.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/simantics/databoard/type/RecordType;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingConstructionException" });
136                         
137                         mv.visitCode();
138                         Label l0 = new Label();                 
139                         mv.visitLabel(l0);
140                         mv.visitVarInsn(ALOAD, 0);
141                         mv.visitLdcInsn(Type.getType("L"+className+";"));                       
142                         mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "(Ljava/lang/Class;)V");
143                         
144                         Label l1 = new Label();
145                         mv.visitLabel(l1);
146                         mv.visitVarInsn(ALOAD, 0);
147                         mv.visitVarInsn(ALOAD, 1);
148                         mv.visitFieldInsn(PUTFIELD, bindingClassName, "type", "Lorg/simantics/databoard/type/Datatype;");
149
150                         Label l2 = new Label();
151                         mv.visitLabel(l2);
152                         mv.visitInsn(RETURN);
153
154                         Label l3 = new Label();
155                         mv.visitLabel(l3);
156                         mv.visitLocalVariable("this", signature, null, l0, l3, 0);
157                         mv.visitLocalVariable("type", "Lorg/simantics/databoard/type/RecordType;", null, l0, l3, 1);
158                         mv.visitMaxs(2, 2);
159                         mv.visitEnd();
160                 }
161                 
162                 // getComponent
163                 {
164                         mv = cv.visitMethod(ACC_PUBLIC, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });
165                         mv.visitCode();
166                         Label l0 = new Label();
167                         mv.visitLabel(l0);
168                         mv.visitVarInsn(ALOAD, 1);
169                         mv.visitTypeInsn(CHECKCAST, className);
170                         mv.visitVarInsn(ASTORE, 3);
171                         Label l1 = new Label();
172                         mv.visitLabel(l1);
173
174                         Label caseLabels[] = createFieldLabels( ci );
175                         Label elseLabel = new Label();
176                         
177                         if ( count > 0 ) {
178                                 // Switch
179                                 mv.visitVarInsn(ILOAD, 2);
180                                 mv.visitTableSwitchInsn(0, count-1, elseLabel, caseLabels);
181                                 
182                                 // case i: x.field = value[i]
183                                 for (int i=0; i<count; i++) {
184                                         Label label = caseLabels[i];
185                                         Field field = ci.fields[i];
186                                         String fieldName = field.getName();
187                                         Class<?> fieldClass = ci.fields[i].getType();
188                                         String typeDescriptor = toTypeDescriptor( fieldClass );
189         
190                                         Method getter = ci.getters[i];
191                                         boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter!=null;
192                                         
193                                         mv.visitLabel( label );
194                                         if ( i==0 ) {
195                                                 mv.visitFrame(Opcodes.F_APPEND,1, classNameX, 0, null);
196                                         } else {
197                                                 mv.visitFrame(Opcodes.F_SAME,0, null, 0, null);
198                                         }
199                                         
200                                         // Read instance argument
201                                         mv.visitVarInsn(ALOAD, 3);
202                                                 
203                                         if ( useGetter ) {
204                                                 // call getField
205                                                 mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()"+typeDescriptor);
206                                         } else {
207                                                 // Read field
208                                                 mv.visitFieldInsn(GETFIELD, className, fieldName, typeDescriptor);
209                                         }
210                                                 
211                                         // Box 
212                                         box(mv, fieldClass);
213                                                 
214                                         mv.visitInsn(ARETURN);
215                                 }
216         
217                         }
218                         
219                         mv.visitLabel(elseLabel);
220                         if (count>0) {
221                                 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
222                         }                       
223                         mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");
224                         mv.visitInsn(DUP);
225                         mv.visitLdcInsn("Illegal field index");
226                         mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");
227                         mv.visitInsn(ATHROW);                   
228                         
229                         // End 
230                         Label l19 = new Label();
231                         mv.visitLabel(l19);
232                         mv.visitLocalVariable("this", "L"+className+";", null, l0, l19, 0);
233                         mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l19, 1);
234                         mv.visitLocalVariable("index", "I", null, l0, l19, 2);
235                         //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, l1, l19, 3);
236                         mv.visitMaxs(3, 4);
237                         mv.visitEnd();
238                 }
239                 
240                 // Create
241                 {
242                         mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });
243                         if ( ci.beanConstructor != null ) {
244                                 mv.visitCode();
245                                 Label l0 = new Label();
246                                 mv.visitLabel(l0);
247                                 mv.visitTypeInsn(NEW, className);
248                                 mv.visitInsn(DUP);
249                                 mv.visitVarInsn(ALOAD, 0);
250                                 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");
251                                 mv.visitVarInsn(ASTORE, 2);
252                                 Label l1 = new Label();
253                                 mv.visitLabel(l1);
254                                 mv.visitVarInsn(ALOAD, 0);
255                                 mv.visitVarInsn(ALOAD, 2);
256                                 mv.visitVarInsn(ALOAD, 1);
257                                 mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V");
258                                 Label l2 = new Label();
259                                 mv.visitLabel(l2);
260                                 mv.visitVarInsn(ALOAD, 2);
261                                 mv.visitInsn(ARETURN);
262                                 Label l3 = new Label();
263                                 mv.visitLabel(l3);
264                                 mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l3, 0);
265                                 mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);
266                                 //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);
267                                 mv.visitMaxs(3, 3);
268                                 mv.visitEnd();                          
269                         } else if ( ci.argsConstructor != null ) {
270                                 mv.visitCode();
271                                 Label l0 = new Label();
272                                 mv.visitLabel(l0);
273                                 mv.visitTypeInsn(NEW, className);
274                                 mv.visitInsn(DUP);
275                                 
276                                 String constArgsDescriptor = "(";
277                                 Class<?>[] args = ci.argsConstructor.getParameterTypes();
278                                 for (int i=0; i<count; i++) {
279                                         Label label = new Label();
280                                         Class<?> field = args[i];
281                                         String fieldName = field.getName();
282                                         Method getter = ci.getters[i];
283                                         Class<?> fieldClass = ci.fields[i].getType();
284                                         Class<?> boxClass = getBoxClass(fieldClass);
285                                         String typeDescriptor = toTypeDescriptor( fieldClass );
286                                         String boxTypeDescriptor = toTypeDescriptor( boxClass );
287                                         constArgsDescriptor += typeDescriptor;
288                                         
289                                         mv.visitLabel(label);
290                                         mv.visitVarInsn(ALOAD, 1);
291                                         if (i<6) {
292                                                 mv.visitInsn(ICONST_0 + i);
293                                         } else {
294                                                 mv.visitIntInsn(BIPUSH, i);                                             
295                                         }
296
297                                         mv.visitInsn(AALOAD);
298                                         mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));
299                                         unbox(mv, fieldClass);                                  
300                                 }
301
302                                 Label l17 = new Label();
303                                 mv.visitLabel(l17);
304                                 constArgsDescriptor += ")V";
305                                 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", constArgsDescriptor);
306                                 mv.visitInsn(ARETURN);
307                                 Label l18 = new Label();
308                                 mv.visitLabel(l18);
309                                 mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l18, 0);
310                                 mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l18, 1);
311                                 mv.visitMaxs(21, 2);
312                                 mv.visitEnd();
313                                 
314                         } else {
315                                 mv.visitCode();
316                                 Label l0 = new Label();
317                                 mv.visitLabel(l0);
318                                 mv.visitTypeInsn(NEW, className);
319                                 mv.visitInsn(DUP);
320                                 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");
321                                 mv.visitVarInsn(ASTORE, 2);
322                                 Label l1 = new Label();
323                                 mv.visitLabel(l1);
324                                 mv.visitVarInsn(ALOAD, 0);
325                                 mv.visitVarInsn(ALOAD, 2);
326                                 mv.visitVarInsn(ALOAD, 1);
327                                 mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V");
328                                 Label l2 = new Label();
329                                 mv.visitLabel(l2);
330                                 mv.visitVarInsn(ALOAD, 2);
331                                 mv.visitInsn(ARETURN);
332                                 Label l3 = new Label();
333                                 mv.visitLabel(l3);
334                                 mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l3, 0);
335                                 mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);
336                                 //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);
337                                 mv.visitMaxs(3, 3);
338                                 mv.visitEnd();                          
339                         }
340                 }
341                 
342                 // CreatePartial
343                 mv = cv.visitMethod(ACC_PUBLIC, "createPartial", "()Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });
344                 if (ci.beanConstructor!=null)
345                 { 
346                         mv.visitCode();
347                         Label l0 = new Label();
348                         mv.visitLabel(l0);
349                         mv.visitTypeInsn(NEW, className);
350                         mv.visitInsn(DUP);
351                         mv.visitVarInsn(ALOAD, 0);
352                         mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");
353                         mv.visitInsn(ARETURN);
354                         Label l1 = new Label();
355                         mv.visitLabel(l1);
356                         mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l1, 0);
357                         mv.visitMaxs(3, 1);
358                         mv.visitEnd();                  
359                 } else if (ci.noArgsConstructor != null)
360                 {
361                         // return new MyClass();
362                         mv.visitCode();
363                         Label l0 = new Label();
364                         mv.visitLabel(l0);
365                         mv.visitTypeInsn(NEW, className);
366                         mv.visitInsn(DUP);
367                         mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");
368                         mv.visitInsn(ARETURN);
369                         Label l1 = new Label();
370                         mv.visitLabel(l1);
371                         mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l1, 0);
372                         mv.visitMaxs(2, 1);
373                         mv.visitEnd();                  
374                 } else {
375                         mv.visitCode();
376                         Label l0 = new Label();
377                         mv.visitLabel(l0);
378                         mv.visitIntInsn(BIPUSH, count);
379                         mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
380                         mv.visitVarInsn(ASTORE, 1);
381                         Label l1 = new Label();
382                         mv.visitLabel(l1);
383                         mv.visitInsn(ICONST_0);
384                         mv.visitVarInsn(ISTORE, 2);
385                         Label l2 = new Label();
386                         mv.visitLabel(l2);
387                         Label l3 = new Label();
388                         mv.visitJumpInsn(GOTO, l3);
389                         Label l4 = new Label();
390                         mv.visitLabel(l4);
391                         mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"[Ljava/lang/Object;", Opcodes.INTEGER}, 0, null);
392                         mv.visitVarInsn(ALOAD, 0);
393                         mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");
394                         mv.visitVarInsn(ILOAD, 2);
395                         mv.visitInsn(AALOAD);
396                         mv.visitVarInsn(ASTORE, 3);
397                         Label l5 = new Label();
398                         mv.visitLabel(l5);
399                         mv.visitVarInsn(ALOAD, 1);
400                         mv.visitVarInsn(ILOAD, 2);
401                         mv.visitVarInsn(ALOAD, 3);
402                         mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/Binding", "createDefault", "()Ljava/lang/Object;");
403                         mv.visitInsn(AASTORE);
404                         Label l6 = new Label();
405                         mv.visitLabel(l6);
406                         mv.visitIincInsn(2, 1);
407                         mv.visitLabel(l3);
408                         mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
409                         mv.visitVarInsn(ILOAD, 2);
410                         mv.visitVarInsn(ALOAD, 1);
411                         mv.visitInsn(ARRAYLENGTH);
412                         mv.visitJumpInsn(IF_ICMPLT, l4);
413                         Label l7 = new Label();
414                         mv.visitLabel(l7);
415                         mv.visitLineNumber(109, l7);
416                         mv.visitVarInsn(ALOAD, 0);
417                         mv.visitVarInsn(ALOAD, 1);
418                         mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "create", "([Ljava/lang/Object;)Ljava/lang/Object;");
419                         mv.visitInsn(ARETURN);
420                         Label l8 = new Label();
421                         mv.visitLabel(l8);
422                         mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l8, 0);
423                         mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l1, l8, 1);
424                         mv.visitLocalVariable("i", "I", null, l2, l7, 2);
425                         mv.visitLocalVariable("fb", "Lorg/simantics/databoard/binding/Binding;", null, l5, l6, 3);
426                         mv.visitMaxs(3, 4);
427                         mv.visitEnd();                  
428                 }
429                 
430                 // setComponent
431                 {
432                         mv = cv.visitMethod(ACC_PUBLIC, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });
433                         mv.visitCode();
434                         Label l0 = new Label();
435                         mv.visitLabel(l0);
436                         mv.visitVarInsn(ALOAD, 1);
437                         mv.visitTypeInsn(CHECKCAST, className);
438                         mv.visitVarInsn(ASTORE, 4);
439                         Label endLabel = new Label();
440                         Label l1 = new Label();
441                         mv.visitLabel(l1);
442                         
443                         Label elseLabel = new Label();
444                         Label labels[] = new Label[ count ];                    
445                         for (int i=0; i<count; i++) labels[i] = new Label();
446                         
447                         if (count>0) {
448                                 mv.visitVarInsn(ILOAD, 2);
449                                 mv.visitTableSwitchInsn(0, count-1, elseLabel, labels);
450                                 
451                                 for (int i=0; i<count; i++) {
452                                         Label label = labels[ i ];
453                                         mv.visitLabel(label);
454                                         Field field = ci.fields[i];
455                                         String fieldName = field.getName();
456                                         Class<?> fieldClass = ci.fields[i].getType();
457                                         Class<?> boxClass = getBoxClass(fieldClass);
458                                         String typeDescriptor = toTypeDescriptor( fieldClass );
459                                         String boxTypeDescriptor = toTypeDescriptor( boxClass );
460         
461                                         Method setter = ci.setters[i];
462                                         Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;
463                                         boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;
464                 
465                                         if (i==0) {
466                                                 mv.visitFrame(Opcodes.F_APPEND,1, classNameX, 0, null);
467                                         } else {
468                                                 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
469                                         }
470                                         mv.visitVarInsn(ALOAD, 4);
471                                         mv.visitVarInsn(ALOAD, 3);
472                                         mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));
473                                         
474                                         if (useSetter) {
475                                                 unbox(mv, setterClass);
476                                                 mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");
477                                         } else {
478                                                 unbox(mv, fieldClass);
479                                                 mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);                                        
480                                         }
481                                         mv.visitInsn(RETURN);
482                                 }
483                         }
484                 
485                         mv.visitLabel(elseLabel);
486                         mv.visitLineNumber(178, elseLabel);
487                         if (count>0) {
488                                 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
489                         }                       
490                         mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");
491                         mv.visitInsn(DUP);
492                         mv.visitLdcInsn("Illegal field index");
493                         mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");
494                         mv.visitInsn(ATHROW);
495
496                         mv.visitLabel(endLabel);
497                         mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, endLabel, 0);
498                         mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);
499                         mv.visitLocalVariable("index", "I", null, l0, endLabel, 2);
500                         mv.visitLocalVariable("value", "Ljava/lang/Object;", null, l0, endLabel, 3);
501                         //mv.visitLocalVariable("x", "L"+className+";", null, l1, endLabel, 4);
502                         mv.visitMaxs(3, 5);
503                         mv.visitEnd();                  
504                 }
505                 
506                 // IsImmutable
507                 {
508                         mv = cv.visitMethod(ACC_PUBLIC, "isImmutable", "()Z", null, null);
509                         mv.visitCode();
510                         Label l0 = new Label();
511                         mv.visitLabel(l0);
512                         mv.visitInsn(ICONST_0);
513                         mv.visitInsn(IRETURN);
514                         Label l1 = new Label();
515                         mv.visitLabel(l1);
516                         mv.visitLocalVariable("this", "L"+className+";", null, l0, l1, 0);
517                         mv.visitMaxs(1, 1);
518                         mv.visitEnd();
519                 }
520
521                 // IsInstance
522                 {
523                         mv = cv.visitMethod(ACC_PUBLIC, "isInstance", "(Ljava/lang/Object;)Z", null, null);
524                         mv.visitCode();
525                         Label l0 = new Label();
526                         mv.visitLabel(l0);
527                         mv.visitVarInsn(ALOAD, 1);
528                         mv.visitTypeInsn(INSTANCEOF, className);
529                         mv.visitInsn(IRETURN);
530                         Label l1 = new Label();
531                         mv.visitLabel(l1);
532                         mv.visitLocalVariable("this", "L"+className+";", null, l0, l1, 0);
533                         mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l1, 1);
534                         mv.visitMaxs(1, 2);
535                         mv.visitEnd();
536                 }
537
538                 // SetComponents
539                 {                       
540                         mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });
541                         mv.visitCode();
542                         Label l0 = new Label();
543                         mv.visitLabel(l0);
544                         mv.visitVarInsn(ALOAD, 1);
545                         mv.visitTypeInsn(CHECKCAST, className);
546                         mv.visitVarInsn(ASTORE, 3);
547                         Label firstLabel = l0;
548                         
549                         for (int i=0; i<count; i++) {
550                                 Label label = new Label();
551                                 if (firstLabel==l0) firstLabel = label;
552                                 Field field = ci.fields[i];
553                                 String fieldName = field.getName();
554                                 Class<?> fieldClass = ci.fields[i].getType();
555                                 Class<?> boxClass = getBoxClass(fieldClass);
556                                 String typeDescriptor = toTypeDescriptor( fieldClass );
557                                 String boxTypeDescriptor = toTypeDescriptor( boxClass );
558
559                                 Method setter = ci.setters[i];
560                                 Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;
561                                 boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;
562                                 
563                                 mv.visitLabel(label);
564                                 mv.visitVarInsn(ALOAD, 3);
565                                 mv.visitVarInsn(ALOAD, 2);
566                                 if (i<6) {
567                                         mv.visitInsn(ICONST_0 + i);
568                                 } else {
569                                         mv.visitIntInsn(BIPUSH, i);                                             
570                                 }
571                                 mv.visitInsn(AALOAD);
572                                 mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));
573                                                         
574                                 if (useSetter) {
575                                         unbox(mv, setterClass);
576                                         mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");
577                                 } else {
578                                         unbox(mv, fieldClass);
579                                         mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);
580                                 }
581                                 
582                         }
583                         Label l17 = new Label();
584                         mv.visitLabel(l17);
585                         mv.visitInsn(RETURN);
586                         Label endLabel = new Label();
587                         mv.visitLabel(endLabel);
588                         mv.visitLocalVariable("this", "L"+className+";", null, l0, endLabel, 0);
589                         mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);
590                         mv.visitLocalVariable("value", "[Ljava/lang/Object;", null, l0, endLabel, 2);
591                         //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, firstLabel, endLabel, 3);
592                         mv.visitMaxs(3, 4);
593                         mv.visitEnd();
594                 }
595                 
596                 // Add primitive setters
597                 {
598                         addGetSetPrimitive(ci, cv, "Boolean", "Z", bindingClassName);
599                         addGetSetPrimitive(ci, cv, "Byte", "B", bindingClassName);
600                         addGetSetPrimitive(ci, cv, "Int", "I", bindingClassName);
601                         addGetSetPrimitive(ci, cv, "Long", "J", bindingClassName);
602                         addGetSetPrimitive(ci, cv, "Float", "F", bindingClassName);
603                         addGetSetPrimitive(ci, cv, "Double", "D", bindingClassName);
604                 }
605                 
606                 cv.visitEnd();
607                 return cw.toByteArray();
608         }
609         
610         private void addGetSetPrimitive(ClassInfo ci, ClassVisitor cv, String setterName, String signature, String bindingClassName)
611         {
612             String className = ci.clazz.getName().replaceAll("\\.", "/");
613             
614             Label firstLabel = new Label();
615             Label secondLabel = new Label();
616             Label errorLabel = new Label();
617             Label exitLabel = new Label();
618             Label lastLabel = new Label();
619             
620             boolean oneByte = !signature.equals("J") && !signature.equals("D");
621             
622             int c = 0;
623             for (Field f : ci.fields) {
624                 if ( toTypeDescriptor(getPrimitiveClass(f.getType())).equals( signature ) ) c++;                                
625             }
626             
627             int[] indices = new int[ c ];
628             Label[] caseLabel = new Label[ c ];
629
630             c = 0;
631             for (int i=0; i<ci.fields.length; i++) 
632             {
633                 Class<?> fieldClass = ci.fields[i].getType();
634                 fieldClass = getPrimitiveClass(fieldClass);
635                 String s = toTypeDescriptor(fieldClass);
636                 if ( !s.equals( signature ) ) continue;
637                 
638                 indices[c] = i;
639                 caseLabel[c] = new Label();
640                 c++;
641             }
642                     
643             //////////////////
644             /// Setter
645             ///
646             MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "set"+setterName, "(Ljava/lang/Object;I"+signature+")V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });
647             mv.visitCode();
648             mv.visitLabel(firstLabel);
649             mv.visitVarInsn(ALOAD, 1);
650             mv.visitTypeInsn(CHECKCAST, className);
651             mv.visitVarInsn(ASTORE, oneByte?4:5);
652
653             mv.visitLabel(secondLabel);
654             mv.visitVarInsn(ILOAD, 2);
655
656             // switch
657             mv.visitLookupSwitchInsn(errorLabel, indices, caseLabel);
658
659             // case 1:
660             if ( c>0 ) {
661                     for (int i=0; i<c; i++) {
662                         int index = indices[i];
663                     Method setter = ci.setters[index];
664                     Field field = ci.fields[index];
665                     Class<?> fieldClass = field.getType();
666                     Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;
667                     boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;
668                     String typeDescriptor = toTypeDescriptor( useSetter ? setterClass : fieldClass );
669                         
670                     mv.visitLabel(caseLabel[i]);
671                     if ( i == 0 ) {
672                         mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {className}, 0, null);
673                     } else {
674                         mv.visitFrame(Opcodes.F_SAME, 0, new Object[] {className}, 0, null);
675                     }
676                     if ( signature.equals("F") ) {
677                             mv.visitVarInsn(ALOAD, 4);
678                             mv.visitVarInsn(FLOAD, 3);
679                     } else if ( signature.equals("D") ) {
680                             mv.visitVarInsn(ALOAD, 5);
681                             mv.visitVarInsn(DLOAD, 3);
682                     } else if ( signature.equals("J") ) {
683                             mv.visitVarInsn(ALOAD, 5);
684                             mv.visitVarInsn(LLOAD, 3);
685                     } else {
686                             mv.visitVarInsn(ALOAD, 4);
687                             mv.visitVarInsn(ILOAD, 3);
688                     }
689                     
690                     if ( useSetter ) {
691                         boxTo(mv, setterClass);
692                         mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");
693                     } else {
694                         boxTo(mv, fieldClass);
695                         mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);
696                     }
697                     mv.visitJumpInsn(GOTO, exitLabel);
698                     }
699             } else {
700                 mv.visitInsn(POP);              
701             }
702
703             // default: (error)
704             /*
705             mv.visitLabel(errorLabel);
706             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
707             mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");
708             mv.visitInsn(DUP);
709             mv.visitLdcInsn("Field is not "+setterName);
710             mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");
711             mv.visitInsn(ATHROW);
712             */
713             
714             // default: setComponent
715             mv.visitLabel(errorLabel);
716             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
717             mv.visitVarInsn(ALOAD, 0);
718             mv.visitVarInsn(ALOAD, 1);
719             mv.visitVarInsn(ILOAD, 2);
720             mv.visitVarInsn(ALOAD, 0);
721             mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");
722             mv.visitVarInsn(ILOAD, 2);
723             mv.visitInsn(AALOAD);
724             if ( signature.equals("F") ) {
725                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/FloatBinding");
726                     mv.visitVarInsn(FLOAD, 3);
727                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/FloatBinding", "create", "(F)Ljava/lang/Object;");
728             } else if ( signature.equals("D") ) {
729                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/DoubleBinding");
730                     mv.visitVarInsn(DLOAD, 3);
731                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/DoubleBinding", "create", "(D)Ljava/lang/Object;");
732             } else if ( signature.equals("J") ) {
733                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/LongBinding");
734                     mv.visitVarInsn(LLOAD, 3);
735                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/LongBinding", "create", "(J)Ljava/lang/Object;");
736             } else if ( signature.equals("Z") ){
737                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/BooleanBinding");
738                     mv.visitVarInsn(ILOAD, 3);
739                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/BooleanBinding", "create", "(Z)Ljava/lang/Object;");
740             } else if ( signature.equals("I") ){
741                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/IntBinding");
742                     mv.visitVarInsn(ILOAD, 3);
743                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/IntBinding", "create", "(I)Ljava/lang/Object;");
744             } else if ( signature.equals("B") ){
745                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/ByteBinding");
746                     mv.visitVarInsn(ILOAD, 3);
747                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/ByteBinding", "create", "(B)Ljava/lang/Object;");
748             }       
749             mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V");
750
751             // return
752             mv.visitLabel(exitLabel);
753             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
754             mv.visitInsn(RETURN);
755
756             // Something at the end
757             mv.visitLabel(lastLabel);
758 //          mv.visitLocalVariable("this", "L"+bindingClassName+";", null, firstLabel, lastLabel, 0);
759 //          mv.visitLocalVariable("r", "Ljava/lang/Object;", null, firstLabel, lastLabel, 1);
760 //          mv.visitLocalVariable("index", "I", null, firstLabel, lastLabel, 2);
761 //          mv.visitLocalVariable("z", signature, null, firstLabel, lastLabel, 3);
762 //          mv.visitLocalVariable("x", "L"+className+";", null, secondLabel, lastLabel, 4);
763             mv.visitMaxs(oneByte?5:6, oneByte?5:6);
764             mv.visitEnd();
765             
766             
767             //////////////////
768             /// Getter
769             ///
770             firstLabel = new Label();
771             secondLabel = new Label();
772             errorLabel = new Label();
773             exitLabel = new Label();
774             lastLabel = new Label();
775             for (int i=0; i<c; i++) caseLabel[i] = new Label();
776             mv = cv.visitMethod(ACC_PUBLIC, "get"+setterName, "(Ljava/lang/Object;I)"+signature, null, new String[] { "org/simantics/databoard/binding/error/BindingException" });
777             mv.visitCode();
778             mv.visitLabel(firstLabel);
779             mv.visitVarInsn(ALOAD, 1);
780             mv.visitTypeInsn(CHECKCAST, className);
781             mv.visitVarInsn(ASTORE, 3);
782
783             mv.visitLabel(secondLabel);
784             mv.visitVarInsn(ILOAD, 2);
785
786             // switch
787             if ( c>0 ) {
788                     mv.visitLookupSwitchInsn(errorLabel, indices, caseLabel);
789         
790                     // case i:
791                     for (int i=0; i<c; i++) {
792                         int index = indices[i];
793                     Method getter = ci.getters[index];
794                     Field field = ci.fields[index];
795                     Class<?> fieldClass = field.getType();
796                     Class<?> getterClass = getter!=null?getter.getReturnType():null;
797                     boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter!=null;
798                     String typeDescriptor = toTypeDescriptor( useGetter ? getterClass : fieldClass );
799                         
800                     mv.visitLabel(caseLabel[i]);
801                     if ( i == 0 ) {
802                         mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {className}, 0, null);
803                     } else {
804                         mv.visitFrame(Opcodes.F_SAME, 0, new Object[] {className}, 0, null);
805                     }
806         
807                     mv.visitVarInsn(ALOAD, 3);
808                     
809                     if ( useGetter ) {
810                         mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()"+typeDescriptor);
811                         unboxFrom(mv, getterClass);
812                     } else {
813                         mv.visitFieldInsn(GETFIELD, className, field.getName(), typeDescriptor);
814                         unboxFrom(mv, fieldClass);
815                     }
816                     
817                     if ( signature.equals("F") ) {
818                             mv.visitInsn(FRETURN);
819                     } else if ( signature.equals("D") ) {
820                             mv.visitInsn(DRETURN);
821                     } else if ( signature.equals("J") ) {
822                             mv.visitInsn(LRETURN);
823                     } else {
824                             mv.visitInsn(IRETURN);
825                     }
826                     }
827             } else {
828                 mv.visitInsn(POP);              
829             }
830
831             // default: (error)
832             /*
833             mv.visitLabel(errorLabel);
834             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
835             mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");
836             mv.visitInsn(DUP);
837             mv.visitLdcInsn("Field is not "+setterName);
838             mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");
839             mv.visitInsn(ATHROW);
840             */
841             
842             // default:
843             mv.visitLabel(errorLabel);
844             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
845             mv.visitVarInsn(ALOAD, 0);
846             mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");
847             mv.visitVarInsn(ILOAD, 2);
848             mv.visitInsn(AALOAD);
849             if ( signature.equals("Z") ) {
850                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/BooleanBinding");
851                     mv.visitVarInsn(ALOAD, 0);
852                     mv.visitVarInsn(ALOAD, 1);
853                     mv.visitVarInsn(ILOAD, 2);
854                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");
855                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/BooleanBinding", "getValue_", "(Ljava/lang/Object;)Z");
856                     mv.visitInsn(IRETURN);
857             } else if ( signature.equals("B") ) {
858                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/ByteBinding");
859                     mv.visitVarInsn(ALOAD, 0);
860                     mv.visitVarInsn(ALOAD, 1);
861                     mv.visitVarInsn(ILOAD, 2);
862                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");
863                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/ByteBinding", "getValue_", "(Ljava/lang/Object;)B");
864                     mv.visitInsn(IRETURN);
865             } else if ( signature.equals("I") ) {
866                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/IntBinding");
867                     mv.visitVarInsn(ALOAD, 0);
868                     mv.visitVarInsn(ALOAD, 1);
869                     mv.visitVarInsn(ILOAD, 2);
870                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");
871                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/IntBinding", "getValue_", "(Ljava/lang/Object;)I");
872                     mv.visitInsn(IRETURN);
873             } else if ( signature.equals("J") ) {
874                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/LongBinding");
875                     mv.visitVarInsn(ALOAD, 0);
876                     mv.visitVarInsn(ALOAD, 1);
877                     mv.visitVarInsn(ILOAD, 2);
878                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");
879                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/LongBinding", "getValue_", "(Ljava/lang/Object;)J");
880                     mv.visitInsn(LRETURN);
881             } else if ( signature.equals("F") ) {
882                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/FloatBinding");
883                     mv.visitVarInsn(ALOAD, 0);
884                     mv.visitVarInsn(ALOAD, 1);
885                     mv.visitVarInsn(ILOAD, 2);
886                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");
887                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/FloatBinding", "getValue_", "(Ljava/lang/Object;)F");
888                     mv.visitInsn(FRETURN);
889             } else if ( signature.equals("D") ) {
890                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/DoubleBinding");
891                     mv.visitVarInsn(ALOAD, 0);
892                     mv.visitVarInsn(ALOAD, 1);
893                     mv.visitVarInsn(ILOAD, 2);
894                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");
895                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/DoubleBinding", "getValue_", "(Ljava/lang/Object;)D");
896                     mv.visitInsn(DRETURN);
897             }       
898
899             // Something at the end
900             mv.visitLabel(lastLabel);
901 //          mv.visitLocalVariable("this", "Lorg/simantics/databoard/binding/reflection/MyBinding;", null, firstLabel, lastLabel, 0);
902 //          mv.visitLocalVariable("r", "Ljava/lang/Object;", null, firstLabel, lastLabel, 1);
903 //          mv.visitLocalVariable("index", "I", null, firstLabel, lastLabel, 2);
904 //          mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, secondLabel, lastLabel, 3);
905             mv.visitMaxs(4, 4);
906             mv.visitEnd();          
907             
908         }
909
910
911         public static Label[] createFieldLabels(ClassInfo ci) 
912         {
913                 Label caseLabels[] = new Label[ ci.fields.length ];
914                 for (int i=0; i<ci.fields.length; i++) caseLabels[i] = new Label();
915                 return caseLabels;
916         }
917         
918         public static String toTypeDescriptor(Class<?> clazz) {
919                 if (clazz==void.class) return "V";
920                 if (clazz==boolean.class) return "Z";
921                 if (clazz==char.class) return "C";
922                 if (clazz==byte.class) return "B";
923                 if (clazz==short.class) return "S";
924                 if (clazz==int.class) return "I";
925                 if (clazz==float.class) return "F";
926                 if (clazz==long.class) return "J";
927                 if (clazz==double.class) return "D";
928                 if (clazz.isArray()) return clazz.getName().replaceAll("\\.", "/");             
929                 return "L"+clazz.getName().replaceAll("\\.", "/")+";";
930         }
931         
932         /**
933          * Get respective boxed class
934          * @param clazz
935          * @return box-class
936          */
937         public static Class<?> getBoxClass(Class<?> clazz) {
938                 if (clazz==void.class) return null;
939                 if (clazz==boolean.class) return Boolean.class;
940                 if (clazz==char.class) return Character.class;
941                 if (clazz==byte.class) return Byte.class;
942                 if (clazz==short.class) return Short.class;
943                 if (clazz==int.class) return Integer.class;
944                 if (clazz==float.class) return Float.class;
945                 if (clazz==long.class) return Long.class;
946                 if (clazz==double.class) return Double.class;
947                 return clazz;
948         }
949         
950         /**
951          * Get respective primitive class
952          * @param clazz
953          * @return primitive-class
954          */
955         public static Class<?> getPrimitiveClass(Class<?> clazz) {
956             if (clazz==Boolean.class) return boolean.class;
957             if (clazz==Character.class) return char.class;
958             if (clazz==Byte.class) return byte.class;
959             if (clazz==Short.class) return short.class;
960             if (clazz==Integer.class) return int.class;
961             if (clazz==Float.class) return float.class;
962             if (clazz==Long.class) return long.class;
963             if (clazz==Double.class) return double.class;
964             return clazz;
965         }          
966         
967         public static boolean isPrimitive(Class<?> clazz) {
968                 return clazz==boolean.class || clazz==char.class || clazz==byte.class ||
969                                 clazz==short.class || clazz==int.class || clazz==float.class ||
970                                 clazz==long.class || clazz==double.class;
971         }
972         
973         public static void unbox(MethodVisitor mv, Class<?> clazz) {
974                 if (clazz==boolean.class) {
975                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
976                 } else if (clazz==char.class) {
977                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); // C?
978                 } else if (clazz==byte.class) {
979                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
980                 } else if (clazz==short.class) {
981                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
982                 } else if (clazz==int.class) {
983                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
984                 } else if (clazz==float.class) {
985                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
986                 } else if (clazz==long.class) {
987                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
988                 } else if (clazz==double.class) {
989                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
990                 }               
991         }
992
993         public static void box(MethodVisitor mv, Class<?> clazz) {
994                 if (clazz==boolean.class) {
995                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");                     
996                 } else if (clazz==char.class) {
997                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");                         
998                 } else if (clazz==byte.class) {
999                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");                   
1000                 } else if (clazz==short.class) {
1001                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");                         
1002                 } else if (clazz==int.class) {
1003                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");                     
1004                 } else if (clazz==float.class) {
1005                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");                         
1006                 } else if (clazz==long.class) {
1007                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");                   
1008                 } else if (clazz==double.class) {
1009                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");                       
1010                 }               
1011         }
1012         
1013     public static void boxTo(MethodVisitor mv, Class<?> clazz) {
1014         if (clazz==Boolean.class) {
1015             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");         
1016         } else if (clazz==Character.class) {
1017             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");             
1018         } else if (clazz==Byte.class) {
1019             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");           
1020         } else if (clazz==Short.class) {
1021             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");             
1022         } else if (clazz==Integer.class) {
1023             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");             
1024         } else if (clazz==Float.class) {
1025             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");             
1026         } else if (clazz==Long.class) {
1027             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");           
1028         } else if (clazz==Double.class) {
1029             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");           
1030         }       
1031     }
1032     
1033     public static void unboxFrom(MethodVisitor mv, Class<?> clazz) {
1034                 if (clazz==Boolean.class) {
1035                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
1036                 } else if (clazz==Character.class) {
1037                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); // C?
1038                 } else if (clazz==Byte.class) {
1039                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
1040                 } else if (clazz==Short.class) {
1041                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
1042                 } else if (clazz==Integer.class) {
1043                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
1044                 } else if (clazz==Float.class) {
1045                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
1046                 } else if (clazz==Long.class) {
1047                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
1048                 } else if (clazz==Double.class) {
1049                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
1050                 }               
1051     }   
1052     
1053         
1054         public static String toClassCanonicalName(Class<?> clazz)
1055         {
1056                 return clazz.getName().replaceAll("\\.", "/");
1057         }
1058
1059         
1060         
1061 }