1 8 package org.codehaus.aspectwerkz.transform.inlining.weaver; 9 10 import org.objectweb.asm.ClassAdapter; 11 import org.objectweb.asm.ClassVisitor; 12 import org.objectweb.asm.CodeVisitor; 13 import org.objectweb.asm.Attribute; 14 import org.objectweb.asm.CodeAdapter; 15 import org.objectweb.asm.Type; 16 import org.objectweb.asm.Label; 17 import org.codehaus.aspectwerkz.definition.SystemDefinition; 18 import org.codehaus.aspectwerkz.expression.ExpressionContext; 19 import org.codehaus.aspectwerkz.expression.PointcutType; 20 import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType; 21 import org.codehaus.aspectwerkz.reflect.ClassInfo; 22 import org.codehaus.aspectwerkz.reflect.FieldInfo; 23 import org.codehaus.aspectwerkz.reflect.MemberInfo; 24 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo; 25 import org.codehaus.aspectwerkz.transform.Context; 26 import org.codehaus.aspectwerkz.transform.TransformationUtil; 27 import org.codehaus.aspectwerkz.transform.TransformationConstants; 28 import org.codehaus.aspectwerkz.transform.inlining.compiler.AbstractJoinPointCompiler; 29 import org.codehaus.aspectwerkz.transform.inlining.ContextImpl; 30 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper; 31 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint; 32 33 import java.lang.reflect.Modifier ; 34 import java.util.Iterator ; 35 import java.util.Set ; 36 37 43 public class FieldSetFieldGetVisitor extends ClassAdapter implements TransformationConstants { 44 45 private final ContextImpl m_ctx; 46 private final ClassLoader m_loader; 47 private final ClassInfo m_callerClassInfo; 48 49 private Label m_lastLabelForLineNumber = EmittedJoinPoint.NO_LINE_NUMBER; 50 51 59 public FieldSetFieldGetVisitor(final ClassVisitor cv, 60 final ClassLoader loader, 61 final ClassInfo classInfo, 62 final Context ctx) { 63 super(cv); 64 m_loader = loader; 65 m_callerClassInfo = classInfo; 66 m_ctx = (ContextImpl) ctx; 67 } 68 69 79 public CodeVisitor visitMethod(final int access, 80 final String name, 81 final String desc, 82 final String [] exceptions, 83 final Attribute attrs) { 84 85 if (name.startsWith(WRAPPER_METHOD_PREFIX)) { 86 return super.visitMethod(access, name, desc, exceptions, attrs); 87 } 88 89 CodeVisitor mv = cv.visitMethod(access, name, desc, exceptions, attrs); 90 return mv == null ? null : new ReplacePutFieldAndGetFieldInstructionCodeAdapter( 91 mv, 92 m_loader, 93 m_callerClassInfo, 94 m_ctx.getClassName(), 95 name, 96 desc 97 ); 98 } 99 100 106 public class ReplacePutFieldAndGetFieldInstructionCodeAdapter extends AfterObjectInitializationCodeAdapter { 107 108 private final ClassLoader m_loader; 109 private final ClassInfo m_callerClassInfo; 110 private final String m_callerClassName; 111 private final String m_callerMethodName; 112 private final String m_callerMethodDesc; 113 private final MemberInfo m_callerMemberInfo; 114 115 125 public ReplacePutFieldAndGetFieldInstructionCodeAdapter(final CodeVisitor ca, 126 final ClassLoader loader, 127 final ClassInfo callerClassInfo, 128 final String callerClassName, 129 final String callerMethodName, 130 final String callerMethodDesc) { 131 super(ca, callerMethodName); 132 m_loader = loader; 133 m_callerClassInfo = callerClassInfo; 134 m_callerClassName = callerClassName; 135 m_callerMethodName = callerMethodName; 136 m_callerMethodDesc = callerMethodDesc; 137 138 if (CLINIT_METHOD_NAME.equals(m_callerMethodName)) { 139 m_callerMemberInfo = m_callerClassInfo.staticInitializer(); 140 } else if (INIT_METHOD_NAME.equals(m_callerMethodName)) { 141 int hash = AsmHelper.calculateConstructorHash(m_callerMethodDesc); 142 m_callerMemberInfo = m_callerClassInfo.getConstructor(hash); 143 } else { 144 int hash = AsmHelper.calculateMethodHash(m_callerMethodName, m_callerMethodDesc); 145 m_callerMemberInfo = m_callerClassInfo.getMethod(hash); 146 } 147 if (m_callerMemberInfo == null) { 148 System.err.println( 149 "AW::WARNING " + 150 "metadata structure could not be build for method [" 151 + m_callerClassInfo.getName().replace('/', '.') 152 + '.' + m_callerMethodName + ':' + m_callerMethodDesc + ']' 153 ); 154 } 155 } 156 157 162 public void visitLabel(Label label) { 163 m_lastLabelForLineNumber = label; 164 super.visitLabel(label); 165 } 166 167 175 public void visitFieldInsn(final int opcode, 176 final String className, 177 final String fieldName, 178 final String fieldDesc) { 179 180 if (className.endsWith(AbstractJoinPointCompiler.JOIN_POINT_CLASS_SUFFIX) || 181 fieldName.startsWith(ASPECTWERKZ_PREFIX) || 182 fieldName.startsWith(SYNTHETIC_MEMBER_PREFIX) || fieldName.equals(SERIAL_VERSION_UID_FIELD_NAME) ) { 185 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 186 return; 187 } 188 189 if (!m_isObjectInitialized) { 191 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 192 return; 193 } 194 195 196 final Type fieldType = Type.getType(fieldDesc); 197 final int joinPointHash = AsmHelper.calculateFieldHash(fieldName, fieldDesc); 198 final ClassInfo classInfo = AsmClassInfo.getClassInfo(className, m_loader); 199 final FieldInfo fieldInfo = getFieldInfo(classInfo, className, fieldName, fieldDesc, joinPointHash); 200 201 if (opcode == PUTFIELD || opcode == PUTSTATIC) { 202 handleFieldModification(fieldInfo, opcode, className, fieldName, fieldDesc, joinPointHash); 203 } else if (opcode == GETFIELD || opcode == GETSTATIC) { 204 handleFieldAccess(fieldInfo, opcode, className, fieldName, fieldDesc, joinPointHash, fieldType); 205 } else { 206 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 207 } 208 } 209 210 221 private void handleFieldAccess(final FieldInfo fieldInfo, 222 final int opcode, 223 final String className, 224 final String fieldName, 225 final String fieldDesc, 226 int joinPointHash, 227 final Type fieldType) { 228 if (m_callerMemberInfo == null) { 229 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 230 return; 231 } 232 233 ExpressionContext ctx = new ExpressionContext(PointcutType.GET, fieldInfo, m_callerMemberInfo); 234 235 if (fieldFilter(m_ctx.getDefinitions(), ctx, fieldInfo)) { 236 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 237 } else { 238 m_ctx.markAsAdvised(); 239 240 String joinPointClassName = TransformationUtil.getJoinPointClassName( 241 m_callerClassName, 242 m_callerMethodName, 243 m_callerMethodDesc, 244 className, 245 JoinPointType.FIELD_GET_INT, 246 joinPointHash 247 ); 248 249 AsmHelper.addDefaultValue(this, fieldType); 251 252 if (Modifier.isStatic(m_callerMemberInfo.getModifiers())) { 254 visitInsn(ACONST_NULL); 255 } else { 256 visitVarInsn(ALOAD, 0); 257 } 258 259 super.visitMethodInsn( 261 INVOKESTATIC, 262 joinPointClassName, 263 INVOKE_METHOD_NAME, 264 TransformationUtil.getInvokeSignatureForFieldJoinPoints( 265 fieldInfo.getModifiers(), fieldDesc, m_callerClassName, className 266 ) 267 ); 268 269 m_ctx.addEmittedJoinPoint( 271 new EmittedJoinPoint( 272 JoinPointType.FIELD_GET_INT, 273 m_callerClassName, 274 m_callerMethodName, 275 m_callerMethodDesc, 276 m_callerMemberInfo.getModifiers(), 277 className, 278 fieldName, 279 fieldDesc, 280 fieldInfo.getModifiers(), 281 joinPointHash, 282 joinPointClassName, 283 m_lastLabelForLineNumber 284 ) 285 ); 286 } 287 } 288 289 299 private void handleFieldModification(final FieldInfo fieldInfo, 300 final int opcode, 301 final String className, 302 final String fieldName, 303 final String fieldDesc, 304 final int joinPointHash) { 305 if (m_callerMemberInfo == null) { 306 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 307 return; 308 } 309 310 ExpressionContext ctx = new ExpressionContext(PointcutType.SET, fieldInfo, m_callerMemberInfo); 311 312 if (fieldFilter(m_ctx.getDefinitions(), ctx, fieldInfo)) { 313 super.visitFieldInsn(opcode, className, fieldName, fieldDesc); 314 } else { 315 m_ctx.markAsAdvised(); 316 317 String joinPointClassName = TransformationUtil.getJoinPointClassName( 318 m_callerClassName, 319 m_callerMethodName, 320 m_callerMethodDesc, 321 className, 322 JoinPointType.FIELD_SET_INT, 323 joinPointHash 324 ); 325 326 if (Modifier.isStatic(m_callerMemberInfo.getModifiers())) { 329 visitInsn(ACONST_NULL); 330 } else { 331 visitVarInsn(ALOAD, 0); 332 } 333 334 super.visitMethodInsn( 336 INVOKESTATIC, 337 joinPointClassName, 338 INVOKE_METHOD_NAME, 339 TransformationUtil.getInvokeSignatureForFieldJoinPoints( 340 fieldInfo.getModifiers(), fieldDesc, m_callerClassName, className 341 ) 342 ); 343 344 final int sort = Type.getType(fieldDesc).getSort(); 345 if (sort != Type.LONG && sort != Type.DOUBLE) { 346 super.visitInsn(POP); 347 } else { 348 super.visitInsn(POP2); 350 } 351 352 m_ctx.addEmittedJoinPoint( 354 new EmittedJoinPoint( 355 JoinPointType.FIELD_SET_INT, 356 m_callerClassName, 357 m_callerMethodName, 358 m_callerMethodDesc, 359 m_callerMemberInfo.getModifiers(), 360 className, 361 fieldName, 362 fieldDesc, 363 fieldInfo.getModifiers(), 364 joinPointHash, 365 joinPointClassName, 366 m_lastLabelForLineNumber 367 ) 368 ); 369 } 370 } 371 372 382 private FieldInfo getFieldInfo(final ClassInfo classInfo, 383 final String className, 384 final String fieldName, 385 final String fieldDesc, 386 final int joinPointHash) { 387 FieldInfo fieldInfo = classInfo.getField(joinPointHash); 388 if (fieldInfo == null) { 389 throw new Error ( 390 "field info metadata structure could not be build for field: " 391 + className 392 + '.' 393 + fieldName 394 + ':' 395 + fieldDesc 396 ); 397 } 398 return fieldInfo; 399 } 400 401 409 public boolean fieldFilter(final Set definitions, 410 final ExpressionContext ctx, 411 final FieldInfo fieldInfo) { 412 if (fieldInfo.getName().startsWith(ORIGINAL_METHOD_PREFIX)) { 413 return true; 414 } 415 for (Iterator it = definitions.iterator(); it.hasNext();) { 416 if (((SystemDefinition) it.next()).hasPointcut(ctx)) { 417 return false; 418 } else { 419 continue; 420 } 421 } 422 return true; 423 } 424 } 425 } | Popular Tags |