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.Label; 16 import org.codehaus.aspectwerkz.definition.SystemDefinition; 17 import org.codehaus.aspectwerkz.expression.ExpressionContext; 18 import org.codehaus.aspectwerkz.expression.PointcutType; 19 import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType; 20 import org.codehaus.aspectwerkz.reflect.ClassInfo; 21 import org.codehaus.aspectwerkz.reflect.MethodInfo; 22 import org.codehaus.aspectwerkz.reflect.MemberInfo; 23 import org.codehaus.aspectwerkz.reflect.ClassInfoHelper; 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 51 public class MethodCallVisitor extends ClassAdapter implements TransformationConstants { 52 53 private final ContextImpl m_ctx; 54 private final ClassLoader m_loader; 55 private final ClassInfo m_callerClassInfo; 56 57 private Label m_lastLabelForLineNumber = EmittedJoinPoint.NO_LINE_NUMBER; 58 59 67 public MethodCallVisitor(final ClassVisitor cv, 68 final ClassLoader loader, 69 final ClassInfo classInfo, 70 final Context ctx) { 71 super(cv); 72 m_loader = loader; 73 m_callerClassInfo = classInfo; 74 m_ctx = (ContextImpl) ctx; 75 } 76 77 87 public CodeVisitor visitMethod(final int access, 88 final String name, 89 final String desc, 90 final String [] exceptions, 91 final Attribute attrs) { 92 93 if (name.startsWith(WRAPPER_METHOD_PREFIX) || 94 Modifier.isNative(access) || 95 Modifier.isAbstract(access)) { 96 return super.visitMethod(access, name, desc, exceptions, attrs); 97 } 98 99 CodeVisitor mv = cv.visitMethod(access, name, desc, exceptions, attrs); 100 return mv == null ? null : new ReplaceInvokeInstructionCodeAdapter( 101 mv, 102 m_loader, 103 m_callerClassInfo, 104 m_ctx.getClassName(), 105 name, 106 desc 107 ); 108 } 109 110 116 public class ReplaceInvokeInstructionCodeAdapter extends AfterObjectInitializationCodeAdapter { 117 118 private final ClassLoader m_loader; 119 private final ClassInfo m_callerClassInfo; 120 private final String m_callerClassName; 121 private final String m_callerMethodName; 122 private final String m_callerMethodDesc; 123 private final MemberInfo m_callerMemberInfo; 124 125 135 public ReplaceInvokeInstructionCodeAdapter(final CodeVisitor ca, 136 final ClassLoader loader, 137 final ClassInfo callerClassInfo, 138 final String callerClassName, 139 final String callerMethodName, 140 final String callerMethodDesc) { 141 super(ca, callerMethodName); 142 m_loader = loader; 143 m_callerClassInfo = callerClassInfo; 144 m_callerClassName = callerClassName; 145 m_callerMethodName = callerMethodName; 146 m_callerMethodDesc = callerMethodDesc; 147 148 if (CLINIT_METHOD_NAME.equals(callerMethodName)) { 149 m_callerMemberInfo = m_callerClassInfo.staticInitializer(); 150 } else if (INIT_METHOD_NAME.equals(callerMethodName)) { 151 int hash = AsmHelper.calculateConstructorHash(m_callerMethodDesc); 152 m_callerMemberInfo = m_callerClassInfo.getConstructor(hash); 153 } else { 154 int hash = AsmHelper.calculateMethodHash(m_callerMethodName, m_callerMethodDesc); 155 m_callerMemberInfo = m_callerClassInfo.getMethod(hash); 156 } 157 } 158 159 164 public void visitLabel(Label label) { 165 m_lastLabelForLineNumber = label; 166 super.visitLabel(label); 167 } 168 169 177 public void visitMethodInsn(final int opcode, 178 String calleeClassName, 179 final String calleeMethodName, 180 final String calleeMethodDesc) { 181 182 if (m_callerMemberInfo == null) { 183 System.err.println( 184 "AW::WARNING " + 185 "metadata structure could not be build for method [" 186 + m_callerClassInfo.getName().replace('/', '.') 187 + '.' + m_callerMethodName + ':' + m_callerMethodDesc + ']' 188 ); 189 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 190 return; 191 } 192 193 if (INIT_METHOD_NAME.equals(calleeMethodName) || 194 CLINIT_METHOD_NAME.equals(calleeMethodName) || 195 calleeMethodName.startsWith(ASPECTWERKZ_PREFIX) 196 || calleeClassName.endsWith(JOIN_POINT_CLASS_SUFFIX) 197 ){super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 199 return; 200 } 201 202 if (opcode == INVOKESPECIAL 204 && !calleeClassName.equals(m_callerClassName) 205 && ClassInfoHelper.extendsSuperClass(m_callerClassInfo, calleeClassName.replace('/', '.'))) { 206 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 207 return; 208 } 209 210 if (!m_isObjectInitialized) { 212 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 213 return; 214 } 215 216 int joinPointHash = AsmHelper.calculateMethodHash(calleeMethodName, calleeMethodDesc); 217 218 ClassInfo classInfo = AsmClassInfo.getClassInfo(calleeClassName, m_loader); 219 MethodInfo calleeMethodInfo = classInfo.getMethod(joinPointHash); 220 221 if (calleeMethodInfo == null) { 222 System.err.println( 223 "AW::WARNING " + 224 "metadata structure could not be build for method [" 225 + classInfo.getName().replace('/', '.') 226 + '.' + calleeMethodName + ':' + calleeMethodDesc 227 + "] when parsing method [" 228 + m_callerClassInfo.getName() + '.' + m_callerMethodName + "(..)]" 229 ); 230 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 232 return; 233 } 234 235 ExpressionContext ctx = new ExpressionContext(PointcutType.CALL, calleeMethodInfo, m_callerMemberInfo); 236 237 if (methodFilter(m_ctx.getDefinitions(), ctx, calleeMethodInfo)) { 238 super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); 239 } else { 240 m_ctx.markAsAdvised(); 241 242 String joinPointClassName = TransformationUtil.getJoinPointClassName( 243 m_callerClassName, 244 m_callerMethodName, 245 m_callerMethodDesc, 246 calleeClassName, 247 JoinPointType.METHOD_CALL_INT, 248 joinPointHash 249 ); 250 251 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.getInvokeSignatureForCodeJoinPoints( 265 calleeMethodInfo.getModifiers(), calleeMethodDesc, 266 m_callerClassName, calleeClassName 267 ) 268 ); 269 270 int modifiers = calleeMethodInfo.getModifiers(); 273 if (opcode == INVOKEINTERFACE) { 274 modifiers = modifiers | MODIFIER_INVOKEINTERFACE; 275 } 276 m_ctx.addEmittedJoinPoint( 277 new EmittedJoinPoint( 278 JoinPointType.METHOD_CALL_INT, 279 m_callerClassName, 280 m_callerMethodName, 281 m_callerMethodDesc, 282 m_callerMemberInfo.getModifiers(), 283 calleeClassName, 284 calleeMethodName, 285 calleeMethodDesc, 286 modifiers, 287 joinPointHash, 288 joinPointClassName, 289 m_lastLabelForLineNumber 290 ) 291 ); 292 } 293 } 294 295 305 public boolean methodFilter(final Set definitions, 306 final ExpressionContext ctx, 307 final MethodInfo calleeMethodInfo) { 308 if (calleeMethodInfo.getName().equals(INIT_METHOD_NAME) || 309 calleeMethodInfo.getName().equals(CLINIT_METHOD_NAME) || 310 calleeMethodInfo.getName().startsWith(ORIGINAL_METHOD_PREFIX)) { 311 return true; 312 } 313 for (Iterator it = definitions.iterator(); it.hasNext();) { 314 if (((SystemDefinition) it.next()).hasPointcut(ctx)) { 315 return false; 316 } else { 317 continue; 318 } 319 } 320 return true; 321 } 322 } 323 } | Popular Tags |