Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--framework/bundles/org.eclipse.ecf.sharedobject/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java75
-rw-r--r--tests/bundles/org.eclipse.ecf.tests.sharedobject/src/org/eclipse/ecf/tests/sharedobject/util/reflection/ClassUtilTest.java126
2 files changed, 189 insertions, 12 deletions
diff --git a/framework/bundles/org.eclipse.ecf.sharedobject/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java b/framework/bundles/org.eclipse.ecf.sharedobject/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java
index faca89130..61f6105ff 100644
--- a/framework/bundles/org.eclipse.ecf.sharedobject/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java
+++ b/framework/bundles/org.eclipse.ecf.sharedobject/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java
@@ -11,7 +11,7 @@
package org.eclipse.ecf.core.util.reflection;
import java.lang.reflect.Method;
-import java.util.Arrays;
+import java.util.*;
/**
* @since 2.2
@@ -19,6 +19,19 @@ import java.util.Arrays;
*/
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)
@@ -54,25 +67,63 @@ public class ClassUtil {
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++) {
- Method candidate = candidates[i];
- String candidateMethodName = candidate.getName().intern();
- Class[] candidateParameterTypes = candidate.getParameterTypes();
- int candidateParameterCount = candidateParameterTypes.length;
+ 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++) {
- Class clazzA = candidateParameterTypes[j];
- Class clazzB = someParameterTypes[j];
- // clazzA must be non-null, but clazzB could be null (null given as parameter value)
- // so in that case we consider it a match and continue
- if (!(clazzB == null || clazzA.isAssignableFrom(clazzB))) {
+ final Class clazzA = candidateParameterTypes[j];
+ final Class clazzB = someParameterTypes[j];
+ if (clazzB != null && !isAssignableFrom(clazzA, clazzB)) {
continue OUTER;
}
}
- return candidate;
+ matches.add(candidate);
}
}
+
// if no match has been found, fail with NSME
- throw new NoSuchMethodException("No such method: " + aMethodName + "(" + Arrays.asList(someParameterTypes) + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ 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;
+ }
+ }
}
}
diff --git a/tests/bundles/org.eclipse.ecf.tests.sharedobject/src/org/eclipse/ecf/tests/sharedobject/util/reflection/ClassUtilTest.java b/tests/bundles/org.eclipse.ecf.tests.sharedobject/src/org/eclipse/ecf/tests/sharedobject/util/reflection/ClassUtilTest.java
new file mode 100644
index 000000000..d70a7a55a
--- /dev/null
+++ b/tests/bundles/org.eclipse.ecf.tests.sharedobject/src/org/eclipse/ecf/tests/sharedobject/util/reflection/ClassUtilTest.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * 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.tests.sharedobject.util.reflection;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.eclipse.ecf.core.util.reflection.ClassUtil;
+
+public class ClassUtilTest extends TestCase {
+
+ /**
+ * Test method for {@link org.eclipse.ecf.core.util.reflection.ClassUtil#getMethod(java.lang.Class, java.lang.String, java.lang.Class[])}.
+ */
+ public void testGetPrimitiveMethodWithPrimitive() {
+ testGetMethod(new Class[] {int.class}, new Class[] {int.class}, new Object[]{new Integer(1)});
+ }
+
+ /**
+ * Test method for {@link org.eclipse.ecf.core.util.reflection.ClassUtil#getMethod(java.lang.Class, java.lang.String, java.lang.Class[])}.
+ */
+ public void testGetPrimitiveMethodWithObject() {
+ testGetMethod(new Class[] {Integer.class}, new Class[] {int.class}, new Object[]{new Integer(1)});
+ }
+
+ /**
+ * Test method for {@link org.eclipse.ecf.core.util.reflection.ClassUtil#getMethod(java.lang.Class, java.lang.String, java.lang.Class[])}.
+ */
+ public void testGetObjectMethodWithObject() {
+ testGetMethod(new Class[] {Long.class}, new Class[]{Long.class}, new Object[]{new Long(1L)});
+ }
+
+ /**
+ * Test method for {@link org.eclipse.ecf.core.util.reflection.ClassUtil#getMethod(java.lang.Class, java.lang.String, java.lang.Class[])}.
+ */
+ public void testGetObjectMethodWithPrimitive() {
+ testGetMethod(new Class[] {long.class}, new Class[]{Long.class}, new Object[]{new Long(1L)});
+ }
+
+ /**
+ * Test method for {@link org.eclipse.ecf.core.util.reflection.ClassUtil#getMethod(java.lang.Class, java.lang.String, java.lang.Class[])}.
+ */
+ public void testGetObjectMethodWhenBoth() {
+ testGetMethod(new Class[] {Boolean.class}, new Class[]{Boolean.class}, new Object[]{new Boolean(true)});
+ }
+
+ /**
+ * Test method for {@link org.eclipse.ecf.core.util.reflection.ClassUtil#getMethod(java.lang.Class, java.lang.String, java.lang.Class[])}.
+ */
+ public void testGetPrimitiveMethodWhenBoth() {
+ testGetMethod(new Class[] {boolean.class}, new Class[]{boolean.class}, new Object[]{new Boolean(true)});
+ }
+
+ /**
+ * Test method for {@link org.eclipse.ecf.core.util.reflection.ClassUtil#getMethod(java.lang.Class, java.lang.String, java.lang.Class[])}.
+ */
+ public void testGetMethodWithoutParams() {
+ testGetMethod(new Class[]{}, new Class[]{}, null);
+ }
+
+ /**
+ * Test method for {@link org.eclipse.ecf.core.util.reflection.ClassUtil#getMethod(java.lang.Class, java.lang.String, java.lang.Class[])}.
+ */
+ public void testGetObjectMethodFromSuperclassWithPrimitive() {
+ testGetMethod(new Class[]{float.class}, new Class[]{Float.class}, new Object[]{new Float(1.0)});
+ }
+
+ /**
+ * Test method for {@link org.eclipse.ecf.core.util.reflection.ClassUtil#getMethod(java.lang.Class, java.lang.String, java.lang.Class[])}.
+ */
+ public void testGetPrimitiveMethodFromSuperclassWithObject() {
+ testGetMethod(new Class[]{Float.class}, new Class[]{Float.class}, new Object[]{new Float(1.0)});
+ }
+
+ // helper
+ private void testGetMethod(Class[] searchParameterTypes, Class[] expectedParameterTypes, Object[] params) {
+ Method method = null;
+ try {
+ method = ClassUtil.getMethod(TestClass.class, "foo", searchParameterTypes);
+ } catch (NoSuchMethodException e) {
+ fail("failed to match expected the method: " + e.getMessage());
+ }
+
+ final Class[] someParameterTypes = method.getParameterTypes();
+ assertTrue("Parameters don't match", Arrays.equals(expectedParameterTypes, someParameterTypes));
+
+ try {
+ assertNotNull("executed method from superclass", method.invoke(new TestClass(), params));
+ } catch (IllegalArgumentException e) {
+ fail(e.getMessage());
+ } catch (IllegalAccessException e) {
+ fail(e.getMessage());
+ } catch (InvocationTargetException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ // helper class
+ class TestClass extends AbstractTestClass {
+ public String foo() {return "";}
+ public String foo(final int i) {return "";}
+ public String foo(final Long i) {return "";}
+ public String foo(final boolean b) {return "";}
+ public String foo(final Boolean b) {return "";}
+ }
+
+ abstract class AbstractTestClass {
+ public String foo(final Float f) {return "";}
+ public String foo() {throw new UnsupportedOperationException();}
+ public String foo(final int i) {throw new UnsupportedOperationException();}
+ public String foo(final Long i) {throw new UnsupportedOperationException();}
+ public String foo(final boolean b) {throw new UnsupportedOperationException();};
+ public String foo(final Boolean b) {throw new UnsupportedOperationException();};
+ }
+}

Back to the top