/** * Visits the methods. * * @param access * @param name * @param desc * @param signature * @param exceptions * @return */ public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature, final String[] exceptions) { if (INIT_METHOD_NAME.equals(name) || CLINIT_METHOD_NAME.equals(name) || name.startsWith(ASPECTWERKZ_PREFIX) || name.startsWith(SYNTHETIC_MEMBER_PREFIX) || name.startsWith(WRAPPER_METHOD_PREFIX) || (AdvisableImpl.ADD_ADVICE_METHOD_NAME.equals(name) && AdvisableImpl.ADD_ADVICE_METHOD_DESC.equals(desc)) || (AdvisableImpl.REMOVE_ADVICE_METHOD_NAME.equals(name) && AdvisableImpl.REMOVE_ADVICE_METHOD_DESC.equals(desc))) { return cv.visitMethod(access, name, desc, signature, exceptions); } int hash = AsmHelper.calculateMethodHash(name, desc); MethodInfo methodInfo = m_classInfo.getMethod(hash); if (methodInfo == null) { System.err.println( "AW::WARNING " + "metadata structure could not be build for method [" + m_classInfo.getName().replace('/', '.') + '.' + name + ':' + desc + ']'); // bail out return cv.visitMethod(access, name, desc, signature, exceptions); } ExpressionContext ctx = new ExpressionContext(PointcutType.EXECUTION, methodInfo, methodInfo); if (methodFilter(m_ctx.getDefinitions(), ctx, methodInfo)) { return cv.visitMethod(access, name, desc, signature, exceptions); } else { String prefixedOriginalName = TransformationUtil.getPrefixedOriginalMethodName(name, m_declaringTypeName); if (m_addedMethods.contains( AlreadyAddedMethodAdapter.getMethodKey(prefixedOriginalName, desc))) { return cv.visitMethod(access, name, desc, signature, exceptions); } m_ctx.markAsAdvised(); // create the proxy for the original method final MethodVisitor proxyMethod = createProxyMethod(access, name, desc, signature, exceptions, methodInfo); int modifiers = ACC_SYNTHETIC; if (Modifier.isStatic(access)) { modifiers |= ACC_STATIC; } // prefix the original method and make sure we copy method annotations to the proxyMethod // while keeping the body for the prefixed method return new MethodAdapter( cv.visitMethod(modifiers, prefixedOriginalName, desc, signature, exceptions)) { public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return new AsmCopyAdapter.CopyAnnotationAdapter( super.visitAnnotation(desc, visible), proxyMethod.visitAnnotation(desc, visible)); } public AnnotationVisitor visitParameterAnnotation( int parameter, String desc, boolean visible) { return new AsmCopyAdapter.CopyAnnotationAdapter( super.visitParameterAnnotation(parameter, desc, visible), proxyMethod.visitParameterAnnotation(parameter, desc, visible)); } public void visitAttribute(Attribute attr) { super.visitAttribute(attr); proxyMethod.visitAttribute(attr); } }; } }
/** * Creates the "proxy method", e.g. the method that has the same name and signature as the * original method but a completely other implementation. * * @param access * @param name * @param desc * @param signature * @param exceptions * @param methodInfo * @return the method visitor */ private MethodVisitor createProxyMethod( final int access, final String name, final String desc, final String signature, final String[] exceptions, final MethodInfo methodInfo) { MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); // load "this" ie callee if target method is not static if (!Modifier.isStatic(access)) { mv.visitVarInsn(ALOAD, 0); } // load args AsmHelper.loadArgumentTypes(mv, Type.getArgumentTypes(desc), Modifier.isStatic(access)); // load "this" ie caller or null if method is static if (Modifier.isStatic(access)) { mv.visitInsn(ACONST_NULL); } else { mv.visitVarInsn(ALOAD, 0); } int joinPointHash = AsmHelper.calculateMethodHash(name, desc); String joinPointClassName = TransformationUtil.getJoinPointClassName( m_declaringTypeName, name, desc, m_declaringTypeName, JoinPointType.METHOD_EXECUTION_INT, joinPointHash); // TODO: should we provide some sort of option to do JITgen when weaving instead of when loading // ? // use case: offline full packaging and alike mv.visitMethodInsn( INVOKESTATIC, joinPointClassName, INVOKE_METHOD_NAME, TransformationUtil.getInvokeSignatureForCodeJoinPoints( access, desc, m_declaringTypeName, m_declaringTypeName)); AsmHelper.addReturnStatement(mv, Type.getReturnType(desc)); mv.visitMaxs(0, 0); // emit the joinpoint m_ctx.addEmittedJoinPoint( new EmittedJoinPoint( JoinPointType.METHOD_EXECUTION_INT, m_declaringTypeName, name, desc, access, m_declaringTypeName, name, desc, access, joinPointHash, joinPointClassName, EmittedJoinPoint.NO_LINE_NUMBER)); return mv; }