1 4 package com.tc.aspectwerkz.transform.inlining.weaver; 5 6 import com.tc.asm.ClassAdapter; 7 import com.tc.asm.ClassVisitor; 8 import com.tc.asm.Label; 9 import com.tc.asm.MethodVisitor; 10 import com.tc.asm.Type; 11 12 import com.tc.aspectwerkz.definition.SystemDefinition; 13 import com.tc.aspectwerkz.joinpoint.management.JoinPointType; 14 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo; 15 import com.tc.aspectwerkz.reflect.ClassInfo; 16 import com.tc.aspectwerkz.reflect.MemberInfo; 17 import com.tc.aspectwerkz.reflect.FieldInfo; 18 import com.tc.aspectwerkz.transform.InstrumentationContext; 19 import com.tc.aspectwerkz.transform.TransformationConstants; 20 import com.tc.aspectwerkz.transform.TransformationUtil; 21 import com.tc.aspectwerkz.transform.inlining.AsmHelper; 22 import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint; 23 import com.tc.aspectwerkz.transform.inlining.compiler.AbstractJoinPointCompiler; 24 import com.tc.aspectwerkz.expression.ExpressionContext; 25 import com.tc.aspectwerkz.expression.PointcutType; 26 27 import java.lang.reflect.Modifier ; 28 import java.util.Iterator ; 29 import java.util.Set ; 30 31 37 public class FieldSetFieldGetVisitor extends ClassAdapter implements TransformationConstants { 38 39 private final InstrumentationContext m_ctx; 40 private final ClassLoader m_loader; 41 private final ClassInfo m_callerClassInfo; 42 43 private Label m_lastLabelForLineNumber = EmittedJoinPoint.NO_LINE_NUMBER; 44 45 53 public FieldSetFieldGetVisitor(final ClassVisitor cv, 54 final ClassLoader loader, 55 final ClassInfo classInfo, 56 final InstrumentationContext ctx) { 57 super(cv); 58 m_loader = loader; 59 m_callerClassInfo = classInfo; 60 m_ctx = ctx; 61 } 62 63 73 public MethodVisitor visitMethod(final int access, 74 final String name, 75 final String desc, 76 final String signature, 77 final String [] exceptions) { 78 79 if (name.startsWith(WRAPPER_METHOD_PREFIX)) { 80 return super.visitMethod(access, name, desc, signature, exceptions); 81 } 82 83 MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); 84 return mv == null ? null : new ReplacePutFieldAndGetFieldInstructionCodeAdapter( 85 mv, 86 m_loader, 87 m_callerClassInfo, 88 m_ctx.getClassName(), 89 name, 90 desc 91 ); 92 } 93 94 100 public class ReplacePutFieldAndGetFieldInstructionCodeAdapter extends AfterObjectInitializationCodeAdapter { 101 102 private final ClassLoader m_loader; 103 private final String m_callerClassName; 104 private final String m_callerMethodName; 105 private final String m_callerMethodDesc; 106 private final MemberInfo m_callerMemberInfo; 107 108 118 public ReplacePutFieldAndGetFieldInstructionCodeAdapter(final MethodVisitor ca, 119 final ClassLoader loader, 120 final ClassInfo callerClassInfo, 121 final String callerClassName, 122 final String callerMethodName, 123 final String callerMethodDesc) { 124 super(ca, callerMethodName); 125 m_loader = loader; 126 m_callerClassName = callerClassName; 127 m_callerMethodName = callerMethodName; 128 m_callerMethodDesc = callerMethodDesc; 129 130 if (CLINIT_METHOD_NAME.equals(m_callerMethodName)) { 131 m_callerMemberInfo = callerClassInfo.staticInitializer(); 132 } else if (INIT_METHOD_NAME.equals(m_callerMethodName)) { 133 int hash = AsmHelper.calculateConstructorHash(m_callerMethodDesc); 134 m_callerMemberInfo = callerClassInfo.getConstructor(hash); 135 } else { 136 int hash = AsmHelper.calculateMethodHash(m_callerMethodName, m_callerMethodDesc); 137 m_callerMemberInfo = callerClassInfo.getMethod(hash); 138 } 139 if (m_callerMemberInfo == null) { 140 System.err.println( 141 "AW::WARNING " + 142 "metadata structure could not be build for method [" 143 + callerClassInfo.getName().replace('/', '.') 144 + '.' + m_callerMethodName + ':' + m_callerMethodDesc + ']' 145 ); 146 } 147 } 148 149 154 public void visitLabel(Label label) { 155 m_lastLabelForLineNumber = label; 156 super.visitLabel(label); 157 } 158 159 167 public void visitFieldInsn(final int opcode, 168 final String className, 169 final String fieldName, 170 final String fieldDesc) { 171 172 if (className.endsWith(AbstractJoinPointCompiler.JOIN_POINT_CLASS_SUFFIX) || 173 fieldName.startsWith(ASPECTWERKZ_PREFIX) || 174 fieldName.startsWith(SYNTHETIC_MEMBER_PREFIX) || fieldName.equals(SERIAL_VERSION_UID_FIELD_NAME) ) { 177 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 178 return; 179 } 180 181 if (!m_isObjectInitialized) { 183 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 184 return; 185 } 186 187 188 final Type fieldType = Type.getType(fieldDesc); 189 final int joinPointHash = AsmHelper.calculateFieldHash(fieldName, fieldDesc); 190 final ClassInfo classInfo = AsmClassInfo.getClassInfo(className, m_loader); 191 final FieldInfo fieldInfo = getFieldInfo(classInfo, className, fieldName, fieldDesc, joinPointHash); 192 193 if (opcode == PUTFIELD || opcode == PUTSTATIC) { 194 handleFieldModification(fieldInfo, opcode, className, fieldName, fieldDesc, joinPointHash); 195 } else if (opcode == GETFIELD || opcode == GETSTATIC) { 196 handleFieldAccess(fieldInfo, opcode, className, fieldName, fieldDesc, joinPointHash, fieldType); 197 } else { 198 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 199 } 200 } 201 202 213 private void handleFieldAccess(final FieldInfo fieldInfo, 214 final int opcode, 215 final String className, 216 final String fieldName, 217 final String fieldDesc, 218 int joinPointHash, 219 final Type fieldType) { 220 if (m_callerMemberInfo == null) { 221 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 222 return; 223 } 224 225 ExpressionContext ctx = new ExpressionContext(PointcutType.GET, fieldInfo, m_callerMemberInfo); 226 227 if (fieldFilter(m_ctx.getDefinitions(), ctx, fieldInfo)) { 228 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 229 } else { 230 m_ctx.markAsAdvised(); 231 232 String joinPointClassName = TransformationUtil.getJoinPointClassName( 233 m_callerClassName, 234 m_callerMethodName, 235 m_callerMethodDesc, 236 className, 237 JoinPointType.FIELD_GET_INT, 238 joinPointHash 239 ); 240 241 AsmHelper.addDefaultValue(this, fieldType); 243 244 if (Modifier.isStatic(m_callerMemberInfo.getModifiers())) { 246 visitInsn(ACONST_NULL); 247 } else { 248 visitVarInsn(ALOAD, 0); 249 } 250 251 super.visitMethodInsn( 253 INVOKESTATIC, 254 joinPointClassName, 255 INVOKE_METHOD_NAME, 256 TransformationUtil.getInvokeSignatureForFieldJoinPoints( 257 fieldInfo.getModifiers(), fieldDesc, m_callerClassName, className 258 ) 259 ); 260 261 m_ctx.addEmittedJoinPoint( 263 new EmittedJoinPoint( 264 JoinPointType.FIELD_GET_INT, 265 m_callerClassName, 266 m_callerMethodName, 267 m_callerMethodDesc, 268 m_callerMemberInfo.getModifiers(), 269 className, 270 fieldName, 271 fieldDesc, 272 fieldInfo.getModifiers(), 273 joinPointHash, 274 joinPointClassName, 275 m_lastLabelForLineNumber 276 ) 277 ); 278 } 279 } 280 281 291 private void handleFieldModification(final FieldInfo fieldInfo, 292 final int opcode, 293 final String className, 294 final String fieldName, 295 final String fieldDesc, 296 final int joinPointHash) { 297 if (m_callerMemberInfo == null) { 298 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 299 return; 300 } 301 302 ExpressionContext ctx = new ExpressionContext(PointcutType.SET, fieldInfo, m_callerMemberInfo); 303 304 if (fieldFilter(m_ctx.getDefinitions(), ctx, fieldInfo)) { 305 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 306 } else { 307 m_ctx.markAsAdvised(); 308 309 String joinPointClassName = TransformationUtil.getJoinPointClassName( 310 m_callerClassName, 311 m_callerMethodName, 312 m_callerMethodDesc, 313 className, 314 JoinPointType.FIELD_SET_INT, 315 joinPointHash 316 ); 317 318 if (Modifier.isStatic(m_callerMemberInfo.getModifiers())) { 321 visitInsn(ACONST_NULL); 322 } else { 323 visitVarInsn(ALOAD, 0); 324 } 325 326 super.visitMethodInsn( 328 INVOKESTATIC, 329 joinPointClassName, 330 INVOKE_METHOD_NAME, 331 TransformationUtil.getInvokeSignatureForFieldJoinPoints( 332 fieldInfo.getModifiers(), fieldDesc, m_callerClassName, className 333 ) 334 ); 335 336 final int sort = Type.getType(fieldDesc).getSort(); 337 if (sort != Type.LONG && sort != Type.DOUBLE) { 338 super.visitInsn(POP); 339 } else { 340 super.visitInsn(POP2); 342 } 343 344 m_ctx.addEmittedJoinPoint( 346 new EmittedJoinPoint( 347 JoinPointType.FIELD_SET_INT, 348 m_callerClassName, 349 m_callerMethodName, 350 m_callerMethodDesc, 351 m_callerMemberInfo.getModifiers(), 352 className, 353 fieldName, 354 fieldDesc, 355 fieldInfo.getModifiers(), 356 joinPointHash, 357 joinPointClassName, 358 m_lastLabelForLineNumber 359 ) 360 ); 361 } 362 } 363 364 374 private FieldInfo getFieldInfo(final ClassInfo classInfo, 375 final String className, 376 final String fieldName, 377 final String fieldDesc, 378 final int joinPointHash) { 379 FieldInfo fieldInfo = classInfo.getField(joinPointHash); 380 if (fieldInfo == null) { 381 throw new RuntimeException ( 382 "field info metadata structure could not be build for field: " 383 + className 384 + '.' 385 + fieldName 386 + ':' 387 + fieldDesc 388 ); 389 } 390 return fieldInfo; 391 } 392 393 401 public boolean fieldFilter(final Set definitions, 402 final ExpressionContext ctx, 403 final FieldInfo fieldInfo) { 404 if (fieldInfo.getName().startsWith(ORIGINAL_METHOD_PREFIX)) { 405 return true; 406 } 407 for (Iterator it = definitions.iterator(); it.hasNext();) { 408 if (((SystemDefinition) it.next()).hasPointcut(ctx)) { 409 return false; 410 } else { 411 continue; 412 } 413 } 414 return true; 415 } 416 } 417 } | Popular Tags |