alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (MethodFinder.java)

This example Java source code file (MethodFinder.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abstractfinder, cache, class, illegalargumentexception, javabean, method, methodfinder, nosuchmethodexception, override, parameterizedtype, reflection, signature, signatureexception, soft, string, type, util

The MethodFinder.java Java example source code

/*
 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.beans.finder;

import com.sun.beans.TypeResolver;
import com.sun.beans.util.Cache;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;

import static com.sun.beans.util.Cache.Kind.SOFT;
import static sun.reflect.misc.ReflectUtil.isPackageAccessible;

/**
 * This utility class provides {@code static} methods
 * to find a public method with specified name and parameter types
 * in specified class.
 *
 * @since 1.7
 *
 * @author Sergey A. Malenkov
 */
public final class MethodFinder extends AbstractFinder<Method> {
    private static final Cache<Signature, Method> CACHE = new Cache(SOFT, SOFT) {
        @Override
        public Method create(Signature signature) {
            try {
                MethodFinder finder = new MethodFinder(signature.getName(), signature.getArgs());
                return findAccessibleMethod(finder.find(signature.getType().getMethods()));
            }
            catch (Exception exception) {
                throw new SignatureException(exception);
            }
        }
    };

    /**
     * Finds public method (static or non-static)
     * that is accessible from public class.
     *
     * @param type  the class that can have method
     * @param name  the name of method to find
     * @param args  parameter types that is used to find method
     * @return object that represents found method
     * @throws NoSuchMethodException if method could not be found
     *                               or some methods are found
     */
    public static Method findMethod(Class<?> type, String name, Class...args) throws NoSuchMethodException {
        if (name == null) {
            throw new IllegalArgumentException("Method name is not set");
        }
        PrimitiveWrapperMap.replacePrimitivesWithWrappers(args);
        Signature signature = new Signature(type, name, args);

        try {
            Method method = CACHE.get(signature);
            return (method == null) || isPackageAccessible(method.getDeclaringClass()) ? method : CACHE.create(signature);
        }
        catch (SignatureException exception) {
            throw exception.toNoSuchMethodException("Method '" + name + "' is not found");
        }
    }

    /**
     * Finds public non-static method
     * that is accessible from public class.
     *
     * @param type  the class that can have method
     * @param name  the name of method to find
     * @param args  parameter types that is used to find method
     * @return object that represents found method
     * @throws NoSuchMethodException if method could not be found
     *                               or some methods are found
     */
    public static Method findInstanceMethod(Class<?> type, String name, Class... args) throws NoSuchMethodException {
        Method method = findMethod(type, name, args);
        if (Modifier.isStatic(method.getModifiers())) {
            throw new NoSuchMethodException("Method '" + name + "' is static");
        }
        return method;
    }

    /**
     * Finds public static method
     * that is accessible from public class.
     *
     * @param type  the class that can have method
     * @param name  the name of method to find
     * @param args  parameter types that is used to find method
     * @return object that represents found method
     * @throws NoSuchMethodException if method could not be found
     *                               or some methods are found
     */
    public static Method findStaticMethod(Class<?> type, String name, Class...args) throws NoSuchMethodException {
        Method method = findMethod(type, name, args);
        if (!Modifier.isStatic(method.getModifiers())) {
            throw new NoSuchMethodException("Method '" + name + "' is not static");
        }
        return method;
    }

    /**
     * Finds method that is accessible from public class or interface through class hierarchy.
     *
     * @param method  object that represents found method
     * @return object that represents accessible method
     * @throws NoSuchMethodException if method is not accessible or is not found
     *                               in specified superclass or interface
     */
    public static Method findAccessibleMethod(Method method) throws NoSuchMethodException {
        Class<?> type = method.getDeclaringClass();
        if (Modifier.isPublic(type.getModifiers()) && isPackageAccessible(type)) {
            return method;
        }
        if (Modifier.isStatic(method.getModifiers())) {
            throw new NoSuchMethodException("Method '" + method.getName() + "' is not accessible");
        }
        for (Type generic : type.getGenericInterfaces()) {
            try {
                return findAccessibleMethod(method, generic);
            }
            catch (NoSuchMethodException exception) {
                // try to find in superclass or another interface
            }
        }
        return findAccessibleMethod(method, type.getGenericSuperclass());
    }

    /**
     * Finds method that accessible from specified class.
     *
     * @param method  object that represents found method
     * @param generic generic type that is used to find accessible method
     * @return object that represents accessible method
     * @throws NoSuchMethodException if method is not accessible or is not found
     *                               in specified superclass or interface
     */
    private static Method findAccessibleMethod(Method method, Type generic) throws NoSuchMethodException {
        String name = method.getName();
        Class<?>[] params = method.getParameterTypes();
        if (generic instanceof Class) {
            Class<?> type = (Class) generic;
            return findAccessibleMethod(type.getMethod(name, params));
        }
        if (generic instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) generic;
            Class<?> type = (Class) pt.getRawType();
            for (Method m : type.getMethods()) {
                if (m.getName().equals(name)) {
                    Class<?>[] pts = m.getParameterTypes();
                    if (pts.length == params.length) {
                        if (Arrays.equals(params, pts)) {
                            return findAccessibleMethod(m);
                        }
                        Type[] gpts = m.getGenericParameterTypes();
                        if (params.length == gpts.length) {
                            if (Arrays.equals(params, TypeResolver.erase(TypeResolver.resolve(pt, gpts)))) {
                                return findAccessibleMethod(m);
                            }
                        }
                    }
                }
            }
        }
        throw new NoSuchMethodException("Method '" + name + "' is not accessible");
    }


    private final String name;

    /**
     * Creates method finder with specified array of parameter types.
     *
     * @param name  the name of method to find
     * @param args  the array of parameter types
     */
    private MethodFinder(String name, Class<?>[] args) {
        super(args);
        this.name = name;
    }

    /**
     * Checks validness of the method.
     * The valid method should be public and
     * should have the specified name.
     *
     * @param method  the object that represents method
     * @return {@code true} if the method is valid,
     *         {@code false} otherwise
     */
    @Override
    protected boolean isValid(Method method) {
        return super.isValid(method) && method.getName().equals(this.name);
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java MethodFinder.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.