com.google.code.jtracert.instrument.impl.asm.JTracertClassAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.google.code.jtracert.instrument.impl.asm.JTracertClassAdapter.java

Source

package com.google.code.jtracert.instrument.impl.asm;

import com.google.code.jtracert.config.InstrumentationProperties;
import com.google.code.jtracert.instrument.ConfigurableTransformer;
import com.google.code.jtracert.util.ClassUtils;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/**
 * Distributed under GNU GENERAL PUBLIC LICENSE Version 3
 *
 * @author Dmitry.Bedrin@gmail.com
 */
public class JTracertClassAdapter extends ClassAdapter implements ConfigurableTransformer {

    private String className;
    private String parentClassName;
    private InstrumentationProperties instrumentationProperties;

    private boolean isInterface;
    private boolean instrumentClass;

    /**
     * @return
     */
    public String getClassName() {
        return className;
    }

    /**
     * @param className
     */
    public void setClassName(String className) {
        this.className = className;
    }

    /**
     * @return
     */
    public String getParentClassName() {
        return parentClassName;
    }

    /**
     * @param parentClassName
     */
    public void setParentClassName(String parentClassName) {
        this.parentClassName = parentClassName;
    }

    /**
     * @return
     */
    public InstrumentationProperties getInstrumentationProperties() {
        return instrumentationProperties;
    }

    /**
     * @param instrumentationProperties
     */
    public void setInstrumentationProperties(InstrumentationProperties instrumentationProperties) {
        this.instrumentationProperties = instrumentationProperties;
    }

    public boolean isInstrumentClass() {
        return instrumentClass;
    }

    public void setInstrumentClass(boolean instrumentClass) {
        this.instrumentClass = instrumentClass;
    }

    /**
     * @param visitor
     * @param instrumentClass
     */
    public JTracertClassAdapter(ClassVisitor visitor, boolean instrumentClass) {
        super(visitor);
        setInstrumentClass(instrumentClass);
    }

    /**
     * @param visitor
     * @param instrumentationProperties
     */
    public JTracertClassAdapter(ClassVisitor visitor, InstrumentationProperties instrumentationProperties,
            boolean instrumentClass) {
        this(visitor, instrumentClass);
        this.instrumentationProperties = instrumentationProperties;
    }

    /**
     * @param version
     * @param access
     * @param name
     * @param signature
     * @param superName
     * @param interfaces
     */
    @Override
    public void visit(int version, int access, String name, String signature, String superName,
            String[] interfaces) {

        isInterface = 0 != (access & Opcodes.ACC_INTERFACE);

        setClassName(ClassUtils.getFullyQualifiedName(name));
        setParentClassName(superName);

        super.visit(version, access, name, signature, superName, interfaces);

    }

    /**
     * @param access
     * @param name
     * @param desc
     * @param signature
     * @param exceptions
     * @return
     */
    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {

        //if (0 == (access & Opcodes.ACC_SYNTHETIC)) {
        if (0 == 0) {

            MethodVisitor parentMethodVisitor = super.visitMethod(access, name, desc, signature, exceptions);

            // instrument java.lang.Object default constructor

            /*if ("java.lang.Object".equals(getClassName())) {
                
            if (!"<init>".equals(name)) return parentMethodVisitor;
                
            if ((null != getInstrumentationProperties()) && (getInstrumentationProperties().isVerbose())) {
                System.out.println("Instrumenting java.lang.Object constructor: " + getClassName() + "." + name);
            }
                
            return new JTracertObjectConstructorAdapter(
                    parentMethodVisitor
            );
            }*/

            // instrumenting loadClass method

            if (("loadClass".equals(name) && ("(Ljava/lang/String;)Ljava/lang/Class;".equals(desc)
                    || "(Ljava/lang/String;Z)Ljava/lang/Class;".equals(desc)))) {

                if (0 == (access & Opcodes.ACC_STATIC)) {
                    if (null != getInstrumentationProperties() && getInstrumentationProperties().isVerbose()) {
                        System.out.println(
                                "Instrumenting class loader method: " + getClassName() + "." + name + " " + desc);
                    }

                    parentMethodVisitor = new InstrumentClassLoaderMethodVisitor(parentMethodVisitor);
                }

            }

            // instrumenting other methods

            if (isInstrumentClass()) {

                if (getClassName().startsWith("java.io") || getClassName().startsWith("java.util.concurrent")
                        || getClassName().startsWith("java.net") || getClassName().startsWith("sun")
                        || getClassName().startsWith("com.sun") || getClassName().startsWith("java.util.jar")
                        || getClassName().startsWith("java.util.zip") || getClassName().startsWith("java.nio")
                        || getClassName().startsWith("java.security")) {
                    return parentMethodVisitor;
                }

                /*// todo: add a classloader check above
                if (getClassName().startsWith("java") || getClassName().startsWith("sun") || getClassName().startsWith("org.xml") || getClassName().startsWith("com.sun") || getClassName().startsWith("$")) {
                if (getClassName().startsWith("java.util")) {
                    return new JTracertSystemMethodAdapter(
                            parentMethodVisitor,
                            access,
                            name,
                            desc,
                            getClassName()
                    );
                } else {
                    return parentMethodVisitor;
                }
                } else {
                return new JTracertMethodAdapter(
                        parentMethodVisitor,
                        access,
                        name,
                        desc,
                        getClassName(),
                        getInstrumentationProperties(),
                        getParentClassName()
                );
                }*/

                return new JTracertMethodAdapter(parentMethodVisitor, access, name, desc, getClassName(),
                        getInstrumentationProperties(), getParentClassName());

            } else {
                return parentMethodVisitor;
            }

        } else {

            if ((null != getInstrumentationProperties()) && (getInstrumentationProperties().isVerbose())) {
                System.out.println("Skiping syntetic method " + getClassName() + "." + name);
            }

            return super.visitMethod(access, name, desc, signature, exceptions);

        }

    }

    /**
     *
     */
    @Override
    public void visitEnd() {

        if (!isInterface) {
            // Apply class transformations
        }

        if ("java.lang.System".equals(getClassName()) || "java/lang/System".equals(getClassName())) {
            MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_SYNCHRONIZED,
                    "constructor", "(Ljava/lang/Object;)V", null, null);
            mv.visitCode();
            mv.visitInsn(Opcodes.RETURN);
            mv.visitMaxs(0, 1);
            mv.visitEnd();
        }

        super.visitEnd();
    }

}