Package alt.jiapi.interceptor

Source Code of alt.jiapi.interceptor.InvocationInterceptor

/*
* 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.interceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Category;

import alt.jiapi.InstrumentationContext;
import alt.jiapi.InstrumentationDescriptor;
import alt.jiapi.reflect.Signature;

import alt.jiapi.event.EventProducer;

/**
* InvocationInterceptor intercepts method invocations and
* delegates invocations to InvokeHandler.<p>
* Following code snippet is an example, how to initialize
* InvocationInterceptor:
*
* <pre>
*      InstrumentationContext ctx = new InstrumentationContext();
*      InstrumentationDescriptor id = new InstrumentationDescriptor();
*      id.addInclusionRule("samples.*");
*      ctx.addInstrumentationDescriptor(id);
*      
*      InvocationInterceptor ii = new InvocationInterceptor(id, "java*",this);
* </pre>
*
* @author Mika Riekkinen
* @version $Revision: 1.9 $ $Date: 2004/04/11 14:22:58 $
*/
public class InvocationInterceptor extends EventProducer {
    private InvocationHandler handler;
    private HashMap rmCache = new HashMap();

    /**
     * Constructor. Resolution is set to '*'.
     *
     * @param id Instrumentation decsriptor, that this InvocationInterceptor
     *        registers itself to.
     * @param handler InvocationHandler
     */
    public InvocationInterceptor(InstrumentationDescriptor id, InvocationHandler handler) {
        this(id, "*", handler);
    }


    /**
     * Creates new InvocationInterceptor. Resolution tells, which
     * methods are to be intercepted.
     *
     * @param id Instrumentation decsriptor, that this InvocationInterceptor
     *        registers itself to.
     * @param resolution Resolution, that is used to select which
     *        methods will be intercepted.
     * @param handler InvocationHandler
     */
    public InvocationInterceptor(InstrumentationDescriptor id,
                                 String resolution, InvocationHandler handler){
        this(id, new String[] { resolution }, handler);
    }


    /**
     * Creates new InvocationInterceptor.
     *
     * @param id Instrumentation decsriptor, that this InvocationInterceptor
     *        registers itself to.
     * @param resolutions Resolutions, that is used further to select which
     *        methods will trigger events to be produced.
     * @param handler InvocationHandler
     */
    public InvocationInterceptor(InstrumentationDescriptor id,
                                 String[] resolutions,
                                 InvocationHandler handler) {
        super(resolutions);
        this.handler = handler;

        id.addInstrumentor(new InvocationInstrumentor(this, handler));
    }



    /**
     * Called by Jiapi runtime.
     * @param o if invocation is being made to an static method,
     *          this parameter holds a Class of the called method,
     *          otherwise this is the instance, that invocation should be
     *          acted on.
     * @param name of the method to call
     * @param args Arguments of the method
     */
    public Object invokeMethod(Object o, String name, Object[] args,
                               String signature) throws Throwable {
        try {
            Method m = null;
            Class c = null;
            if (o instanceof Class) { // invokestatic
                c = (Class)o;
            }
            else  { // invokevirtual
                c = o.getClass();
            }

            //System.out.println("Signature: " + signature);
       
            //long l1 = System.currentTimeMillis();
            m = getReflectionMethod(c, name, args, signature);
            //long l2 = System.currentTimeMillis();
            //System.out.println((l2-l1));

            Object r = handler.invoke(o, m, args);
            return r;
        }
        catch(java.lang.reflect.InvocationTargetException ite) {
            throw ite.getTargetException();
        }
        catch(Throwable t) {
            t.printStackTrace();
            throw t;
        }
    }


    private Method getReflectionMethod(Class c, String name, Object[] args,
                                       String signature) {
        Method m = null;

        // NOTE: cache should be configurable. It can potentially
        //       consume a lot of memory
        m = (Method)rmCache.get(signature);
        if (m != null) {
            return m;
        }
       
        String sign = signature.substring(signature.lastIndexOf('('));
        Signature s = new Signature(sign);

        String[] paramTypes = s.getParameters();

        try {
            Class[] params = params = new Class[args.length];

            for (int i = 0; i < args.length; i++) {
                params[i] = args[i].getClass();

                // BUG: Following code segment makes a false
                // assumption, that java.lang.Integer etc. allways
                // represents a primitive type
                if ("int".equals(paramTypes[i])) {
                    params[i] = Integer.TYPE;
                }
                else if ("long".equals(paramTypes[i])) {
                    params[i] = Long.TYPE;
                }
                else if ("char".equals(paramTypes[i])) {
                    params[i] = Character.TYPE;
                }
                else if ("boolean".equals(paramTypes[i])) {
                    params[i] = Boolean.TYPE;
                }
                else if ("byte".equals(paramTypes[i])) {
                    params[i] = Byte.TYPE;
                }
                else if ("float".equals(paramTypes[i])) {
                    params[i] = Float.TYPE;
                }
                else if ("double".equals(paramTypes[i])) {
                    params[i] = Double.TYPE;
                }
            }

            m = c.getMethod(name, params);
        }
        catch(Exception e) {
            e.printStackTrace();
        }

        rmCache.put(signature, m);

        return m;
    }
}
TOP

Related Classes of alt.jiapi.interceptor.InvocationInterceptor

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.