MethodProxy.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Copyright 2003,2004 The Apache Software Foundation
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  Licensed under the Apache License, Version 2.0 (the "License");
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * you may not use this file except in compliance with the License.
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * You may obtain a copy of the License at
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *      http://www.apache.org/licenses/LICENSE-2.0
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  Unless required by applicable law or agreed to in writing, software
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * distributed under the License is distributed on an "AS IS" BASIS,
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * See the License for the specific language governing permissions and
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * limitations under the License.
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallpackage org.mockito.cglib.proxy;
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallimport java.lang.reflect.InvocationTargetException;
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallimport java.lang.reflect.Method;
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallimport org.mockito.cglib.core.AbstractClassGenerator;
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallimport org.mockito.cglib.core.CodeGenerationException;
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallimport org.mockito.cglib.core.GeneratorStrategy;
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallimport org.mockito.cglib.core.NamingPolicy;
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallimport org.mockito.cglib.core.Signature;
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallimport org.mockito.cglib.reflect.FastClass;
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/**
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Classes generated by {@link Enhancer} pass this object to the
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * registered {@link MethodInterceptor} objects when an intercepted method is invoked. It can
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * be used to either invoke the original method, or call the same method on a different
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * object of the same type.
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * @version $Id: MethodProxy.java,v 1.14 2008/05/26 04:05:50 herbyderby Exp $
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallpublic class MethodProxy {
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private Signature sig1;
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private Signature sig2;
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private CreateInfo createInfo;
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private final Object initLock = new Object();
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private volatile FastClassInfo fastClassInfo;
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /**
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * For internal use by {@link Enhancer} only; see the {@link org.mockito.cglib.reflect.FastMethod} class
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * for similar functionality.
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        MethodProxy proxy = new MethodProxy();
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        proxy.sig1 = new Signature(name1, desc);
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        proxy.sig2 = new Signature(name2, desc);
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        proxy.createInfo = new CreateInfo(c1, c2);
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return proxy;
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private void init()
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /*
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * Using a volatile invariant allows us to initialize the FastClass and
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * method index pairs atomically.
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         *
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * Double-checked locking is safe with volatile in Java 5.  Before 1.5 this
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * code could allow fastClassInfo to be instantiated more than once, which
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * appears to be benign.
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         */
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (fastClassInfo == null)
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        {
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            synchronized (initLock)
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            {
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                if (fastClassInfo == null)
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                {
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    CreateInfo ci = createInfo;
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    FastClassInfo fci = new FastClassInfo();
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    fci.f1 = helper(ci, ci.c1);
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    fci.f2 = helper(ci, ci.c2);
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    fci.i1 = fci.f1.getIndex(sig1);
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    fci.i2 = fci.f2.getIndex(sig2);
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    fastClassInfo = fci;
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                }
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private static class FastClassInfo
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        FastClass f1;
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        FastClass f2;
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        int i1;
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        int i2;
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private static class CreateInfo
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Class c1;
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Class c2;
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        NamingPolicy namingPolicy;
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        GeneratorStrategy strategy;
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        boolean attemptLoad;
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        public CreateInfo(Class c1, Class c2)
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        {
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            this.c1 = c1;
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            this.c2 = c2;
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (fromEnhancer != null) {
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                namingPolicy = fromEnhancer.getNamingPolicy();
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                strategy = fromEnhancer.getStrategy();
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                attemptLoad = fromEnhancer.getAttemptLoad();
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private static FastClass helper(CreateInfo ci, Class type) {
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        FastClass.Generator g = new FastClass.Generator();
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        g.setType(type);
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        g.setClassLoader(ci.c2.getClassLoader());
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        g.setNamingPolicy(ci.namingPolicy);
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        g.setStrategy(ci.strategy);
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        g.setAttemptLoad(ci.attemptLoad);
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return g.create();
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private MethodProxy() {
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /**
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * Return the signature of the proxied method.
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    public Signature getSignature() {
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return sig1;
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /**
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * Return the name of the synthetic method created by CGLIB which is
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * used by {@link #invokeSuper} to invoke the superclass
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * (non-intercepted) method implementation. The parameter types are
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * the same as the proxied method.
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    public String getSuperName() {
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return sig2.getName();
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /**
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * Return the {@link org.mockito.cglib.reflect.FastClass} method index
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * for the method used by {@link #invokeSuper}. This index uniquely
1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * identifies the method within the generated proxy, and therefore
1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * can be useful to reference external metadata.
1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @see #getSuperName
1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    public int getSuperIndex() {
1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        init();
1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return fastClassInfo.i2;
1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /**
1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * Return the <code>MethodProxy</code> used when intercepting the method
1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * matching the given signature.
1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @param type the class generated by Enhancer
1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @param sig the signature to match
1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @return the MethodProxy instance, or null if no applicable matching method is found
1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @throws IllegalArgumentException if the Class was not created by Enhancer or does not use a MethodInterceptor
1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    public static MethodProxy find(Class type, Signature sig) {
1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        try {
1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            Method m = type.getDeclaredMethod(MethodInterceptorGenerator.FIND_PROXY_NAME,
1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                              MethodInterceptorGenerator.FIND_PROXY_TYPES);
1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return (MethodProxy)m.invoke(null, new Object[]{ sig });
1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        } catch (NoSuchMethodException e) {
1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            throw new IllegalArgumentException("Class " + type + " does not use a MethodInterceptor");
1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        } catch (IllegalAccessException e) {
1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            throw new CodeGenerationException(e);
1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        } catch (InvocationTargetException e) {
1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            throw new CodeGenerationException(e);
1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /**
1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * Invoke the original method, on a different object of the same type.
1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @param obj the compatible object; recursion will result if you use the object passed as the first
1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * argument to the MethodInterceptor (usually not what you want)
1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @param args the arguments passed to the intercepted method; you may substitute a different
1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * argument array as long as the types are compatible
1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @see MethodInterceptor#intercept
1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @throws Throwable the bare exceptions thrown by the called method are passed through
1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * without wrapping in an <code>InvocationTargetException</code>
1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    public Object invoke(Object obj, Object[] args) throws Throwable {
1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        try {
1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            init();
1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            FastClassInfo fci = fastClassInfo;
1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return fci.f1.invoke(fci.i1, obj, args);
1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        } catch (InvocationTargetException e) {
1949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            throw e.getTargetException();
1959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        } catch (IllegalArgumentException e) {
1969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (fastClassInfo.i1 < 0)
1979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                throw new IllegalArgumentException("Protected method: " + sig1);
1989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            throw e;
1999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
2009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
2019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /**
2039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * Invoke the original (super) method on the specified object.
2049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @param obj the enhanced object, must be the object passed as the first
2059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * argument to the MethodInterceptor
2069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @param args the arguments passed to the intercepted method; you may substitute a different
2079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * argument array as long as the types are compatible
2089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @see MethodInterceptor#intercept
2099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * @throws Throwable the bare exceptions thrown by the called method are passed through
2109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * without wrapping in an <code>InvocationTargetException</code>
2119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
2129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    public Object invokeSuper(Object obj, Object[] args) throws Throwable {
2139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        try {
2149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            init();
2159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            FastClassInfo fci = fastClassInfo;
2169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return fci.f2.invoke(fci.i2, obj, args);
2179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        } catch (InvocationTargetException e) {
2189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            throw e.getTargetException();
2199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
2209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
2219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall