jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java
changeset 1844 ac2cf8242428
child 1851 8203c7eb8caf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java	Mon Dec 22 17:42:49 2008 +0300
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.beans.finder;
+
+import com.sun.beans.WeakCache;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * 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 WeakCache<Signature, Method> CACHE = new WeakCache<Signature, Method>();
+
+    /**
+     * 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);
+
+        Method method = CACHE.get(signature);
+        if (method != null) {
+            return method;
+        }
+        method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods()));
+        CACHE.put(signature, method);
+        return method;
+    }
+
+    /**
+     * 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
+     */
+    private static Method findAccessibleMethod(Method method) throws NoSuchMethodException {
+        Class<?> type = method.getDeclaringClass();
+        if (Modifier.isPublic(type.getModifiers())) {
+            return method;
+        }
+        if (Modifier.isStatic(method.getModifiers())) {
+            throw new NoSuchMethodException("Method '" + method.getName() + "' is not accessible");
+        }
+        for (Class<?> face : type.getInterfaces()) {
+            try {
+                return findAccessibleMethod(method, face);
+            }
+            catch (NoSuchMethodException exception) {
+                // try to find in superclass or another interface
+            }
+        }
+        return findAccessibleMethod(method, type.getSuperclass());
+    }
+
+    /**
+     * Finds method that accessible from specified class.
+     *
+     * @param method  object that represents found method
+     * @param type    class 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, Class<?> type) throws NoSuchMethodException {
+        String name = method.getName();
+        Class<?>[] params = method.getParameterTypes();
+        return findAccessibleMethod(type.getMethod(name, params));
+    }
+
+
+    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;
+    }
+
+    /**
+     * Returns an array of {@code Class} objects
+     * that represent the formal parameter types of the method
+     * Returns an empty array if the method takes no parameters.
+     *
+     * @param method  the object that represents method
+     * @return the parameter types of the method
+     */
+    @Override
+    protected Class<?>[] getParameters(Method method) {
+        return method.getParameterTypes();
+    }
+
+    /**
+     * Returns {@code true} if and only if the method
+     * was declared to take a variable number of arguments.
+     *
+     * @param method  the object that represents method
+     * @return {@code true} if the method was declared
+     *         to take a variable number of arguments;
+     *         {@code false} otherwise
+     */
+    @Override
+    protected boolean isVarArgs(Method method) {
+        return method.isVarArgs();
+    }
+
+    /**
+     * 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 Modifier.isPublic(method.getModifiers()) && method.getName().equals(this.name);
+    }
+}