1 15 16 package javassist; 17 18 import javassist.bytecode.*; 19 import javassist.compiler.JvstCodeGen; 20 import java.util.Hashtable ; 21 import javassist.CtMethod.ConstParameter; 22 23 class CtNewWrappedMethod { 24 25 private static final String addedWrappedMethod = "_added_m$"; 26 27 public static CtMethod wrapped(CtClass returnType, String mname, 28 CtClass[] parameterTypes, 29 CtClass[] exceptionTypes, 30 CtMethod body, ConstParameter constParam, 31 CtClass declaring) 32 throws CannotCompileException 33 { 34 CtMethod mt = new CtMethod(returnType, mname, parameterTypes, 35 declaring); 36 mt.setModifiers(body.getModifiers()); 37 try { 38 mt.setExceptionTypes(exceptionTypes); 39 } 40 catch (NotFoundException e) { 41 throw new CannotCompileException(e); 42 } 43 44 Bytecode code = makeBody(declaring, declaring.getClassFile2(), body, 45 parameterTypes, returnType, constParam); 46 mt.getMethodInfo2().setCodeAttribute(code.toCodeAttribute()); 47 return mt; 48 } 49 50 static Bytecode makeBody(CtClass clazz, ClassFile classfile, 51 CtMethod wrappedBody, 52 CtClass[] parameters, 53 CtClass returnType, 54 ConstParameter cparam) 55 throws CannotCompileException 56 { 57 boolean isStatic = Modifier.isStatic(wrappedBody.getModifiers()); 58 Bytecode code = new Bytecode(classfile.getConstPool(), 0, 0); 59 int stacksize = makeBody0(clazz, classfile, wrappedBody, isStatic, 60 parameters, returnType, cparam, code); 61 code.setMaxStack(stacksize); 62 code.setMaxLocals(isStatic, parameters, 0); 63 return code; 64 } 65 66 protected static int makeBody0(CtClass clazz, ClassFile classfile, 67 CtMethod wrappedBody, 68 boolean isStatic, CtClass[] parameters, 69 CtClass returnType, ConstParameter cparam, 70 Bytecode code) 71 throws CannotCompileException 72 { 73 if (!(clazz instanceof CtClassType)) 74 throw new CannotCompileException("bad declaring class" 75 + clazz.getName()); 76 77 if (!isStatic) 78 code.addAload(0); 79 80 int stacksize = compileParameterList(code, parameters, 81 (isStatic ? 0 : 1)); 82 int stacksize2; 83 String desc; 84 if (cparam == null) { 85 stacksize2 = 0; 86 desc = ConstParameter.defaultDescriptor(); 87 } 88 else { 89 stacksize2 = cparam.compile(code); 90 desc = cparam.descriptor(); 91 } 92 93 checkSignature(wrappedBody, desc); 94 95 String bodyname; 96 try { 97 bodyname = addBodyMethod((CtClassType)clazz, classfile, 98 wrappedBody); 99 102 } 103 catch (BadBytecode e) { 104 throw new CannotCompileException(e); 105 } 106 107 if (isStatic) 108 code.addInvokestatic(Bytecode.THIS, bodyname, desc); 109 else 110 code.addInvokespecial(Bytecode.THIS, bodyname, desc); 111 112 compileReturn(code, returnType); 114 if (stacksize < stacksize2 + 2) 115 stacksize = stacksize2 + 2; 116 117 return stacksize; 118 } 119 120 private static void checkSignature(CtMethod wrappedBody, 121 String descriptor) 122 throws CannotCompileException 123 { 124 if (!descriptor.equals(wrappedBody.getMethodInfo2().getDescriptor())) 125 throw new CannotCompileException( 126 "wrapped method with a bad signature: " 127 + wrappedBody.getDeclaringClass().getName() 128 + '.' + wrappedBody.getName()); 129 } 130 131 private static String addBodyMethod(CtClassType clazz, 132 ClassFile classfile, 133 CtMethod src) 134 throws BadBytecode, CannotCompileException 135 { 136 Hashtable bodies = clazz.getHiddenMethods(); 137 String bodyname = (String )bodies.get(src); 138 if (bodyname == null) { 139 do { 140 bodyname = addedWrappedMethod + clazz.getUniqueNumber(); 141 } while (classfile.getMethod(bodyname) != null); 142 ClassMap map = new ClassMap(); 143 map.put(src.getDeclaringClass().getName(), clazz.getName()); 144 MethodInfo body = new MethodInfo(classfile.getConstPool(), 145 bodyname, src.getMethodInfo2(), 146 map); 147 int acc = body.getAccessFlags(); 148 body.setAccessFlags(AccessFlag.setPrivate(acc)); 149 classfile.addMethod(body); 150 bodies.put(src, bodyname); 151 } 152 153 return bodyname; 154 } 155 156 163 static int compileParameterList(Bytecode code, 164 CtClass[] params, int regno) { 165 return JvstCodeGen.compileParameterList(code, params, regno); 166 } 167 168 171 private static void compileReturn(Bytecode code, CtClass type) { 172 if (type.isPrimitive()) { 173 CtPrimitiveType pt = (CtPrimitiveType)type; 174 if (pt != CtClass.voidType) { 175 String wrapper = pt.getWrapperName(); 176 code.addCheckcast(wrapper); 177 code.addInvokevirtual(wrapper, pt.getGetMethodName(), 178 pt.getGetMethodDescriptor()); 179 } 180 181 code.addOpcode(pt.getReturnOp()); 182 } 183 else { 184 code.addCheckcast(type); 185 code.addOpcode(Bytecode.ARETURN); 186 } 187 } 188 } 189 | Popular Tags |