package com.ikokoon.serenity.instrumentation.dependency; import org.apache.log4j.Logger; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodAdapter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import com.ikokoon.serenity.Collector; import com.ikokoon.serenity.instrumentation.VisitorFactory; import com.ikokoon.toolkit.Toolkit; /** * This class visits the method instructions and collects dependency metrics on the method. * * @author Michael Couck * @since 18.07.09 * @version 01.00 */ public class DependencyMethodAdapter extends MethodAdapter implements Opcodes { /** The logger for the class. */ private Logger logger = Logger.getLogger(this.getClass()); /** The name of the class that this method adapter parsing for dependency metrics. */ private String className; /** The name of the method. */ private String methodName; /** The byte code description of the method, i.e. the signature. */ private String methodDescription; /** * The constructor initialises a {@link DependencyMethodAdapter} and takes all the interesting items for the method that are used for the * collection of the data. * * @param methodVisitor * the method visitor of the parent * @param className * the name of the class the method belongs to * @param methodName * the name of the method * @param methodDescription * the description of the method */ public DependencyMethodAdapter(MethodVisitor methodVisitor, Integer access, String className, String methodName, String methodDescription) { super(methodVisitor); this.className = Toolkit.slashToDot(className); this.methodName = methodName; this.methodDescription = methodDescription; Type[] argumentTypes = Type.getArgumentTypes(methodDescription); for (Type argumentType : argumentTypes) { if (argumentType.getSort() == Type.OBJECT) { Collector.collectEfferentAndAfferent(className, argumentType.getClassName()); } if (argumentType.getSort() == Type.ARRAY) { visitArray(argumentType); } } if (logger.isDebugEnabled()) { logger.debug("Class name : " + className + ", name : " + methodName + ", desc : " + methodDescription); } } /** * This method recursively visits array types. * * @param argumentType * the type to visit */ private void visitArray(Type argumentType) { if (argumentType.getSort() == Type.OBJECT) { Collector.collectEfferentAndAfferent(className, argumentType.getClassName()); } if (argumentType.getSort() == Type.ARRAY) { argumentType = argumentType.getElementType(); visitArray(argumentType); } } /** * {@inheritDoc} */ public AnnotationVisitor visitAnnotation(String desc, boolean visible) { logger.debug("visitAnnotation : " + desc + ", " + visible); VisitorFactory.getSignatureVisitor(className, desc); return this.mv.visitAnnotation(desc, visible); } /** * {@inheritDoc} */ public void visitFieldInsn(int opcode, String owner, String name, String desc) { if (logger.isDebugEnabled()) { logger.debug("visitFieldInst : " + owner + ", " + name + ", " + desc); } VisitorFactory.getSignatureVisitor(className, desc); this.mv.visitFieldInsn(opcode, owner, name, desc); } /** * {@inheritDoc} */ public void visitLineNumber(int lineNumber, Label label) { if (logger.isDebugEnabled()) { logger.info("visitLineNumber : " + className + ", " + lineNumber + ", " + label + ", " + label.getOffset() + ", " + className + ", " + methodName); } Collector.collectLine(className, methodName, methodDescription, lineNumber); this.mv.visitLineNumber(lineNumber, label); } /** * {@inheritDoc} */ public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { if (logger.isDebugEnabled()) { logger.debug("visitLocalVariable : " + name + ", " + desc + ", " + signature + ", " + start + ", " + end + ", " + index); } VisitorFactory.getSignatureVisitor(className, desc); if (signature != null) { VisitorFactory.getSignatureVisitor(className, signature); } this.mv.visitLocalVariable(name, desc, signature, start, end, index); } /** * {@inheritDoc} */ public void visitMethodInsn(int opcode, String owner, String name, String desc) { if (logger.isDebugEnabled()) { logger.debug("visitMethodInst : " + opcode + ", " + owner + ", " + name + ", " + desc); } VisitorFactory.getSignatureVisitor(className, desc); this.mv.visitMethodInsn(opcode, owner, name, desc); } /** * {@inheritDoc} */ public void visitMultiANewArrayInsn(String desc, int dims) { if (logger.isDebugEnabled()) { logger.debug("visitMultiANewArrayInst : " + desc + ", " + dims); } VisitorFactory.getSignatureVisitor(className, desc); this.mv.visitMultiANewArrayInsn(desc, dims); } /** * {@inheritDoc} */ public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { if (logger.isDebugEnabled()) { logger.debug("visitParameterAnnotation : " + parameter + ", " + desc + ", " + visible); } VisitorFactory.getSignatureVisitor(className, desc); return this.mv.visitParameterAnnotation(parameter, desc, visible); } }