Package alt.jiapi.interceptor

Source Code of alt.jiapi.interceptor.FieldInstrumentor

package alt.jiapi.interceptor;

import java.util.List;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import alt.jiapi.InstrumentationException;

import alt.jiapi.event.EventInstrumentor;
import alt.jiapi.event.EventRuntime;

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.Loader;
import alt.jiapi.reflect.Signature;

import alt.jiapi.reflect.FieldExistsException;
import alt.jiapi.reflect.MethodExistsException;

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

import alt.jiapi.util.HotSpot;
import alt.jiapi.util.HotSpotLocator;


/**
* Class FieldInstrumentor.
*
* @author Mika Riekkinen
*/
class FieldInstrumentor extends EventInstrumentor {
    private FieldHandler handler;
    private JiapiMethod getMethod;
    private JiapiMethod setMethod;

    FieldInstrumentor(FieldInterceptor2 ii, FieldHandler handler) {
        super(ii);
        this.handler = handler;

        JiapiClass jc = getEventProducer();
        try {
            this.getMethod =
                jc.getDeclaredMethod("getField",
                                     new String[] { "java.lang.Object",
                                                    "java.lang.String"});

            this.setMethod =
                jc.getDeclaredMethod("setField",
                                     new String[] { "java.lang.Object",
                                                    "java.lang.String",
                                                    "java.lang.Object"});
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    public void instrument(JiapiMethod jm) {
        JiapiField interceptor = getEventProducerField();
        InstructionList il = jm.getInstructionList();
        InstructionFactory factory = il.getInstructionFactory();

        HotSpotLocator hsl =
            new HotSpotLocator(il,
                               new byte[]{Opcodes.GETSTATIC/*,Opcodes.PUTSTATIC*/});
        HotSpot[] hotSpots = hsl.getHotSpots();

        for (int i = 0; i < hotSpots.length; i++) {
            FieldAccess fa = (FieldAccess)hotSpots[i].getHotSpotInstruction();
           
            if (fa.getName().startsWith("__jiapi")) {
                continue;
            }

            if (!match(fa.getClassName() + "." + fa.getFieldName())) {
                continue;
            }

            // BUG: We cannot use reflection in this interceptor, since it
            // is allowed only for public fields.
            if (!isPublicField(fa)) {
                continue;
            }

            InstructionList hsList = hotSpots[i].getInstructionList();
            InstructionList nList = il.createEmptyList();

            nList.add(factory.getField(interceptor)); // Interceptor

            // Class or objref; 1st parameter to interceptor
            if ((fa.getOpcode() == Opcodes.GETSTATIC) ||
                (fa.getOpcode() == Opcodes.PUTSTATIC)) {
                addClassForNameInstructions(fa.getClassName(), nList);
            }
            else {
                nList.add(il.get(0)); // objref
            }

            // Name of the field; 2nd parameter to interceptor
            nList.add(factory.pushConstant(fa.getClassName() + "." +
                                           fa.getFieldName()));

            // call Interceptor
            if ((fa.getOpcode() == Opcodes.GETSTATIC) ||
                (fa.getOpcode() == Opcodes.GETFIELD)) {
                nList.add(factory.invoke(getMethod));
            }
            else {
                nList.add(il.get(1)); // value ???
                nList.add(factory.invoke(setMethod));
            }
           
            handleReturnValue(nList, fa.getTypeName());

            //nList.add(factory.cast(fa.getTypeName()));

            hsList.replace(nList);
        }
    }


    private void addClassForNameInstructions(String name, InstructionList il) {
        InstructionFactory f = il.getInstructionFactory();

        InstructionList nl = il.createEmptyList();
       
        // NOTE: We do not create exception handlers for
        //       Class.forName(...) invocation.
        //       However, we use this to get Class of the running object,
        //       so its Class is allways found.
        try {
            nl.add(f.pushConstant(name));
            nl.add(f.invoke(Modifier.STATIC, "java.lang.Class",
                            "forName", new Signature("java.lang.Class",
                                                     new String[] {"java.lang.String"})));
        }
        catch(Exception e) {
            e.printStackTrace();
            il.add(f.pushNull());
        }

        il.add(nl);
    }


    private boolean isPublicField(FieldAccess fa) {
        try {
            JiapiClass jc = new Loader().loadClass(fa.getClassName());
            JiapiField jf = jc.getField(fa.getName());

            return Modifier.isPublic(jf.getModifiers());
        }
        catch(Exception e) {
            e.printStackTrace();
        }

        return false;
    }


    private void handleReturnValue(InstructionList il, String rType) {
        // Convert return value if needed.
        InstructionFactory factory = il.getInstructionFactory();

        if ("int".equals(rType)) {
            try {
                JiapiClass jc = new Loader().loadClass("java.lang.Integer");
                JiapiMethod jm =
                    jc.getDeclaredMethod("intValue", new String[0]);

                il.add(factory.cast("java.lang.Integer"));
                il.add(factory.invoke(jm));
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
        else if ("long".equals(rType)) {
            try {
                JiapiClass jc = new Loader().loadClass("java.lang.Long");
                JiapiMethod jm =
                    jc.getDeclaredMethod("longValue", new String[0]);

                il.add(factory.cast("java.lang.Long"));
                il.add(factory.invoke(jm));
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
        else if ("char".equals(rType)) {
            try {
                JiapiClass jc = new Loader().loadClass("java.lang.Character");
                JiapiMethod jm =
                    jc.getDeclaredMethod("charValue", new String[0]);

                il.add(factory.cast("java.lang.Character"));
                il.add(factory.invoke(jm));
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
        else if ("boolean".equals(rType)) {
            try {
                JiapiClass jc = new Loader().loadClass("java.lang.Boolean");
                JiapiMethod jm =
                    jc.getDeclaredMethod("booleanValue", new String[0]);

                il.add(factory.cast("java.lang.Boolean"));
                il.add(factory.invoke(jm));
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
        else if ("byte".equals(rType)) {
            try {
                JiapiClass jc = new Loader().loadClass("java.lang.Byte");
                JiapiMethod jm =
                    jc.getDeclaredMethod("byteValue", new String[0]);

                il.add(factory.cast("java.lang.Byte"));
                il.add(factory.invoke(jm));
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
        else if ("float".equals(rType)) {
            try {
                JiapiClass jc = new Loader().loadClass("java.lang.Float");
                JiapiMethod jm =
                    jc.getDeclaredMethod("floatValue", new String[0]);

                il.add(factory.cast("java.lang.Float"));
                il.add(factory.invoke(jm));
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
        else if ("double".equals(rType)) {
            try {
                JiapiClass jc = new Loader().loadClass("java.lang.Double");
                JiapiMethod jm =
                    jc.getDeclaredMethod("doubleValue", new String[0]);

                il.add(factory.cast("java.lang.Double"));
                il.add(factory.invoke(jm));
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
        else if ("void".equals(rType)){
            // Pop out the return value(probably null) of
            // the invocation handler if it was a 'void' method
            il.add(new Instruction(new byte[]{Opcodes.POP}));
        }
        else { // Cast to correct Object
            il.add(factory.cast(rType));
        }
    }
}
TOP

Related Classes of alt.jiapi.interceptor.FieldInstrumentor

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.