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.MethodVisitor; 9 import com.tc.asm.Label; 10 11 import com.tc.aspectwerkz.definition.SystemDefinition; 12 import com.tc.aspectwerkz.joinpoint.management.JoinPointType; 13 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo; 14 import com.tc.aspectwerkz.reflect.ClassInfo; 15 import com.tc.aspectwerkz.reflect.MemberInfo; 16 import com.tc.aspectwerkz.reflect.ClassInfoHelper; 17 import com.tc.aspectwerkz.reflect.MethodInfo; 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.expression.ExpressionContext; 24 import com.tc.aspectwerkz.expression.PointcutType; 25 26 import java.lang.reflect.Modifier ; 27 import java.util.Iterator ; 28 import java.util.Set ; 29 30 44 public class MethodCallVisitor extends ClassAdapter implements TransformationConstants { 45 46 private final InstrumentationContext m_ctx; 47 private final ClassLoader m_loader; 48 private final ClassInfo m_callerClassInfo; 49 50 private Label m_lastLabelForLineNumber = EmittedJoinPoint.NO_LINE_NUMBER; 51 52 60 public MethodCallVisitor(final ClassVisitor cv, 61 final ClassLoader loader, 62 final ClassInfo classInfo, 63 final InstrumentationContext ctx) { 64 super(cv); 65 m_loader = loader; 66 m_callerClassInfo = classInfo; 67 m_ctx = (InstrumentationContext) ctx; 68 } 69 70 80 public MethodVisitor visitMethod(final int access, 81 final String name, 82 final String desc, 83 final String signature, 84 final String [] exceptions) { 85 86 if (name.startsWith(WRAPPER_METHOD_PREFIX) || 87 Modifier.isNative(access) || 88 Modifier.isAbstract(access)) { 89 return super.visitMethod(access, name, desc, signature, exceptions); 90 } 91 92 MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); 93 return mv == null ? null : new ReplaceInvokeInstructionCodeAdapter( 94 mv, 95 m_loader, 96 m_callerClassInfo, 97 m_ctx.getClassName(), 98 name, 99 desc 100 ); 101 } 102 103 109 public class ReplaceInvokeInstructionCodeAdapter extends AfterObjectInitializationCodeAdapter { 110 111 private final ClassLoader m_loader; 112 private final ClassInfo m_callerClassInfo; 113 private final String m_callerClassName; 114 private final String m_callerMethodName; 115 private final String m_callerMethodDesc; 116 private final MemberInfo m_callerMemberInfo; 117 118 128 public ReplaceInvokeInstructionCodeAdapter(final MethodVisitor ca, 129 final ClassLoader loader, 130 final ClassInfo callerClassInfo, 131 final String callerClassName, 132 final String callerMethodName, 133 final String callerMethodDesc) { 134 super(ca, callerMethodName); 135 m_loader = loader; 136 m_callerClassInfo = callerClassInfo; 137 m_callerClassName = callerClassName; 138 m_callerMethodName = callerMethodName; 139 m_callerMethodDesc = callerMethodDesc; 140 141 if (CLINIT_METHOD_NAME.equals(callerMethodName)) { 142 m_callerMemberInfo = m_callerClassInfo.staticInitializer(); 143 } else if (INIT_METHOD_NAME.equals(callerMethodName)) { 144 int hash = AsmHelper.calculateConstructorHash(m_callerMethodDesc); 145 m_callerMemberInfo = m_callerClassInfo.getConstructor(hash); 146 } else { 147 int hash = AsmHelper.calculateMethodHash(m_callerMethodName, m_callerMethodDesc); 148 m_callerMemberInfo = m_callerClassInfo.getMethod(hash); 149 } 150 } 151 152 157 public void visitLabel(Label label) { 158 m_lastLabelForLineNumber = label; 159 super.visitLabel(label); 160 } 161 162 170 public void visitMethodInsn(final int opcode, 171 String calleeClassName, 172 final String calleeMethodName, 173 final String calleeMethodDesc) { 174 175 if (m_callerMemberInfo == null) { 176 System.err.println( 177 "AW::WARNING " + 178 "metadata structure could not be build for method [" 179 + m_callerClassInfo.getName().replace('/', '.') 180 + '.' + m_callerMethodName + ':' + m_callerMethodDesc + ']' 181 ); 182 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 183 return; 184 } 185 186 if (INIT_METHOD_NAME.equals(calleeMethodName) || 187 CLINIT_METHOD_NAME.equals(calleeMethodName) || 188 calleeMethodName.startsWith(ASPECTWERKZ_PREFIX) 189 || calleeClassName.endsWith(JOIN_POINT_CLASS_SUFFIX)) { 190 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 191 return; 192 } 193 194 if (opcode == INVOKESPECIAL 196 && !calleeClassName.equals(m_callerClassName) 197 && ClassInfoHelper.extendsSuperClass(m_callerClassInfo, calleeClassName.replace('/', '.'))) { 198 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 199 return; 200 } 201 202 if (!m_isObjectInitialized) { 204 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 205 return; 206 } 207 208 int joinPointHash = AsmHelper.calculateMethodHash(calleeMethodName, calleeMethodDesc); 209 210 ClassInfo classInfo = AsmClassInfo.getClassInfo(calleeClassName, m_loader); 211 MethodInfo calleeMethodInfo = classInfo.getMethod(joinPointHash); 212 213 if (calleeMethodInfo == null) { 214 System.err.println( 215 "AW::WARNING " + 216 "metadata structure could not be build for method [" 217 + classInfo.getName().replace('/', '.') 218 + '.' + calleeMethodName + ':' + calleeMethodDesc 219 + "] when parsing method [" 220 + m_callerClassInfo.getName() + '.' + m_callerMethodName + "(..)]" 221 ); 222 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 224 return; 225 } 226 227 ExpressionContext ctx = new ExpressionContext(PointcutType.CALL, calleeMethodInfo, m_callerMemberInfo); 228 229 if (methodFilter(m_ctx.getDefinitions(), ctx, calleeMethodInfo)) { 230 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 231 } else { 232 m_ctx.markAsAdvised(); 233 234 String joinPointClassName = TransformationUtil.getJoinPointClassName( 235 m_callerClassName, 236 m_callerMethodName, 237 m_callerMethodDesc, 238 calleeClassName, 239 JoinPointType.METHOD_CALL_INT, 240 joinPointHash 241 ); 242 243 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.getInvokeSignatureForCodeJoinPoints( 257 calleeMethodInfo.getModifiers(), calleeMethodDesc, 258 m_callerClassName, calleeClassName 259 ) 260 ); 261 262 int modifiers = calleeMethodInfo.getModifiers(); 265 if (opcode == INVOKEINTERFACE) { 266 modifiers = modifiers | MODIFIER_INVOKEINTERFACE; 267 } 268 m_ctx.addEmittedJoinPoint( 269 new EmittedJoinPoint( 270 JoinPointType.METHOD_CALL_INT, 271 m_callerClassName, 272 m_callerMethodName, 273 m_callerMethodDesc, 274 m_callerMemberInfo.getModifiers(), 275 calleeClassName, 276 calleeMethodName, 277 calleeMethodDesc, 278 modifiers, 279 joinPointHash, 280 joinPointClassName, 281 m_lastLabelForLineNumber 282 ) 283 ); 284 } 285 } 286 287 297 public boolean methodFilter(final Set definitions, 298 final ExpressionContext ctx, 299 final MethodInfo calleeMethodInfo) { 300 if (calleeMethodInfo.getName().equals(INIT_METHOD_NAME) || 301 calleeMethodInfo.getName().equals(CLINIT_METHOD_NAME) || 302 calleeMethodInfo.getName().startsWith(ORIGINAL_METHOD_PREFIX)) { 303 return true; 304 } 305 for (Iterator it = definitions.iterator(); it.hasNext();) { 306 if (((SystemDefinition) it.next()).hasPointcut(ctx)) { 307 return false; 308 } else { 309 continue; 310 } 311 } 312 return true; 313 } 314 } 315 } | Popular Tags |