1 46 package org.codehaus.groovy.classgen; 47 48 import groovy.lang.MetaMethod; 49 50 import java.util.List ; 51 52 import org.objectweb.asm.ClassVisitor; 53 import org.objectweb.asm.CodeVisitor; 54 import org.objectweb.asm.Constants; 55 import org.objectweb.asm.Label; 56 57 63 public class ReflectorGenerator implements Constants { 64 65 private List methods; 66 private ClassVisitor cw; 67 private CodeVisitor cv; 68 private BytecodeHelper helper = new BytecodeHelper(null); 69 private String classInternalName; 70 71 public ReflectorGenerator(List methods) { 72 this.methods = methods; 73 } 74 75 public void generate(ClassVisitor cw, String className) { 76 this.cw = cw; 77 String fileName = className; 78 int idx = className.lastIndexOf('.'); 79 if (idx > 0) { 80 fileName = className.substring(idx + 1); 81 } 82 fileName += ".java"; 83 84 classInternalName = BytecodeHelper.getClassInternalName(className); 85 cw.visit(ClassGenerator.asmJDKVersion, ACC_PUBLIC + ACC_SUPER, classInternalName, "org/codehaus/groovy/runtime/Reflector", null, fileName); 86 87 cv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 88 cv.visitVarInsn(ALOAD, 0); 89 cv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/Reflector", "<init>", "()V"); 90 cv.visitInsn(RETURN); 91 cv.visitMaxs(1, 1); 92 93 generateInvokeMethod(); 94 95 cw.visitEnd(); 96 } 97 98 protected void generateInvokeMethod() { 99 int methodCount = methods.size(); 100 101 cv = 102 cw.visitMethod( 103 ACC_PUBLIC, 104 "invoke", 105 "(Lgroovy/lang/MetaMethod;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", 106 null, 107 null); 108 helper = new BytecodeHelper(cv); 109 110 cv.visitVarInsn(ALOAD, 1); 111 cv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/MetaMethod", "getMethodIndex", "()I"); 112 Label defaultLabel = new Label(); 113 Label[] labels = new Label[methodCount]; 114 int[] indices = new int[methodCount]; 115 for (int i = 0; i < methodCount; i++) { 116 labels[i] = new Label(); 117 118 MetaMethod method = (MetaMethod) methods.get(i); 119 method.setMethodIndex(i + 1); 120 indices[i] = method.getMethodIndex(); 121 122 } 124 125 cv.visitLookupSwitchInsn(defaultLabel, indices, labels); 126 128 for (int i = 0; i < methodCount; i++) { 129 cv.visitLabel(labels[i]); 130 131 MetaMethod method = (MetaMethod) methods.get(i); 132 invokeMethod(method); 133 if (method.getReturnType() == void.class) { 134 cv.visitInsn(ACONST_NULL); 135 } 136 cv.visitInsn(ARETURN); 137 } 138 139 cv.visitLabel(defaultLabel); 140 cv.visitVarInsn(ALOAD, 0); 141 cv.visitVarInsn(ALOAD, 1); 142 cv.visitVarInsn(ALOAD, 2); 143 cv.visitVarInsn(ALOAD, 3); 144 cv.visitMethodInsn( 145 INVOKEVIRTUAL, 146 classInternalName, 147 "noSuchMethod", 148 "(Lgroovy/lang/MetaMethod;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); 149 cv.visitInsn(ARETURN); 150 cv.visitMaxs(4, 4); 151 } 152 153 protected void invokeMethod(MetaMethod method) { 154 158 Class ownerClass = method.getInterfaceClass(); 159 boolean useInterface = false; 160 if (ownerClass == null) { 161 ownerClass = method.getDeclaringClass(); 162 } 163 else { 164 useInterface = true; 165 } 166 String type = BytecodeHelper.getClassInternalName(ownerClass.getName()); 167 String descriptor = BytecodeHelper.getMethodDescriptor(method.getReturnType(), method.getParameterTypes()); 168 169 172 if (method.isStatic()) { 173 loadParameters(method, 3); 174 cv.visitMethodInsn(INVOKESTATIC, type, method.getName(), descriptor); 175 } 176 else { 177 cv.visitVarInsn(ALOAD, 2); 178 helper.doCast(ownerClass); 179 loadParameters(method, 3); 180 cv.visitMethodInsn((useInterface) ? INVOKEINTERFACE : INVOKEVIRTUAL, type, method.getName(), descriptor); 181 } 182 183 helper.box(method.getReturnType()); 184 } 185 186 271 272 protected void loadParameters(MetaMethod method, int argumentIndex) { 273 Class [] parameters = method.getParameterTypes(); 274 int size = parameters.length; 275 for (int i = 0; i < size; i++) { 276 cv.visitVarInsn(ALOAD, argumentIndex); 277 helper.pushConstant(i); 278 cv.visitInsn(AALOAD); 279 280 Class type = parameters[i]; 282 if (type.isPrimitive()) { 283 helper.unbox(type); 284 } 285 else { 286 helper.doCast(type.getName()); 287 } 288 } 289 } 290 } 291 | Popular Tags |