diff options
author | slewis | 2014-03-27 00:55:31 +0000 |
---|---|---|
committer | slewis | 2014-03-27 00:55:31 +0000 |
commit | 20964f407f28056294dae2ec4885a81c96f55284 (patch) | |
tree | 61f8ccdf866f3c690450719a6e20b684f4a98968 /framework/bundles/org.eclipse.ecf/src | |
parent | 69a9eeac0aa150a75ecf70bac5be9750c39eb90a (diff) | |
parent | ea88e73ed7fcf5ecbe7e7e9e004ced274e530417 (diff) | |
download | org.eclipse.ecf-20964f407f28056294dae2ec4885a81c96f55284.tar.gz org.eclipse.ecf-20964f407f28056294dae2ec4885a81c96f55284.tar.xz org.eclipse.ecf-20964f407f28056294dae2ec4885a81c96f55284.zip |
Merge remote-tracking branch 'origin/master' into bug421569
Change-Id: I944b5302570995d64fd9ed8b78764b7f81385b64
Diffstat (limited to 'framework/bundles/org.eclipse.ecf/src')
-rw-r--r-- | framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java b/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java new file mode 100644 index 000000000..128ade165 --- /dev/null +++ b/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2010 Markus Alexander Kuppe. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Alexander Kuppe (ecf-dev_eclipse.org <at> lemmster <dot> de) - initial API and implementation + ******************************************************************************/ +package org.eclipse.ecf.core.util.reflection; + +import java.lang.reflect.Method; +import java.util.*; + +/** + * @since 3.3 + */ +public class ClassUtil { + + private static Map convertor = new HashMap(); + + static { + convertor.put(boolean.class, Boolean.class); + convertor.put(byte.class, Byte.class); + convertor.put(char.class, Character.class); + convertor.put(double.class, Double.class); + convertor.put(float.class, Float.class); + convertor.put(int.class, Integer.class); + convertor.put(long.class, Long.class); + convertor.put(short.class, Short.class); + } + + /** + * @param aClass The Class providing method under question (Must not be null) + * @param aMethodName The method name to search for (Must not be null) + * @param someParameterTypes Method arguments (May be null or parameters) + * @return A match. If more than one method matched (due to overloading) an arbitrary match is taken + * @throws NoSuchMethodException If a match cannot be found + */ + public static Method getMethod(final Class aClass, String aMethodName, final Class[] someParameterTypes) throws NoSuchMethodException { + // no args makes matching simple + if (someParameterTypes == null || someParameterTypes.length == 0) { + return aClass.getMethod(aMethodName, (Class[]) null); + } + return getMethod(aClass.getMethods(), aMethodName, someParameterTypes); + } + + /** + * @param aClass The Class providing method under question (Must not be null) + * @param aMethodName The method name to search for (Must not be null) + * @param someParameterTypes Method arguments (May be null or parameters) + * @return A match. If more than one method matched (due to overloading) an arbitrary match is taken + * @throws NoSuchMethodException If a match cannot be found + */ + public static Method getDeclaredMethod(final Class aClass, String aMethodName, final Class[] someParameterTypes) throws NoSuchMethodException { + // no args makes matching simple + if (someParameterTypes == null || someParameterTypes.length == 0) { + return aClass.getDeclaredMethod(aMethodName, (Class[]) null); + } + return getMethod(aClass.getDeclaredMethods(), aMethodName, someParameterTypes); + } + + private static Method getMethod(final Method[] candidates, String aMethodName, final Class[] someParameterTypes) throws NoSuchMethodException { + // match parameters to determine callee + final int parameterCount = someParameterTypes.length; + aMethodName = aMethodName.intern(); + + final TreeSet matches = new TreeSet(new MethodComparator(someParameterTypes)); + OUTER: for (int i = 0; i < candidates.length; i++) { + final Method candidate = candidates[i]; + final String candidateMethodName = candidate.getName().intern(); + final Class[] candidateParameterTypes = candidate.getParameterTypes(); + final int candidateParameterCount = candidateParameterTypes.length; + if (candidateParameterCount == parameterCount && aMethodName == candidateMethodName) { + for (int j = 0; j < candidateParameterCount; j++) { + final Class clazzA = candidateParameterTypes[j]; + final Class clazzB = someParameterTypes[j]; + if (clazzB != null && !isAssignableFrom(clazzA, clazzB)) { + continue OUTER; + } + } + matches.add(candidate); + } + } + + // if no match has been found, fail with NSME + if (matches.size() == 0) { + throw new NoSuchMethodException("No such method: " + aMethodName + "(" + Arrays.asList(someParameterTypes) + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + return (Method) matches.first(); + } + + // extends Class.isAssingable(Class) with autoboxing + private static boolean isAssignableFrom(Class clazzA, Class clazzB) { + if (!(clazzA.isPrimitive() ^ clazzB.isPrimitive())) { + return clazzA.isAssignableFrom(clazzB); + } else if (clazzA.isPrimitive()) { + final Class oClazzA = (Class) convertor.get(clazzA); + return oClazzA.isAssignableFrom(clazzB); + } else { + final Class oClazzB = (Class) convertor.get(clazzB); + return clazzA.isAssignableFrom(oClazzB); + } + } + + private static class MethodComparator implements Comparator { + + private final Class[] parameterTypes; + + public MethodComparator(Class[] someParameterTypes) { + parameterTypes = someParameterTypes; + } + + public int compare(Object object1, Object object2) { + final Class[] pt1 = ((Method) object1).getParameterTypes(); + final Class[] pt2 = ((Method) object2).getParameterTypes(); + + if (Arrays.equals(pt1, pt2)) { + return 0; + } else if (Arrays.equals(parameterTypes, pt1)) { + return -1; + } else { + return 1; + } + } + } +} |