1 22 package org.jboss.proxy.compiler; 23 24 import org.apache.bcel.Constants; 25 import org.apache.bcel.classfile.Field; 26 import org.apache.bcel.classfile.Method; 27 28 import org.apache.bcel.generic.ArrayType; 29 import org.apache.bcel.generic.BasicType; 30 import org.apache.bcel.generic.ConstantPoolGen; 31 import org.apache.bcel.generic.ClassGen; 32 import org.apache.bcel.generic.FieldGen; 33 import org.apache.bcel.generic.Instruction; 34 import org.apache.bcel.generic.InstructionFactory; 35 import org.apache.bcel.generic.InstructionList; 36 import org.apache.bcel.generic.MethodGen; 37 import org.apache.bcel.generic.ObjectType; 38 import org.apache.bcel.generic.PUSH; 39 import org.apache.bcel.generic.ReferenceType; 40 import org.apache.bcel.generic.Type; 41 42 50 public class ProxyImplementationFactory 51 { 52 private final static String RUNTIME_CN = Runtime .class.getName(); 54 private final static String INVOCATION_HANDLER_CN = InvocationHandler.class.getName(); 55 private final static String STRING_BUFFER_CN = StringBuffer .class.getName(); 56 57 private final static ObjectType RUNTIME_T = (ObjectType)Utility.getType(Runtime .class); 59 private final static ObjectType INVOCATION_HANDLER_T = (ObjectType)Utility.getType(InvocationHandler.class); 60 private final static ArrayType ARRAY_OF_CLASS_T = new ArrayType("java.lang.Class", 1); 61 private final static ObjectType OBJECT_T = new ObjectType("java.lang.Object"); 62 private final static ArrayType ARRAY_OF_OBJECT_T = new ArrayType("java.lang.Object", 1); 63 private final static ObjectType STRING_T = new ObjectType("java.lang.String"); 64 private final static ObjectType STRING_BUFFER_T = new ObjectType("java.lang.StringBuffer"); 65 private final static ObjectType PROXY_TARGET_T = new ObjectType(Proxies.ProxyTarget.class.getName()); 66 private final static Type[] INVOKE_ARGS = { INVOCATION_HANDLER_T, 67 Type.INT, 68 ARRAY_OF_OBJECT_T }; 69 private final static String GET_INVOCATION_HANDLER_MN = "getInvocationHandler"; 71 private final static String GET_TARGET_TYPES_MN = "getTargetTypes"; 72 private final static String TO_STRING_MN = "toString"; 73 private final static String APPEND_MN = "append"; 74 private final static String CTOR_MN = "<init>"; 75 76 private final static String INVOCATION_HANDLER_FN = "invocationHandler"; 78 79 80 private static Type PROXY_CLASS_T; 81 82 private InstructionList il = new InstructionList(); 83 private String proxyClassName; 84 private String superClassName; 85 private ConstantPoolGen constPool; 86 private InstructionFactory iFactory; 87 88 95 public ProxyImplementationFactory(final String superClassName, 96 final String proxyClassName, 97 final ClassGen cg) 98 { 99 this.superClassName = superClassName; 100 this.proxyClassName = proxyClassName; 101 102 PROXY_CLASS_T = new ObjectType(proxyClassName); 103 constPool = cg.getConstantPool(); 104 iFactory = new InstructionFactory(cg, constPool); 105 } 106 107 119 public Method createGetInvocationHandler() 120 { 121 MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, 122 INVOCATION_HANDLER_T, 123 Type.NO_ARGS, 124 null, GET_INVOCATION_HANDLER_MN, proxyClassName, il, constPool); 125 126 il.append(iFactory.createLoad(PROXY_CLASS_T, 0)); 127 il.append(iFactory.createGetField(proxyClassName, INVOCATION_HANDLER_FN, INVOCATION_HANDLER_T)); 128 il.append(iFactory.createReturn(INVOCATION_HANDLER_T)); 129 130 mg.stripAttributes(true); 131 mg.setMaxStack(); 132 mg.setMaxLocals(); 133 134 return getMethodAndTidyup(mg); 135 } 136 137 152 public Method createGetTargetTypes() 153 { 154 MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, 155 ARRAY_OF_CLASS_T, 156 Type.NO_ARGS, 157 null, 158 GET_TARGET_TYPES_MN, 159 proxyClassName, 160 il, 161 constPool); 162 163 il.append(iFactory.createLoad(PROXY_CLASS_T, 0)); 164 il.append(iFactory.createGetField(proxyClassName, Runtime.RUNTIME_FN, RUNTIME_T)); 165 il.append(iFactory.createInvoke(RUNTIME_CN, 166 "copyTargetTypes", 167 ARRAY_OF_CLASS_T, 168 Type.NO_ARGS, 169 Constants.INVOKEVIRTUAL)); 170 171 il.append(iFactory.createReturn(ARRAY_OF_CLASS_T)); 172 173 mg.stripAttributes(true); 174 mg.setMaxStack(1); 175 mg.setMaxLocals(); 176 177 return getMethodAndTidyup(mg); 178 } 179 180 195 public Method createToString() 196 { 197 MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, STRING_T, 198 Type.NO_ARGS, 199 null, TO_STRING_MN, proxyClassName, il, constPool); 200 201 il.append(iFactory.createNew(STRING_BUFFER_T)); 202 il.append(iFactory.createDup(1)); 203 il.append(iFactory.createInvoke(STRING_BUFFER_CN, 204 CTOR_MN, 205 Type.VOID, 206 Type.NO_ARGS, 207 Constants.INVOKESPECIAL)); 208 il.append(new PUSH(constPool, "ProxyTarget[")); 209 il.append(iFactory.createInvoke(STRING_BUFFER_CN, 210 APPEND_MN, 211 STRING_BUFFER_T, 212 new Type[]{STRING_T}, 213 Constants.INVOKEVIRTUAL)); 214 il.append(iFactory.createLoad(PROXY_CLASS_T, 0)); 215 il.append(iFactory.createGetField(proxyClassName, INVOCATION_HANDLER_FN, INVOCATION_HANDLER_T)); 216 il.append(iFactory.createInvoke(STRING_BUFFER_CN, 217 APPEND_MN, 218 STRING_BUFFER_T, 219 new Type[]{OBJECT_T}, 220 Constants.INVOKEVIRTUAL)); 221 il.append(new PUSH(constPool, "]")); 222 il.append(iFactory.createInvoke(STRING_BUFFER_CN, 223 APPEND_MN, 224 STRING_BUFFER_T, 225 new Type[]{STRING_T}, 226 Constants.INVOKEVIRTUAL)); 227 il.append(iFactory.createInvoke(STRING_BUFFER_CN, 228 TO_STRING_MN, 229 STRING_T, 230 Type.NO_ARGS, 231 Constants.INVOKEVIRTUAL)); 232 il.append(iFactory.createReturn(STRING_T)); 233 234 mg.stripAttributes(true); 235 mg.setMaxStack(); 236 mg.setMaxLocals(); 237 238 return getMethodAndTidyup(mg); 239 } 240 241 256 public Method createConstructor() 257 { 258 MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, 259 Type.VOID, 260 new Type[]{INVOCATION_HANDLER_T}, 261 null, 262 CTOR_MN, 263 proxyClassName, 264 il, 265 constPool); 266 267 il.append(iFactory.createLoad(INVOCATION_HANDLER_T, 0)); 268 il.append(iFactory.createInvoke(superClassName, 269 CTOR_MN, 270 Type.VOID, 271 Type.NO_ARGS, 272 Constants.INVOKESPECIAL)); 273 il.append(iFactory.createLoad(PROXY_CLASS_T, 0)); 274 il.append(iFactory.createLoad(INVOCATION_HANDLER_T, 1)); 275 il.append(iFactory.createPutField(proxyClassName, INVOCATION_HANDLER_FN, INVOCATION_HANDLER_T)); 276 il.append(iFactory.createReturn(Type.VOID)); 277 278 mg.stripAttributes(true); 279 mg.setMaxStack(); 280 mg.setMaxLocals(); 281 282 return getMethodAndTidyup(mg); 283 } 284 285 302 public Method createProxyMethod(String name, 303 int methodNum, 304 Type rType, 305 Type[] pTypes, 306 String [] exceptionNames) 307 { 308 MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, 309 rType, 310 pTypes, 311 null, name, 313 proxyClassName, 314 il, 315 constPool); 316 317 for (int j = 0; j < exceptionNames.length; j++) { 318 mg.addException(exceptionNames[j]); 319 } 320 321 il.append(iFactory.createGetStatic(proxyClassName, Runtime.RUNTIME_FN, RUNTIME_T)); 323 il.append(iFactory.createLoad(RUNTIME_T, 0)); 324 325 il.append(iFactory.createGetField(proxyClassName, INVOCATION_HANDLER_FN, INVOCATION_HANDLER_T)); 327 328 il.append(new PUSH(constPool, methodNum)); 330 331 il.append(new PUSH(constPool, pTypes.length)); 333 il.append((Instruction)iFactory.createNewArray(OBJECT_T, (short)1)); 334 335 if (pTypes.length > 0) { 336 int i = 1; 339 for (int j = 0; j < pTypes.length; j++) { 340 Type t = pTypes[j]; 341 342 il.append(iFactory.createDup(1)); 344 345 il.append(new PUSH(constPool, j)); 347 348 if (t instanceof BasicType) { 350 String wrappedClassName = Utility.getObjectEquivalentClassName((BasicType)t); 352 ObjectType wrappedType = new ObjectType(wrappedClassName); 353 il.append(iFactory.createNew(wrappedType)); 354 355 il.append(iFactory.createDup(1)); 357 358 il.append(iFactory.createLoad(t, i)); 360 il.append(iFactory.createInvoke(wrappedClassName, 361 CTOR_MN, 362 Type.VOID, 363 new Type[] { t }, 364 Constants.INVOKESPECIAL)); 365 366 switch (t.getType()) { 368 case Constants.T_DOUBLE: case Constants.T_LONG: i++; 371 } 372 373 t = wrappedType; 375 } 376 else { 377 il.append(iFactory.createLoad(t, i)); 379 } 380 381 i++; 384 385 il.append(iFactory.createArrayStore(t)); 387 } 388 } 389 390 il.append(iFactory.createInvoke(RUNTIME_CN, 391 "invoke", 392 Type.OBJECT, 393 INVOKE_ARGS, 394 Constants.INVOKEVIRTUAL)); 395 396 if (rType instanceof ReferenceType) { 398 il.append(iFactory.createCheckCast((ReferenceType)rType)); 399 } 400 else if (rType instanceof BasicType) { 401 if (rType == Type.VOID) { 402 il.append(iFactory.createPop(1)); 404 } 405 else { 406 String wrappedClassName = Utility.getObjectEquivalentClassName((BasicType)rType); 410 ObjectType wrappedType = new ObjectType(wrappedClassName); 411 il.append(iFactory.createCheckCast((ReferenceType)wrappedType)); 412 413 String methodName = Utility.signatureToString(rType.getSignature()) + "Value"; 414 415 il.append(iFactory.createInvoke(wrappedClassName, 416 methodName, 417 rType, 418 Type.NO_ARGS, 419 Constants.INVOKEVIRTUAL)); 420 } 421 } 422 423 il.append(iFactory.createReturn(rType)); 424 425 mg.stripAttributes(true); 426 mg.setMaxStack(); 427 mg.setMaxLocals(); 428 429 return getMethodAndTidyup(mg); 430 } 431 432 445 public Field createInvocationHandlerField() 446 { 447 FieldGen fg = new FieldGen(Constants.ACC_PRIVATE, 448 INVOCATION_HANDLER_T, 449 INVOCATION_HANDLER_FN, 450 constPool); 451 return fg.getField(); 452 } 453 454 467 public Field createRuntimeField() 468 { 469 FieldGen fg = new FieldGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, 470 RUNTIME_T, 471 Runtime.RUNTIME_FN, 472 constPool); 473 return fg.getField(); 474 } 475 476 480 private Method getMethodAndTidyup(final MethodGen mg) 481 { 482 Method m = mg.getMethod(); 483 il.dispose(); 484 485 return m; 486 } 487 } 488 | Popular Tags |