Package alt.jiapi.event

Source Code of alt.jiapi.event.EventInstrumentor

package alt.jiapi.event;

import java.lang.reflect.Modifier;

import alt.jiapi.InstrumentationException;
import alt.jiapi.Instrumentor;

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

/**
* Class EventInstrumentor.
*
* @author Mika Riekkinen
*/
public abstract class EventInstrumentor implements Instrumentor {
    private EventProducer ep;
    private JiapiField eventProducerField;
    private JiapiClass currentClass;

    protected EventInstrumentor(EventProducer ep) {
        this.ep = ep;
    }

    /**
     * Matches given String to resolutions set to event-producer.
     */
    public boolean match(String s) {
        return ep.match(s);
    }

    /**
     * Called by Jiapi insturmentation process.
     */
    public void instrument(JiapiClass jc) {
        this.currentClass = jc;

        if (jc.isInterface()) {
            return;
        }


        // Instrument all the methods
        JiapiMethod[] dMethods = jc.getDeclaredMethods();
        for (int i = 0; i < dMethods.length; i++) {
            // Do not instrument methods syntesized by jiapi
            if (!dMethods[i].isSynthetic()) {
                // Abstract methods do not have instruction list
                if (dMethods[i].getInstructionList() != null) {
                    int su1 = dMethods[i].getInstructionList().stackUsage();
                    instrument(dMethods[i]);
                    int su2 = dMethods[i].getInstructionList().stackUsage();

                    if (su1 != su2) {
                        System.out.println("ERROR: " + "Instrumentation of " + jc.getName() + ": " + dMethods[i] + " changes stack usage from " + su1 + " to " + su2);
                        //throw new InstrumentationException("Instrumentation of " + jc.getName() + ": " + dMethods[i] + " changes stack usage from " + su1 + " to " + su2);
                    }
                }
            }
        }
    }

    protected JiapiClass getEventProducer() {
        JiapiClass jc = null;
        try {
            jc = new Loader().loadClass(ep.getClass().getName());
        }
        catch(Exception e) {
            System.out.println("ERROR: " + e);
        }

        return jc;
    }

    protected JiapiField getEventProducerField() {
        String fieldName = "__jiapi_field_" +
            EventRuntime.nextFieldNameIndex();

        // Store EventProducer in EventRuntime,
        // so that it can be retrieved later by instrumented class
        // when they are instantiated.
        EventRuntime.setFieldValue(fieldName, ep);

        // First add a field to hold event producer
        eventProducerField = null;
        try {
            eventProducerField =
                currentClass.addField(Modifier.PRIVATE +Modifier.STATIC,
                                      ep.getClass().getName(), fieldName);
        }
        catch(FieldExistsException fee) {
            // ERROR
        }
       

        // Next, create static initializer, that initializes
        // field created above.
        JiapiMethod clinit = null;
        try {
            clinit = currentClass.getDeclaredMethod("<clinit>",new String[]{});
        }
        catch(NoSuchMethodException nsme) {
            // It did not exists, so create one
            try {
                clinit =
                    currentClass.addMethod(Modifier.STATIC, "<clinit>",
                                           new Signature("void",
                                                         new String[0]));
                // create 'return' from <clinit>
                clinit.getInstructionList().add(clinit.getInstructionList().getInstructionFactory().returnMethod(clinit));
            }
            catch(MethodExistsException mee) {
                mee.printStackTrace();
            }
        }

        InstructionList il = clinit.getInstructionList();
        InstructionFactory factory = il.getInstructionFactory();
        InstructionList initializer = il.createEmptyList();

        try {
            JiapiClass er = currentClass.getLoader().loadClass("alt.jiapi.event.EventRuntime");
            JiapiMethod gfv =
                er.getDeclaredMethod("getFieldValue",
                                     new String[] {"java.lang.String"});

            // Get the field value from runtime
            initializer.add(factory.pushConstant(fieldName));
            initializer.add(factory.invoke(gfv));


            // put the returned event producer to __jiapi_field
            initializer.add(factory.cast(ep.getClass().getName()));
            initializer.add(factory.setField(eventProducerField));
        }
        catch(NoSuchMethodException nsme) {
            nsme.printStackTrace();
        }
        catch(ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }
        catch(java.io.IOException ioe) {
            ioe.printStackTrace();
        }

        // Insert initializer code before 'return'
        il.insert(0, initializer);


        return eventProducerField;
    }

    public JiapiClass getCurrentClass() {
        return currentClass;
    }


    public abstract void instrument(JiapiMethod jm);
}
TOP

Related Classes of alt.jiapi.event.EventInstrumentor

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.