Package alt.jiapi.instrumentor

Source Code of alt.jiapi.instrumentor.CreateMethodInstrumentor

/*
* Copyright (C) 2001 Mika Riekkinen, Joni Suominen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package alt.jiapi.instrumentor;

import java.lang.reflect.Modifier;

import org.apache.log4j.Category;

import alt.jiapi.Runtime;
import alt.jiapi.reflect.InstructionFactory;
import alt.jiapi.reflect.InstructionList;
import alt.jiapi.reflect.JiapiClass;
import alt.jiapi.reflect.JiapiMethod;
import alt.jiapi.reflect.Signature;
import alt.jiapi.reflect.MethodExistsException;

/**
* An Instrumentor which creates a new method for a class.
*
* @author Mika Riekkinen
* @author Joni Suominen
* @version $Revision: 1.12 $ $Date: 2004/03/15 14:47:53 $
*/
public class CreateMethodInstrumentor extends AbstractInstrumentor {
    private static Category log = Runtime.getLogCategory(CreateMethodInstrumentor.class);

    public static int FORWARD_ORIGINAL = 1;
    public static int FORWARD_NEW      = 2;
    public static int FORWARD_BOTH     = 3;
    private static int DEFAULT         = FORWARD_NEW;

    private int modifiers;
    private String returnType;
    private String methodName;
    private String[] parameterNames;

    private int forwardMode = DEFAULT;
    private boolean createReturn = true;

    /**
     * A constructor which can be used to create a method with
     * empty argument list and void return value.
     *
     * @param modifiers modifier flags
     * @param methodName name of a method
     */
    public CreateMethodInstrumentor(int modifiers, String methodName) {
        this(modifiers, "void", methodName, new String[0]);
    }

    /**
     * A constructor which can be used to create a method with
     * empty argument list and void return value.
     *
     * @param modifiers modifier flags
     * @param methodName name of a method
     */
    public CreateMethodInstrumentor(int modifiers, String returnType,
                                    String methodName) {
        this(modifiers, returnType, methodName, new String[0]);
    }

    /**
     * A constructor which can be used to create a method with
     * with a given signature.
     *
     * @param modifiers modifier flags
     * @param methodName name of a method
     * @param parameterNames signature of a method
     */
    public CreateMethodInstrumentor(int modifiers, String methodName,
                                    String[] parameterNames) {
        this(modifiers, "void", methodName, parameterNames);
    }

    /**
     * A constructor which can be used to create a method using
     * a given method as a template.
     *
     * @param method a method to be used as a template
     */
    public CreateMethodInstrumentor(JiapiMethod method) {
        this(method.getModifiers(), method.getReturnType(), method.getName(),
             method.getParameterTypeNames());
    }
   
    /**
     * A constructor which can be used to create a method with
     * with a given signature.
     *
     * @param modifiers modifier flags
     * @param returnType modifier flags
     * @param methodName name of a method
     * @param parameterNames signature of a method
     */
    public CreateMethodInstrumentor(int modifiers, String returnType,
                                    String methodName,
                                    String[] parameterNames) {
        this.methodName = methodName;
        this.modifiers = modifiers;
        this.parameterNames = parameterNames;
        this.returnType = returnType;
    }

    /**
     * Sets the forward mode for the instrumentor. Forward mode
     * specifies which InstructionList is sent forward in the chain.
     * Possible options are:
     * <li>
     * <ul>FORWARD_ORIGINAL</ul>
     * Forwards the original InstructionList, i.e the InstructionList
     * which was given in instrument-method.
     * <ul>FORWARD_NEW</ul>
     * Forwards the just created method's InstructionList.
     * <ul>FORWARD_BOTH</ul>
     * Forwards the both InstructionLists
     * </li>
     */
    public void setForwardMode(int forwardMode) {
        this.forwardMode = forwardMode;
    }

    /**
     * Set whether a default body should be created for a method.
     * If true, an instructions which will return either null, 0, false
     * or 0.0 will be created. Depending on method's return type.
     * If set to false, the method body will be left empty.
     *
     * @param b set to true if default method body should be created
     */
    public void setCreateReturn(boolean b) {
        createReturn = b;
    }

    /**
     * Instrument a JiapiClass.
     *
     * @param clazz A Class to be instrumented
     */
    public void instrument(InstructionList il) {
        JiapiClass clazz = getCurrentClass();

        // If the class is interface, then the modifiers must be public.
        // Interface can have only public methods.
        if (Modifier.isInterface(clazz.getModifiers())) {
            if (!Modifier.isPublic(modifiers)) {
                log.info("Cannot create non public method " +
                          methodName + " to interface " + clazz.getName());

                // NOTE! Throw an exception if mode is FORWARD_NEW (or BOTH)
                forward(il);
                return;
            }
        }

        log.info("Creating method " + clazz.getName() + "." + methodName);

        JiapiMethod method = null;
        try {
            Signature signature = new Signature(returnType, parameterNames);
            method = clazz.addMethod((short)modifiers, methodName, signature);
        }
        catch (MethodExistsException mee) {
            log.info("method " + clazz.getName() + "." + methodName +
                     " already exists");

            method = mee.getMethod();
        }

        if (forwardMode == FORWARD_ORIGINAL) {
            forward(il);
        }
        else if (forwardMode == FORWARD_NEW) {
            forward(method.getInstructionList());
        }
        else {
            // Forward both
            forward(il);
            forward(method.getInstructionList());
        }

        if (createReturn) {
            InstructionFactory factory = method.getInstructionFactory();
            method.getInstructionList().add(factory.returnMethod(method));
        }
    }
}
TOP

Related Classes of alt.jiapi.instrumentor.CreateMethodInstrumentor

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.