Find accessible method and include any inherited interfaces as well. - Java Reflection

Java examples for Reflection:Method

Description

Find accessible method and include any inherited interfaces as well.

Demo Code

/*******************************************************************************
 * Copyright (c) 2011 MadRobot.//from   w ww. j a  v a  2  s  . co  m
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *  Elton Kent - initial API and implementation
 ******************************************************************************/
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;

public class Main{
    private static Map declaredMethodCache = Collections
            .synchronizedMap(new WeakHashMap());
    /**
     * 
     *Find accessible method and include any inherited interfaces as well.
     *<p>
     * Its a little slow when compared to
     * {@link MethodUtils#findAccessibleMethod(Class, String, Class...)}
     *</p>
     * 
     * @param start
     * @param methodName
     * @param argCount
     *            number of arguments
     * @param argumentTypes
     *            list of argument types. If null the method is determined based
     *            on <code>argCount</code>
     * @return
     */
    public static Method findAccessibleMethodIncludeInterfaces(Class start,
            String methodName, int argCount, Class argumentTypes[]) {

        if (methodName == null) {
            return null;
        }
        // For overriden methods we need to find the most derived version.
        // So we start with the given class and walk up the superclass chain.

        Method method = null;

        for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
            Method methods[] = MethodUtils.getPublicDeclaredMethods(cl);
            for (int i = 0; i < methods.length; i++) {
                method = methods[i];
                if (method == null) {
                    continue;
                }

                // make sure method signature matches.
                Class params[] = method.getParameterTypes();
                if (method.getName().equals(methodName)
                        && params.length == argCount) {
                    if (argumentTypes != null) {
                        boolean different = false;
                        if (argCount > 0) {
                            for (int j = 0; j < argCount; j++) {
                                if (params[j] != argumentTypes[j]) {
                                    different = true;
                                    continue;
                                }
                            }
                            if (different) {
                                continue;
                            }
                        }
                    }
                    return method;
                }
            }
        }
        method = null;

        // Now check any inherited interfaces. This is necessary both when
        // the argument class is itself an interface, and when the argument
        // class is an abstract class.
        Class ifcs[] = start.getInterfaces();
        for (int i = 0; i < ifcs.length; i++) {
            // Note: The original implementation had both methods calling
            // the 3 arg method. This is preserved but perhaps it should
            // pass the args array instead of null.
            method = findAccessibleMethodIncludeInterfaces(ifcs[i],
                    methodName, argCount, null);
            if (method != null) {
                break;
            }
        }
        return method;
    }
    /**
     * Get the methods declared as public within the class
     * 
     * @param clz
     *            class to find public methods
     * @return
     */
    public static synchronized Method[] getPublicDeclaredMethods(Class clz) {
        // Looking up Class.getDeclaredMethods is relatively expensive,
        // so we cache the results.
        Method[] result = null;
        // if(!ReflectUtil.isPackageAccessible(clz)){
        // return new Method[0];
        // }
        final Class fclz = clz;
        Reference ref = (Reference) declaredMethodCache.get(fclz);
        if (ref != null) {
            result = (Method[]) ref.get();
            if (result != null) {
                return result;
            }
        }

        // We have to raise privilege for getDeclaredMethods
        result = (Method[]) AccessController
                .doPrivileged(new PrivilegedAction() {

                    public Object run() {
                        return fclz.getDeclaredMethods();
                    }
                });

        // Null out any non-public methods.
        for (int i = 0; i < result.length; i++) {
            Method method = result[i];
            int mods = method.getModifiers();
            if (!Modifier.isPublic(mods)) {
                result[i] = null;
            }
        }
        // Add it to the cache.
        declaredMethodCache.put(fclz, new SoftReference(result));
        return result;
    }
}

Related Tutorials