1 22 package org.jboss.aop.instrument; 23 24 25 import javassist.CannotCompileException; 26 import javassist.CtClass; 27 import javassist.CtField; 28 import javassist.CtMethod; 29 import javassist.CtNewMethod; 30 import javassist.Modifier; 31 import javassist.NotFoundException; 32 33 import org.jboss.aop.AspectManager; 34 import org.jboss.aop.ClassAdvisor; 35 36 42 public class GeneratedAdvisorCallerTransformer extends CallerTransformer 43 { 44 public GeneratedAdvisorCallerTransformer(Instrumentor instrumentor, AspectManager manager) 45 { 46 super(instrumentor, manager, true, new GeneratedAdvisorCallerInfoAdder(instrumentor)); 47 } 48 49 private GeneratedAdvisorInstrumentor getInstrumentor() 50 { 51 return (GeneratedAdvisorInstrumentor)instrumentor; 52 } 53 54 private CtClass getGenadvisor() 55 { 56 return getInstrumentor().getGenadvisor(); 57 } 58 59 protected CallerExprEditor callerExprEditorFactory(ClassAdvisor advisor, CtClass clazz) 60 { 61 return new GeneratedAdvisorCallerExprEditor(advisor, clazz); 62 } 63 64 class GeneratedAdvisorCallerExprEditor extends CallerExprEditor 65 { 66 public GeneratedAdvisorCallerExprEditor(ClassAdvisor advisor, CtClass callingClass) 67 { 68 super(advisor, callingClass); 69 } 70 71 protected void setupConstructor(ConstructorDetail cd)throws NotFoundException, CannotCompileException 72 { 73 if (callerInfos.get(cd.callerInfoField) == null) 74 { 75 callerInfos.put(cd.callerInfoField, NonOptimizedCallerTransformer.PLACEHOLDER); 76 callerInfoAdder.addMethodByConInfoField(getGenadvisor(), cd.callerInfoField, cd.callingIndex, cd.classname, cd.calledHash); 77 addJoinpoint(cd); 78 createGenAdvisorMethodByConMethod(cd); 79 } 80 } 81 82 private void addJoinpoint(ConstructorDetail cd)throws CannotCompileException, NotFoundException 83 { 84 CtClass joinpoint = createJoinpointClass(cd); 85 CtClass genadvisor = getInstrumentor().getGenadvisor(); 86 CtField field = new CtField( 87 joinpoint, 88 MethodByConJoinPointGenerator.getInfoFieldName(cd.callingIndex, cd.classname, cd.calledHash), 89 genadvisor); 90 field.setModifiers(Modifier.PROTECTED); 91 genadvisor.addField(field); 92 } 93 94 private CtClass createJoinpointClass(ConstructorDetail cd) throws CannotCompileException, NotFoundException 95 { 96 return MethodByConJoinPointGenerator.createJoinpointBaseClass( 97 getInstrumentor(), 98 cd.callingIndex, 99 callingClass, 100 cd.calledMethod, 101 cd.classname, 102 cd.calledHash, 103 cd.callerInfoField); 104 } 105 106 private void createGenAdvisorMethodByConMethod(ConstructorDetail cd) throws NotFoundException, CannotCompileException 107 { 108 final boolean hasTargetObject = !Modifier.isStatic(cd.calledMethod.getModifiers()); 109 final int originalLength = cd.calledMethod.getParameterTypes().length; 110 CtClass[] params = null; 111 112 if (hasTargetObject) 113 { 114 params = new CtClass[originalLength + 1]; 115 params[0] = instrumentor.forName(cd.classname); System.arraycopy(cd.calledMethod.getParameterTypes(), 0, params, 1, originalLength); 117 } 118 else 119 { 120 params = cd.calledMethod.getParameterTypes(); 121 } 122 123 String proceed = null; 124 125 if (hasTargetObject) 126 { 127 proceed = MethodExecutionTransformer.getAopReturnStr(cd.calledMethod) + "$1." + cd.calledMethod.getName() + "(" + getArguments(params.length, 1) +");"; 128 } 129 else 130 { 131 proceed = MethodExecutionTransformer.getAopReturnStr(cd.calledMethod) + cd.classname + "." + cd.calledMethod.getName() + "($$);"; 132 } 133 134 String infoName = MethodByConJoinPointGenerator.getInfoFieldName(cd.callingIndex, cd.classname, cd.calledHash); 135 String generatorName = MethodByConJoinPointGenerator.getJoinPointGeneratorFieldName(cd.callingIndex, cd.classname, cd.calledHash); 136 String code = 137 "{" + 138 " if (" + infoName + " == null && " + generatorName + " != null)" + 139 " {" + 140 " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" + 141 " }" + 142 " if (" + infoName + " == null)" + 143 " { " + 144 " " + proceed + 145 " }" + 146 " else" + 147 " {" + 148 " return " + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($$);" + 149 " }" + 150 "}"; 151 152 try 153 { 154 CtMethod method = CtNewMethod.make( 155 cd.calledMethod.getReturnType(), 156 cd.callerInfoField, 157 params, 158 cd.calledMethod.getExceptionTypes(), 159 code, 160 getGenadvisor()); 161 getGenadvisor().addMethod(method); 162 } 163 catch(CannotCompileException e) 164 { 165 System.out.println("Error for " + cd.callingIndex + " code:" + code); 166 throw e; 167 } 168 } 169 170 171 protected void setupMethod(MethodDetail md) throws NotFoundException, CannotCompileException 172 { 173 if (callerInfos.get(md.callerInfoField) == null) 174 { 175 callerInfos.put(md.callerInfoField, NonOptimizedCallerTransformer.PLACEHOLDER); 176 callerInfoAdder.addMethodByMethodInfoField(getGenadvisor(), md.callerInfoField, md.callingHash, md.classname, md.calledHash); 177 addJoinpoint(md); 178 createGenAdvisorMethodByMethodMethod(md); 179 } 180 } 181 182 private void addJoinpoint(MethodDetail md)throws CannotCompileException, NotFoundException 183 { 184 CtClass joinpoint = createJoinpointClass(md); 185 CtClass genadvisor = getInstrumentor().getGenadvisor(); 186 CtField field = new CtField( 187 joinpoint, 188 MethodByMethodJoinPointGenerator.getInfoFieldName(md.callingHash, md.classname, md.calledHash), 189 genadvisor); 190 field.setModifiers(Modifier.PROTECTED); 191 genadvisor.addField(field); 192 } 193 194 private CtClass createJoinpointClass(MethodDetail md) throws CannotCompileException, NotFoundException 195 { 196 return MethodByMethodJoinPointGenerator.createJoinpointBaseClass( 197 getInstrumentor(), 198 md.callingHash, 199 !Modifier.isStatic(md.where.getModifiers()), 200 callingClass, 201 md.calledMethod, 202 md.classname, 203 md.calledHash, 204 md.callerInfoField); 205 } 206 207 private void createGenAdvisorMethodByMethodMethod(MethodDetail md) throws NotFoundException, CannotCompileException 208 { 209 210 final boolean hasCallingObject = !Modifier.isStatic(md.where.getModifiers()); 211 final boolean hasTargetObject = !Modifier.isStatic(md.calledMethod.getModifiers()); 212 final int originalLength = md.calledMethod.getParameterTypes().length; 213 214 int offset = 0; 215 if (hasTargetObject) offset++; 216 if (hasCallingObject) offset++; 217 218 219 CtClass[] params = new CtClass[originalLength + offset]; 220 int index = 0; 221 if (hasTargetObject) params[index++] = instrumentor.forName(md.classname); if (hasCallingObject) params[index++] = callingClass; 223 224 System.arraycopy(md.calledMethod.getParameterTypes(), 0, params, offset, originalLength); 225 226 String proceed = null; 227 if (hasTargetObject) 228 { 229 proceed = MethodExecutionTransformer.getAopReturnStr(md.calledMethod) + "$1." + md.calledMethod.getName() + "(" + getArguments(params.length, hasCallingObject ? 2 : 1) +");"; 230 } 231 else 232 { 233 proceed = MethodExecutionTransformer.getAopReturnStr(md.calledMethod) + md.classname + "." + md.calledMethod.getName() + "(" + getArguments(params.length, hasCallingObject ? 1 : 0) +");"; 234 } 235 236 String infoName = MethodByMethodJoinPointGenerator.getInfoFieldName(md.callingHash, md.classname, md.calledHash); 237 String generatorName = MethodByMethodJoinPointGenerator.getJoinPointGeneratorFieldName(md.callingHash, md.classname, md.calledHash); 238 String code = 239 "{" + 240 " if (" + infoName + " == null && " + generatorName + " != null)" + 241 " {" + 242 " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" + 243 " }" + 244 " if (" + infoName + " == null)" + 245 " { " + 246 " " + proceed + 247 " }" + 248 " else" + 249 " {" + 250 " " + MethodExecutionTransformer.getReturnStr(md.calledMethod) + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($$);" + 251 " }" + 252 "}"; 253 254 255 try 256 { 257 CtMethod method = CtNewMethod.make( 258 md.calledMethod.getReturnType(), 259 md.callerInfoField, 260 params, 261 md.calledMethod.getExceptionTypes(), 262 code, 263 getGenadvisor()); 264 getGenadvisor().addMethod(method); 265 } 266 catch(CannotCompileException e) 267 { 268 System.out.println("Error for " + md.where + " code:" + code); 269 throw e; 270 } 271 } 272 273 protected void setupMethod(ConByMethodDetail cd) throws NotFoundException, CannotCompileException 274 { 275 if (callerInfos.get(cd.callerInfoField) == null) 276 { 277 callerInfos.put(cd.callerInfoField, NonOptimizedCallerTransformer.PLACEHOLDER); 278 callerInfoAdder.addConByMethodInfoField(getGenadvisor(), cd.callerInfoField, cd.callingHash, cd.classname, cd.calledHash); 279 addJoinpoint(cd); 280 createGenAdvisorConByMethodMethod(cd); 281 } 282 } 283 284 private void addJoinpoint(ConByMethodDetail cd)throws CannotCompileException, NotFoundException 285 { 286 CtClass joinpoint = createJoinpointClass(cd); 287 CtClass genadvisor = getInstrumentor().getGenadvisor(); 288 CtField field = new CtField( 289 joinpoint, 290 ConByMethodJoinPointGenerator.getInfoFieldName(cd.callingHash, cd.classname, cd.calledHash), 291 genadvisor); 292 field.setModifiers(Modifier.PROTECTED); 293 genadvisor.addField(field); 294 } 295 296 private CtClass createJoinpointClass(ConByMethodDetail cd) throws CannotCompileException, NotFoundException 297 { 298 return ConByMethodJoinPointGenerator.createJoinpointBaseClass( 299 getInstrumentor(), 300 cd.callingHash, 301 !Modifier.isStatic(cd.where.getModifiers()), 302 callingClass, 303 cd.calledConstructor, 304 cd.classname, 305 cd.calledHash, 306 cd.callerInfoField); 307 } 308 309 private void createGenAdvisorConByMethodMethod(ConByMethodDetail cd) throws NotFoundException, CannotCompileException 310 { 311 final boolean hasCallingObject = !Modifier.isStatic(cd.where.getModifiers()); 312 final String info = cd.callerInfoField; 313 314 final int originalLength = cd.calledConstructor.getParameterTypes().length; 315 CtClass[] params = null; 316 317 if (hasCallingObject) 318 { 319 params = new CtClass[originalLength + 1]; 320 params[0] = callingClass; 321 System.arraycopy(cd.calledConstructor.getParameterTypes(), 0, params, 1, originalLength); 322 } 323 else 324 { 325 params = cd.calledConstructor.getParameterTypes(); 326 } 327 328 String infoName = ConByMethodJoinPointGenerator.getInfoFieldName(cd.callingHash, cd.classname, cd.calledHash); 329 String generatorName = ConByMethodJoinPointGenerator.getJoinPointGeneratorFieldName(cd.callingHash, cd.classname, cd.calledHash); 330 StringBuffer code = new StringBuffer (); 331 code.append("{"); 332 code.append(" if (" + infoName + " == null && " + generatorName + " != null)"); 333 code.append(" {"); 334 code.append(" " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();"); 335 code.append(" }"); 336 code.append(" if (" + infoName + " == null)"); 337 code.append(" { "); 338 code.append(" return new " + cd.calledConstructor.getDeclaringClass().getName() + "(" + getArguments(params.length, hasCallingObject ? 1 : 0) + "); "); 339 code.append(" }"); 340 code.append(" else"); 341 code.append(" {"); 342 code.append(" return " + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($$);"); 343 code.append(" }"); 344 code.append("}"); 345 346 try 347 { 348 CtMethod method = CtNewMethod.make( 349 cd.calledConstructor.getDeclaringClass(), 350 info, 351 params, 352 cd.calledConstructor.getExceptionTypes(), 353 code.toString(), 354 getGenadvisor()); 355 getGenadvisor().addMethod(method); 356 } 357 catch(CannotCompileException e) 358 { 359 System.out.println("Error for " + cd.where + ": code:" + code); 360 throw e; 361 } 362 } 363 364 365 protected void setupConstructor(ConByConDetail cd)throws NotFoundException, CannotCompileException 366 { 367 if (callerInfos.get(cd.callerInfoField) == null) 368 { 369 callerInfos.put(cd.callerInfoField, NonOptimizedCallerTransformer.PLACEHOLDER); 370 callerInfoAdder.addConByConInfoField(getGenadvisor(), cd.callerInfoField, cd.callingIndex, cd.classname, cd.calledHash); 371 addJoinpoint(cd); 372 createGenAdvisorConByConMethod(cd); 373 } 374 } 375 376 private void addJoinpoint(ConByConDetail cd)throws CannotCompileException, NotFoundException 377 { 378 CtClass joinpoint = createJoinpointClass(cd); 379 CtClass genadvisor = getInstrumentor().getGenadvisor(); 380 CtField field = new CtField( 381 joinpoint, 382 ConByConJoinPointGenerator.getInfoFieldName(cd.callingIndex, cd.classname, cd.calledHash), 383 genadvisor); 384 field.setModifiers(Modifier.PROTECTED); 385 genadvisor.addField(field); 386 } 387 388 private CtClass createJoinpointClass(ConByConDetail cd) throws CannotCompileException, NotFoundException 389 { 390 return ConByConJoinPointGenerator.createJoinpointBaseClass( 391 getInstrumentor(), 392 cd.callingIndex, 393 callingClass, 394 cd.calledConstructor, 395 cd.classname, 396 cd.calledHash, 397 cd.callerInfoField); 398 } 399 400 401 private void createGenAdvisorConByConMethod(ConByConDetail cd)throws CannotCompileException, NotFoundException 402 { 403 String infoName = ConByConJoinPointGenerator.getInfoFieldName(cd.callingIndex, cd.classname, cd.calledHash); 404 String generatorName = ConByConJoinPointGenerator.getJoinPointGeneratorFieldName(cd.callingIndex, cd.classname, cd.calledHash); 405 String code = 406 "{" + 407 " if (" + infoName + " == null && " + generatorName + " != null)" + 408 " {" + 409 " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" + 410 " }" + 411 " if (" + infoName + " == null)" + 412 " { " + 413 " return new " + cd.calledConstructor.getDeclaringClass().getName() + "($$); " + 414 " }" + 415 " else" + 416 " {" + 417 " return " + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($$);" + 418 " }" + 419 "}"; 420 421 try 422 { 423 CtMethod method = CtNewMethod.make( 424 cd.calledConstructor.getDeclaringClass(), 425 cd.callerInfoField, 426 cd.calledConstructor.getParameterTypes(), 427 cd.calledConstructor.getExceptionTypes(), 428 code, 429 getGenadvisor()); 430 getGenadvisor().addMethod(method); 431 } 432 catch(CannotCompileException e) 433 { 434 System.out.println("Error for " + cd.callingIndex + " code:" + code); 435 throw e; 436 } 437 } 438 439 protected void replaceMethodCallInCon(ConstructorDetail cd)throws CannotCompileException, NotFoundException 440 { 441 final String advisor = " ((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" + Instrumentor.HELPER_FIELD_NAME + ")"; 442 final int paramsLength = cd.calledMethod.getParameterTypes().length; 443 String args = null; 444 if (Modifier.isStatic(cd.calledMethod.getModifiers())) 445 { 446 args = (paramsLength > 0) ? "$$" : ""; 447 } 448 else 449 { 450 args = "$0" + ((paramsLength > 0) ? ", $$" : ""); 451 } 452 453 final String ret = (!cd.calledMethod.getReturnType().equals(CtClass.voidType)) ? "$_ = " : ""; 454 455 String replaced = ret + advisor + "." + cd.callerInfoField + "(" + args + ");"; 456 457 try 458 { 459 cd.call.replace(replaced); 460 } 461 catch(CannotCompileException e) 462 { 463 System.out.println("Error for " + cd.con + " code:" + replaced); 464 throw e; 465 } 466 } 467 468 protected void replaceMethodCallInMethod(MethodDetail md)throws NotFoundException, CannotCompileException 469 { 470 final boolean hasCallingObject = !Modifier.isStatic(md.where.getModifiers()); 471 final boolean hasTargetObject = !Modifier.isStatic(md.calledMethod.getModifiers()); 472 final int paramsLength = md.calledMethod.getParameterTypes().length; 473 String args = null; 474 if (hasCallingObject && hasTargetObject) 475 { 476 args = "$0, this" + ((paramsLength > 0 ) ? ", $$" : ""); 477 } 478 else if (!hasCallingObject && hasTargetObject) 479 { 480 args = "$0" + ((paramsLength > 0 ) ? ", $$" : ""); 481 } 482 else if (hasCallingObject && !hasTargetObject) 483 { 484 args = "this" + ((paramsLength > 0 ) ? ", $$" : ""); 485 } 486 else 487 { 488 args = "$$"; 489 } 490 491 String advisor; 492 if (hasCallingObject) 493 { 494 advisor = "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" + 495 GeneratedAdvisorInstrumentor.GET_CURRENT_ADVISOR + ")"; 496 } 497 else 498 { 499 advisor = " ((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" + Instrumentor.HELPER_FIELD_NAME + ")"; 500 } 501 final String ret = (md.calledMethod.getReturnType().equals(CtClass.voidType)) ? "" : "$_ = "; 502 503 String replaced = ret + advisor + "." + md.callerInfoField + "(" + args + ");"; 504 505 try 506 { 507 md.call.replace(replaced); 508 } 509 catch(CannotCompileException e) 510 { 511 System.out.println("Error for " + md.where + " code:" + replaced); 512 throw e; 513 } 514 } 515 516 517 protected void replaceConCallInMethod(ConByMethodDetail cd) throws NotFoundException, CannotCompileException 518 { 519 final int paramsLength = cd.calledConstructor.getParameterTypes().length; 520 String args = null; 521 String advisor = null; 522 if (!Modifier.isStatic(cd.where.getModifiers())) 523 { 524 args = "this" + ((paramsLength > 0) ? ", $$" : ""); 525 advisor = "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" + 526 GeneratedAdvisorInstrumentor.GET_CURRENT_ADVISOR + ")"; 527 } 528 else 529 { 530 args = ((paramsLength > 0) ? "$$" : ""); 531 advisor = " ((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" + Instrumentor.HELPER_FIELD_NAME + ")"; 532 } 533 534 String replaced = "$_ = " + advisor + "." + cd.callerInfoField + "(" + args + ");"; 535 536 try 537 { 538 cd.call.replace(replaced); 539 } 540 catch(CannotCompileException e) 541 { 542 System.out.println("Error for " + cd.where + " code:" + replaced); 543 throw e; 544 } 545 } 546 547 protected void replaceConCallInCon(ConByConDetail cd)throws CannotCompileException, NotFoundException 548 { 549 String advisor = "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" + 550 Instrumentor.HELPER_FIELD_NAME + ")"; 551 552 String replaced = "$_ = " + advisor + "." + cd.callerInfoField + "($$);"; 553 554 try 555 { 556 cd.call.replace(replaced); 557 } 558 catch(CannotCompileException e) 559 { 560 System.out.println("Error for " + cd.callingIndex + " code:" + replaced); 561 throw e; 562 } 563 } 564 } 565 566 567 private String getArguments(int length, int offset) 568 { 569 StringBuffer sb = new StringBuffer (""); 570 for (int i = 0 ; i < length - offset; i++) 571 { 572 if (i > 0) 573 { 574 sb.append(", "); 575 } 576 sb.append("$" + (i + 1 + offset)); 577 } 578 return sb.toString(); 579 } 580 581 } 582 | Popular Tags |