1 4 package com.tc.aspectwerkz.transform.inlining.weaver; 5 6 import java.util.Set ; 7 import java.util.Iterator ; 8 import java.util.Collection ; 9 10 import com.tc.asm.*; 11 12 import com.tc.aspectwerkz.DeploymentModel; 13 import com.tc.aspectwerkz.expression.PointcutType; 14 import com.tc.aspectwerkz.expression.ExpressionInfo; 15 import com.tc.aspectwerkz.expression.ExpressionContext; 16 import com.tc.aspectwerkz.reflect.ClassInfo; 17 import com.tc.aspectwerkz.definition.AdviceDefinition; 18 import com.tc.aspectwerkz.definition.DeploymentScope; 19 import com.tc.aspectwerkz.definition.SystemDefinition; 20 import com.tc.aspectwerkz.perx.PerObjectAspect; 21 import com.tc.aspectwerkz.transform.InstrumentationContext; 22 import com.tc.aspectwerkz.transform.TransformationConstants; 23 24 30 public class InstanceLevelAspectVisitor extends ClassAdapter implements TransformationConstants { 31 32 private final InstrumentationContext m_ctx; 33 private final ClassInfo m_classInfo; 34 private boolean m_isAdvised = false; 35 36 43 public InstanceLevelAspectVisitor(final ClassVisitor cv, 44 final ClassInfo classInfo, 45 final InstrumentationContext ctx) { 46 super(cv); 47 m_classInfo = classInfo; 48 m_ctx = (InstrumentationContext) ctx; 49 } 50 51 60 public void visit(final int version, 61 final int access, 62 final String name, 63 final String signature, 64 final String superName, 65 final String [] interfaces) { 66 67 if (classFilter(m_classInfo, m_ctx.getDefinitions())) { 68 super.visit(version, access, name, signature, superName, interfaces); 69 return; 70 } 71 72 for (int i = 0; i < interfaces.length; i++) { 73 String anInterface = interfaces[i]; 74 if (anInterface.equals(HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME)) { 75 super.visit(version, access, name, signature, superName, interfaces); 76 return; 77 } 78 } 79 String [] newInterfaceArray = new String [interfaces.length + 1]; 80 System.arraycopy(interfaces, 0, newInterfaceArray, 0, interfaces.length); 81 newInterfaceArray[interfaces.length] = HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME; 82 83 super.visit(version, access, name, signature, superName, newInterfaceArray); 85 86 addAspectMapField(); 88 89 addGetAspectMethod(name); 91 92 addHasAspectMethod(name); 94 95 addBindAspectMethod(name); 96 } 97 98 108 public MethodVisitor visitMethod(final int access, 109 final String name, 110 final String desc, 111 final String signature, 112 final String [] exceptions) { 113 if (m_isAdvised) { 114 if (name.equals(INIT_METHOD_NAME)) { 115 MethodVisitor mv = new AppendToInitMethodCodeAdapter( 116 cv.visitMethod(access, name, desc, signature, exceptions), 117 name 118 ); 119 mv.visitMaxs(0, 0); 120 return mv; 121 } 122 } 123 return cv.visitMethod(access, name, desc, signature, exceptions); 124 } 125 126 129 private void addAspectMapField() { 130 super.visitField( 131 ACC_PRIVATE + ACC_SYNTHETIC + ACC_TRANSIENT, 132 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 133 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE, 134 null, null 135 ); 136 } 137 138 143 private void addGetAspectMethod(final String name) { 144 MethodVisitor cv = super.visitMethod( 145 ACC_PUBLIC + ACC_SYNTHETIC, 146 INSTANCE_LEVEL_GETASPECT_METHOD_NAME, 147 INSTANCE_LEVEL_GETASPECT_METHOD_SIGNATURE, 148 null, null 149 ); 150 151 cv.visitVarInsn(ALOAD, 0); 152 cv.visitFieldInsn( 153 GETFIELD, 154 name, 155 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 156 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 157 ); 158 cv.visitInsn(DUP); 160 Label ifMapNonNull = new Label(); 161 cv.visitJumpInsn(IFNONNULL, ifMapNonNull); 162 cv.visitInsn(ACONST_NULL); 163 cv.visitInsn(ARETURN); 164 cv.visitLabel(ifMapNonNull); 165 166 cv.visitVarInsn(ALOAD, 1); 213 cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, GET_METHOD_NAME, GET_METHOD_SIGNATURE); 214 cv.visitInsn(ARETURN); 222 cv.visitMaxs(0, 0); 230 231 m_ctx.markAsAdvised(); 232 m_isAdvised = true; 233 } 234 235 private void addHasAspectMethod(String mapFieldName) { 236 MethodVisitor cv = super.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, 237 INSTANCE_LEVEL_HASASPECT_METHOD_NAME, 238 INSTANCE_LEVEL_HASASPECT_METHOD_SIGNATURE, 239 null, 240 null 241 ); 242 243 cv.visitVarInsn(ALOAD, 0); 244 cv.visitFieldInsn(GETFIELD, 245 mapFieldName, 246 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 247 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 248 ); 249 cv.visitInsn(DUP); 250 Label ifMapNonNull = new Label(); 251 cv.visitJumpInsn(IFNONNULL, ifMapNonNull); 252 cv.visitInsn(ICONST_0); 253 cv.visitInsn(IRETURN); 254 cv.visitLabel(ifMapNonNull); 255 cv.visitVarInsn(ALOAD, 1); 256 cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, "containsKey", "(Ljava/lang/Object;)Z"); 257 cv.visitInsn(IRETURN); 266 cv.visitMaxs(0, 0); 267 268 m_ctx.markAsAdvised(); 269 m_isAdvised = true; 270 } 271 272 private void addBindAspectMethod(final String name) { 273 MethodVisitor cv = super.visitMethod( 274 ACC_PUBLIC + ACC_SYNTHETIC, 275 INSTANCE_LEVEL_BINDASPECT_METHOD_NAME, 276 INSTANCE_LEVEL_BINDASPECT_METHOD_SIGNATURE, 277 null, null 278 ); 279 280 cv.visitVarInsn(ALOAD, 0); 281 cv.visitFieldInsn( 282 GETFIELD, 283 name, 284 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 285 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 286 ); 287 Label ifFieldNullNotLabel = new Label(); 289 cv.visitJumpInsn(IFNONNULL, ifFieldNullNotLabel); 290 cv.visitVarInsn(ALOAD, 0); 291 cv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME); 292 cv.visitInsn(DUP); 293 cv.visitMethodInsn( 294 INVOKESPECIAL, 295 HASH_MAP_CLASS_NAME, 296 INIT_METHOD_NAME, 297 NO_PARAM_RETURN_VOID_SIGNATURE 298 ); 299 cv.visitFieldInsn( 300 PUTFIELD, 301 name, 302 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 303 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 304 ); 305 cv.visitLabel(ifFieldNullNotLabel); 306 307 cv.visitVarInsn(ALOAD, 0); 308 cv.visitFieldInsn( 309 GETFIELD, 310 name, 311 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 312 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 313 ); 314 cv.visitVarInsn(ALOAD, 1); 315 cv.visitVarInsn(ALOAD, 2); 316 cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, PUT_METHOD_NAME, PUT_METHOD_SIGNATURE); 317 cv.visitVarInsn(ALOAD, 2); 318 cv.visitInsn(ARETURN); 319 } 320 321 328 public static boolean classFilter(final ClassInfo classInfo, final Set definitions) { 329 if (classInfo.isInterface()) { 330 return true; 331 } 332 333 ExpressionContext ctx = new ExpressionContext(PointcutType.WITHIN, null, classInfo); 334 335 for (Iterator it = definitions.iterator(); it.hasNext();) { 336 SystemDefinition systemDef = (SystemDefinition) it.next(); 337 String className = classInfo.getName().replace('/', '.'); 338 if (systemDef.inExcludePackage(className)) { 339 return true; 340 } 341 if (!systemDef.inIncludePackage(className)) { 342 return true; 343 } 344 345 Collection adviceDefs = systemDef.getAdviceDefinitions(); 346 for (Iterator defs = adviceDefs.iterator(); defs.hasNext();) { 347 AdviceDefinition adviceDef = (AdviceDefinition) defs.next(); 348 ExpressionInfo expressionInfo = adviceDef.getExpressionInfo(); 349 if (expressionInfo == null) { 350 continue; 351 } 352 DeploymentModel deploymentModel = adviceDef.getDeploymentModel(); 353 354 if (DeploymentModel.PER_INSTANCE.equals(deploymentModel)) { 356 if (expressionInfo.getAdvisedClassFilterExpression().match(ctx)) { 357 return false; 358 } 359 } 360 361 if (adviceDef.getAspectClassName().equals(PerObjectAspect.PEROBJECT_ASPECT_NAME)) { 363 ExpressionInfo perXExpressionInfo = adviceDef.getExpressionInfo(); 364 if (perXExpressionInfo.getAdvisedClassFilterExpression().match(ctx)) { 365 return false; 366 } 367 } 368 } 369 370 Collection deploymentScopes = systemDef.getDeploymentScopes(); 372 for (Iterator scopes = deploymentScopes.iterator(); scopes.hasNext();) { 373 DeploymentScope deploymentScope = (DeploymentScope) scopes.next(); 374 ExpressionInfo expression = new ExpressionInfo( 375 deploymentScope.getExpression(), 376 systemDef.getUuid() 377 ); 378 if (expression.getAdvisedClassFilterExpression().match(ctx)) { 379 return false; 380 } 381 } 382 } 383 384 return true; 385 } 386 387 392 private class AppendToInitMethodCodeAdapter extends AfterObjectInitializationCodeAdapter { 393 394 private boolean m_done = false; 395 396 public AppendToInitMethodCodeAdapter(final MethodVisitor ca, String callerMemberName) { 397 super(ca, callerMemberName); 398 } 399 400 408 public void visitMethodInsn(int opcode, 409 String owner, 410 String name, 411 String desc) { 412 super.visitMethodInsn(opcode, owner, name, desc); 413 if (opcode == INVOKESPECIAL && m_isObjectInitialized && !m_done) { 414 m_done = true; 415 416 mv.visitVarInsn(ALOAD, 0); 418 mv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME); 419 mv.visitInsn(DUP); 420 mv.visitMethodInsn( 421 INVOKESPECIAL, 422 HASH_MAP_CLASS_NAME, 423 INIT_METHOD_NAME, 424 NO_PARAM_RETURN_VOID_SIGNATURE 425 ); 426 mv.visitFieldInsn( 427 PUTFIELD, 428 m_classInfo.getName().replace('.', '/'), 429 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 430 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 431 ); 432 } 433 } 434 } 435 } 436 | Popular Tags |