| /* 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; | |
| } | |
| } |