| /* gnu.java.beans.decoder.MethodFinder |
| Copyright (C) 2004 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath 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 for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| package gnu.java.beans.decoder; |
| |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Method; |
| import java.util.HashMap; |
| |
| class MethodFinder |
| { |
| /** Provides a mapping between a wrapper class and its corresponding primitive's type. */ |
| private static HashMap typeMapping = new HashMap(); |
| |
| static { |
| typeMapping.put(Byte.class, Byte.TYPE); |
| typeMapping.put(Short.class, Short.TYPE); |
| typeMapping.put(Integer.class, Integer.TYPE); |
| typeMapping.put(Long.class, Long.TYPE); |
| typeMapping.put(Float.class, Float.TYPE); |
| typeMapping.put(Double.class, Double.TYPE); |
| |
| typeMapping.put(Character.class, Character.TYPE); |
| typeMapping.put(Boolean.class, Boolean.TYPE); |
| } |
| |
| private MethodFinder() |
| { |
| } |
| |
| /** Searches a Method which can accept the given arguments. |
| * |
| * @param klass |
| * @param name |
| * @param arguments |
| * @return |
| * @throws NoSuchMethodException |
| */ |
| static Method getMethod(Class klass, String name, Object[] arguments) |
| throws NoSuchMethodException |
| { |
| // prepares array containing the types of the arguments |
| Class[] argumentTypes = getArgumentTypes(arguments); |
| |
| Method[] methods = klass.getMethods(); |
| |
| // iterates over all public methods |
| for (int i = 0; i < methods.length; i++) |
| { |
| if (methods[i].getName().equals(name)) |
| { |
| if (matchingArgumentTypes(methods[i].getParameterTypes(), |
| argumentTypes)) |
| return methods[i]; |
| } |
| } |
| |
| throw new NoSuchMethodException( |
| "Could not find a matching method named " |
| + name |
| + "() in class " |
| + klass); |
| } |
| |
| static Constructor getConstructor(Class klass, Object[] arguments) |
| throws NoSuchMethodException |
| { |
| Class[] argumentTypes = getArgumentTypes(arguments); |
| Constructor[] constructors = klass.getConstructors(); |
| |
| // iterates over all public methods |
| for (int i = 0; i < constructors.length; i++) |
| { |
| if (matchingArgumentTypes(constructors[i].getParameterTypes(), |
| argumentTypes)) |
| return constructors[i]; |
| } |
| |
| throw new NoSuchMethodException( |
| "Could not find a matching constructor in class " + klass); |
| } |
| |
| /** Transforms an array of argument objects into an array of argument types. |
| * For each argument being null the argument is null, too. An argument type |
| * being null means: Accepts everything (although this can be ambigous). |
| * |
| * @param arguments |
| * @return |
| */ |
| private static Class[] getArgumentTypes(Object[] arguments) |
| { |
| if (arguments == null) |
| return new Class[0]; |
| |
| // prepares array containing the types of the arguments |
| Class[] argumentTypes = new Class[arguments.length]; |
| for (int i = 0; i < arguments.length; i++) |
| argumentTypes[i] = |
| (arguments[i] == null) ? null : arguments[i].getClass(); |
| return argumentTypes; |
| } |
| |
| /** Tests whether the argument types supplied to the method argument types |
| * are assignable. In addition to the assignment specifications this method |
| * handles the primitive's wrapper classes as if they were of their |
| * primitive type (e.g Boolean.class equals Boolean.TYPE). |
| * When a supplied argument type is null it is assumed that no argument |
| * object was supplied for it and the test for this particular parameter will |
| * pass. |
| * |
| * @param methodArgTypes |
| * @param suppliedArgTypes |
| * @return |
| */ |
| private static boolean matchingArgumentTypes( |
| Class[] methodArgTypes, |
| Class[] suppliedArgTypes) |
| { |
| if (methodArgTypes.length != suppliedArgTypes.length) |
| return false; |
| |
| for (int i = 0; i < methodArgTypes.length; i++) |
| { |
| if (suppliedArgTypes[i] == null) |
| { |
| // by definition a non-existant argument type (null) can be converted to everything |
| continue; |
| } |
| else if (typeMapping.containsKey(suppliedArgTypes[i])) |
| { |
| Class primitiveType = |
| (Class) typeMapping.get(suppliedArgTypes[i]); |
| if (!(methodArgTypes[i].isAssignableFrom(suppliedArgTypes[i]) |
| || methodArgTypes[i].isAssignableFrom(primitiveType))) |
| return false; |
| } |
| else if (!methodArgTypes[i].isAssignableFrom(suppliedArgTypes[i])) |
| return false; |
| } |
| |
| return true; |
| } |
| } |