All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.greenpepper.shaded.net.sf.cglib.proxy.MethodProxy Maven / Gradle / Ivy

There is a newer version: 4.2.4
Show newest version
/*
 * Copyright 2003,2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.sf.cglib.proxy;

import java.lang.reflect.*;
import java.util.Arrays;
import java.util.List;
import net.sf.cglib.core.*;
import net.sf.cglib.reflect.*;

/**
 * Classes generated by {@link Enhancer} pass this object to the
 * registered {@link MethodInterceptor} objects when an intercepted method is invoked. It can
 * be used to either invoke the original method, or call the same method on a different
 * object of the same type.
 * @version $Id: MethodProxy.java,v 1.12 2004/06/24 21:15:20 herbyderby Exp $
 */
public class MethodProxy {
    private Signature sig;
    private String superName;
    private FastClass f1;
    private FastClass f2;
    private int i1;
    private int i2;

    /**
     * For internal use by {@link Enhancer} only; see the {@link net.sf.cglib.reflect.FastMethod} class
     * for similar functionality.
     */
    public static MethodProxy create(ClassLoader loader, Class c1, Class c2, String desc, String name1, String name2) {
        final Signature sig1 = new Signature(name1, desc);
        Signature sig2 = new Signature(name2, desc);
        FastClass f1 = helper(loader, c1);
        FastClass f2 = helper(loader, c2);
        int i1 = f1.getIndex(sig1);
        int i2 = f2.getIndex(sig2);

        MethodProxy proxy;
        if (i1 < 0) {
            proxy = new MethodProxy() {
                public Object invoke(Object obj, Object[] args) throws Throwable {
                    throw new IllegalArgumentException("Protected method: " + sig1);
                }
            };
        } else {
            proxy = new MethodProxy();
        }

        proxy.f1 = f1;
        proxy.f2 = f2;
        proxy.i1 = i1;
        proxy.i2 = i2;
        proxy.sig = sig1;
        proxy.superName = name2;
        return proxy;
    }

    private static FastClass helper(ClassLoader loader, Class type) {
        FastClass.Generator g = new FastClass.Generator();
        g.setType(type);
        g.setClassLoader(loader);
        AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
        if (fromEnhancer != null) {
            g.setNamingPolicy(fromEnhancer.getNamingPolicy());
            g.setStrategy(fromEnhancer.getStrategy());
            g.setAttemptLoad(fromEnhancer.getAttemptLoad());
        }
        return g.create();
    }

    private MethodProxy() {
    }

    /**
     * Return the signature of the proxied method.
     */
    public Signature getSignature() {
        return sig;
    }

    /**
     * Return the name of the synthetic method created by CGLIB which is
     * used by {@link #invokeSuper} to invoke the superclass
     * (non-intercepted) method implementation. The parameter types are
     * the same as the proxied method.
     */
    public String getSuperName() {
        return superName;
    }

    /**
     * Return the {@link net.sf.cglib.reflect.FastClass} method index
     * for the method used by {@link #invokeSuper}. This index uniquely
     * identifies the method within the generated proxy, and therefore
     * can be useful to reference external metadata.
     * @see #getSuperName
     */
    public int getSuperIndex() {
        return i2;
    }

    /**
     * Return the MethodProxy used when intercepting the method
     * matching the given signature.
     * @param type the class generated by Enhancer
     * @param sig the signature to match
     * @return the MethodProxy instance, or null if no applicable matching method is found
     * @throws IllegalArgumentException if the Class was not created by Enhancer or does not use a MethodInterceptor
     */
    public static MethodProxy find(Class type, Signature sig) {
        try {
            Method m = type.getDeclaredMethod(MethodInterceptorGenerator.FIND_PROXY_NAME,
                                              MethodInterceptorGenerator.FIND_PROXY_TYPES);
            return (MethodProxy)m.invoke(null, new Object[]{ sig });
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Class " + type + " does not use a MethodInterceptor");
        } catch (IllegalAccessException e) {
            throw new CodeGenerationException(e);
        } catch (InvocationTargetException e) {
            throw new CodeGenerationException(e);
        }
    }

    /**
     * Invoke the original method, on a different object of the same type.
     * @param obj the compatible object; recursion will result if you use the object passed as the first
     * argument to the MethodInterceptor (usually not what you want)
     * @param args the arguments passed to the intercepted method; you may substitute a different
     * argument array as long as the types are compatible
     * @see MethodInterceptor#intercept
     * @throws Throwable the bare exceptions thrown by the called method are passed through
     * without wrapping in an InvocationTargetException
     */
    public Object invoke(Object obj, Object[] args) throws Throwable {
        try {
            return f1.invoke(i1, obj, args);
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        }
    }

    /**
     * Invoke the original (super) method on the specified object.
     * @param obj the enhanced object, must be the object passed as the first
     * argument to the MethodInterceptor
     * @param args the arguments passed to the intercepted method; you may substitute a different
     * argument array as long as the types are compatible
     * @see MethodInterceptor#intercept
     * @throws Throwable the bare exceptions thrown by the called method are passed through
     * without wrapping in an InvocationTargetException
     */
    public Object invokeSuper(Object obj, Object[] args) throws Throwable {
        try {
            return f2.invoke(i2, obj, args);
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy