All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.eg.agent.compile.visitor.EventClassVisitor Maven / Gradle / Ivy

package com.eg.agent.compile.visitor;

import com.eg.agent.compile.InstrumentationContext;
import com.eg.agent.compile.EGLogger;
import com.eg.objectweb.asm.ClassAdapter;
import com.eg.objectweb.asm.ClassVisitor;
import com.eg.objectweb.asm.MethodVisitor;
import com.eg.objectweb.asm.commons.GeneratorAdapter;
import com.eg.objectweb.asm.commons.Method;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author janakiraman.k
 *
 */
public abstract class EventClassVisitor extends ClassAdapter {
    protected final Set baseClasses;
    private final Map methodVisitors = new HashMap();
    protected String superName;
    protected boolean instrument = false;
    protected final InstrumentationContext context;
    protected final EGLogger log;
    private Pattern androidPackagePattern = Pattern.compile("^android[x]{0,1}/.*");
    protected final Map baseClassPatterns;

    public EventClassVisitor(ClassVisitor cv, InstrumentationContext context, EGLogger log, Set baseClasses, Map methodMappings) {
        super(cv);
        this.context = context;
        this.log = log;
        this.baseClasses = Collections.unmodifiableSet(baseClasses);
        java.util.Map.Entry entry;
        for (Iterator i$ = methodMappings.entrySet().iterator(); i$.hasNext(); methodVisitors.put(entry.getKey(), new MethodVisitorFactory((Method) entry.getValue())))
            entry = (java.util.Map.Entry) i$.next();
        
        this.baseClassPatterns = new HashMap();
        for (String pattern : baseClasses) {
            this.baseClassPatterns.put(pattern, Pattern.compile(pattern));
        }
    }


    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        this.superName = superName;

        this.instrument = this.shouldInstrumentClass(name, superName);

        if (this.instrument) {
            this.context.markModified();
        }
    }

    protected boolean shouldInstrumentClass(String className, String superName) {
        if (!this.androidPackagePattern.matcher(className.toLowerCase()).matches()) {
        	if(this.baseClasses.contains(superName)) {
        		return true;
        	}
            for (Pattern baseClassPattern : this.baseClassPatterns.values()) {
                Matcher matcher = baseClassPattern.matcher(superName);
                if (!matcher.matches()) continue;
                return true;
            }
        }
        return false;
    }

    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
        if (!this.instrument) {
            return mv;
        }

        Method method = new Method(name, desc);
        MethodVisitorFactory v = (MethodVisitorFactory) this.methodVisitors.get(method);
        if (v != null) {
            this.methodVisitors.remove(method);
            return v.createMethodVisitor(access, method, mv, false);
        }
        return mv;
    }

    public void visitEnd() {
        if (!this.instrument) {
            return;
        }
        MethodVisitor mv;
        for (Iterator i$ = methodVisitors.entrySet().iterator(); i$.hasNext(); mv.visitEnd()) {
            java.util.Map.Entry entry = (java.util.Map.Entry) i$.next();
            mv = super.visitMethod(4, ((Method) entry.getKey()).getName(), ((Method) entry.getKey()).getDescriptor(), null, null);
            mv = ((MethodVisitorFactory) entry.getValue()).createMethodVisitor(4, (Method) entry.getKey(), mv, true);
            mv.visitCode();
            mv.visitInsn(177);
            mv.visitMaxs(0, 0);
        }
        super.visitEnd();
    }

    protected abstract void injectCodeIntoMethod(GeneratorAdapter paramGeneratorAdapter, Method paramMethod1, Method paramMethod2);

    protected class MethodVisitorFactory {
        final Method monitorMethod;

        public MethodVisitorFactory(Method monitorMethod) {
            this.monitorMethod = monitorMethod;
        }

        public MethodVisitor createMethodVisitor(int access, final Method method, MethodVisitor mv, final boolean callSuper) {
            return new GeneratorAdapter(access, method, mv) {
                public void visitCode() {
                    super.visitCode();

                    if (callSuper) {
                        loadThis();
                        for (int i = 0; i < method.getArgumentTypes().length; i++) {
                            loadArg(i);
                        }
                        visitMethodInsn(183, EventClassVisitor.this.superName, method.getName(), method.getDescriptor());
                    }

                    EventClassVisitor.this.injectCodeIntoMethod(this, method, EventClassVisitor.MethodVisitorFactory.this.monitorMethod);
                }
            };
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy