Package alt.jiapi.event

Source Code of alt.jiapi.event.MethodEventInstrumentor

package alt.jiapi.event;

import java.lang.reflect.Modifier;

import alt.jiapi.Instrumentor;
import alt.jiapi.reflect.Instruction;
import alt.jiapi.reflect.InstructionFactory;
import alt.jiapi.reflect.InstructionList;
import alt.jiapi.reflect.JiapiClass;
import alt.jiapi.reflect.JiapiField;
import alt.jiapi.reflect.JiapiMethod;
import alt.jiapi.reflect.MethodExistsException;
import alt.jiapi.reflect.Signature;

import alt.jiapi.reflect.instruction.OpcodeGroups;
import alt.jiapi.reflect.instruction.Opcodes;
import alt.jiapi.reflect.instruction.FieldAccess;

/**
* MethodEventInstrumentor. This class instruments
* target classes so, that method entries and exits are trapped
* to MethodEventProducer.
*
* @author Mika Riekkinen
*/
class MethodEventInstrumentor extends EventInstrumentor {
    MethodEventInstrumentor(MethodEventProducer mep) {
        super(mep);
    }

    public void instrument(JiapiMethod jm) {
        InstructionList il = jm.getInstructionList();
        InstructionFactory factory = il.getInstructionFactory();
        JiapiClass mep = getEventProducer();
        JiapiMethod methodEntered = null;
        JiapiMethod methodExited = null;
        JiapiField jiapiField = getEventProducerField();

        // a flag, that tells whether or not InstructionList being
        // processed is in a static method.
        boolean isStatic = Modifier.isStatic(il.getDeclaringMethod().getModifiers());

        try {
            methodEntered =
                mep.getDeclaredMethod("methodEntered",
                                      new String[] { "java.lang.Object",
                                                     "java.lang.String" });
            methodExited =
                mep.getDeclaredMethod("methodExited",
                                      new String[] { "java.lang.Object",
                                                     "java.lang.String" });
        }
        catch(Exception e) {
            System.out.println("ERROR: " + e);
        }

        // Create instructions for method entrance
        InstructionList entryList = il.createEmptyList();
        entryList.add(factory.getField(jiapiField));
        if (isStatic) {
            entryList.add(factory.pushConstant(il.getDeclaringMethod().getDeclaringClass().getName())); // BUG: we should pass a Class
        }
        else {
            entryList.add(factory.pushThis());
        }
        entryList.add(factory.pushConstant(il.getDeclaringMethod().getName()));
        entryList.add(factory.invoke(methodEntered));

        // Skip super(....) call, if in <init> method
        int superIdx = il.indexOf(Opcodes.INVOKESPECIAL);

        // BUG: we should insert entrylist on <clinit> pass the
        //      __jiapi_field initialization
        if (!"<clinit>".equals(il.getDeclaringMethod().getName())) {
            // FIXME: See bug above
            il.insert(superIdx+1, entryList);
        }
        else {
            int idx = findFieldInitIndex(il, jiapiField);
            if (idx != -1) {
                il.insert(idx + 1, entryList);
            }
        }

        // Create instructions for method exits
        InstructionList exitList = il.createEmptyList();
        exitList.add(factory.getField(jiapiField));
        if (isStatic) {
            exitList.add(factory.pushConstant(il.getDeclaringMethod().getDeclaringClass().getName())); // BUG: we should pass a Class
        }
        else {
            exitList.add(factory.pushThis());
        }

        exitList.add(factory.pushConstant(il.getDeclaringMethod().getName()));
        exitList.add(factory.invoke(methodExited));

        // Find all method exits
        int idx = il.indexOf(OpcodeGroups.RETURN_INSTRUCTIONS, 0);
        while (idx != -1) {
            Instruction ins = il.get(idx);
            il.insert(idx, exitList);

            // Next index. Skip Instructions created above.
            idx = il.indexOf(OpcodeGroups.RETURN_INSTRUCTIONS,
                             idx + exitList.size() + 1);
        }
    }


    // Find event producer initialization on <clinit>
    private int findFieldInitIndex(InstructionList il, JiapiField jiapiField) {
        int idx = -1;
       
        while ((idx = il.indexOf(Opcodes.PUTSTATIC, idx+1)) != -1) {
            FieldAccess fa = (FieldAccess)il.get(idx);
            if (fa.getFieldName().equals(jiapiField.getName())) {
                break;
            }
        }

        return idx;
    }
}
TOP

Related Classes of alt.jiapi.event.MethodEventInstrumentor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.