Split Reflections.invokeMethodArgs into Method find and Method invoke

Gives more control over what method gets executed.


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/eb4ac4c1
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/eb4ac4c1
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/eb4ac4c1

Branch: refs/heads/master
Commit: eb4ac4c1493a563982c98eb8cbd97e47bf9a6700
Parents: 6607ccb
Author: Svetoslav Neykov <svetoslav.ney...@cloudsoftcorp.com>
Authored: Tue Dec 13 11:11:41 2016 +0200
Committer: Svetoslav Neykov <svetoslav.ney...@cloudsoftcorp.com>
Committed: Tue Dec 13 11:11:41 2016 +0200

----------------------------------------------------------------------
 .../brooklyn/util/javalang/Reflections.java     | 72 ++++++++++++++++----
 .../brooklyn/util/javalang/ReflectionsTest.java | 18 +++++
 2 files changed, 75 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/eb4ac4c1/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java 
b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
index 95bbf7f..fba72b5 100644
--- 
a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
+++ 
b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
@@ -842,18 +842,26 @@ public class Reflections {
     }
     /** as {@link #invokeMethodFromArgs(Object, String, List)} but giving 
control over whether to set it accessible */
     public static Maybe<Object> invokeMethodFromArgs(Object clazzOrInstance, 
String method, List<?> args, boolean setAccessible) throws 
IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+        Maybe<Method> maybeMethod = getMethodFromArgs(clazzOrInstance, method, 
args);
+        if (maybeMethod.isAbsent()) {
+            return Maybe.absent(Maybe.getException(maybeMethod));
+        }
+        Method m = maybeMethod.get();
+
+        return Maybe.of(invokeMethodFromArgs(clazzOrInstance, m, args, 
setAccessible));
+    }
+
+    /** searches for the given method on the given clazz or instance, doing 
reasonably good matching on args etc */
+    public static Maybe<Method> getMethodFromArgs(Object clazzOrInstance, 
String method, List<?> args) {
         Preconditions.checkNotNull(clazzOrInstance, "clazz or instance");
         Preconditions.checkNotNull(method, "method");
         Preconditions.checkNotNull(args, "args to "+method);
         
         Class<?> clazz;
-        Object instance;
         if (clazzOrInstance instanceof Class) {
             clazz = (Class<?>)clazzOrInstance;
-            instance = null;
         } else {
             clazz = clazzOrInstance.getClass();
-            instance = clazzOrInstance;
         }
         
         Object[] argsArray = args.toArray();
@@ -873,25 +881,16 @@ public class Reflections {
                             }
                         }
                         if (varargsMatch) {
-                            Object varargs = Array.newInstance(varargType, 
argsArray.length+1 - parameterTypes.length);
-                            for (int i=parameterTypes.length-1; 
i<argsArray.length; i++) {
-                                Boxing.setInArray(varargs, 
i+1-parameterTypes.length, argsArray[i], varargType);
-                            }
-                            Object[] newArgsArray = new 
Object[parameterTypes.length];
-                            System.arraycopy(argsArray, 0, newArgsArray, 0, 
parameterTypes.length-1);
-                            newArgsArray[parameterTypes.length-1] = varargs;
-                            if (setAccessible) m.setAccessible(true);
-                            return Maybe.of(m.invoke(instance, newArgsArray));
+                            return Maybe.of(m);
                         }
                     }
                 }
                 if (typesMatch(argsArray, parameterTypes)) {
-                    if (setAccessible) m.setAccessible(true);
-                    return Maybe.of(m.invoke(instance, argsArray));
+                    return Maybe.of(m);
                 }
             }
         }
-        
+
         List<String> argTypes = Lists.newArrayList();
         for (Object arg : args) {
             argTypes.add(arg == null ? "<null>" : 
arg.getClass().getSimpleName());
@@ -899,6 +898,49 @@ public class Reflections {
         return Maybe.absent("Method '"+method+"' not found matching given args 
of type "+argTypes);
     }
 
+    /** invokes the given method on the given clazz or instance, assuming that 
the method matches passed arguments
+     * @throws InvocationTargetException 
+     * @throws IllegalAccessException 
+     * @throws IllegalArgumentException */
+    public static Object invokeMethodFromArgs(Object clazzOrInstance, Method 
m, List<?> args)
+            throws IllegalAccessException, InvocationTargetException {
+        return invokeMethodFromArgs(clazzOrInstance, m, args, false);
+    }
+
+    /** as {@link #invokeMethodFromArgs(Object, Method, List)} but giving 
control over whether to set it accessible */
+    public static Object invokeMethodFromArgs(Object clazzOrInstance, Method 
m, List<?> args, boolean setAccessible)
+            throws IllegalAccessException, InvocationTargetException {
+        Preconditions.checkNotNull(clazzOrInstance, "clazz or instance");
+        Preconditions.checkNotNull(m, "method");
+        Preconditions.checkNotNull(args, "args to "+m);
+
+        Object instance;
+        if (clazzOrInstance instanceof Class) {
+            instance = null;
+        } else {
+            instance = clazzOrInstance;
+        }
+
+        Object[] argsArray = args.toArray();
+
+        Class<?>[] parameterTypes = m.getParameterTypes();
+        if (m.isVarArgs()) {
+            Class<?> varargType = 
parameterTypes[parameterTypes.length-1].getComponentType();
+            Object varargs = Array.newInstance(varargType, argsArray.length+1 
- parameterTypes.length);
+            for (int i=parameterTypes.length-1; i<argsArray.length; i++) {
+                Boxing.setInArray(varargs, i+1-parameterTypes.length, 
argsArray[i], varargType);
+            }
+            Object[] newArgsArray = new Object[parameterTypes.length];
+            System.arraycopy(argsArray, 0, newArgsArray, 0, 
parameterTypes.length-1);
+            newArgsArray[parameterTypes.length-1] = varargs;
+            if (setAccessible) m.setAccessible(true);
+            return m.invoke(instance, newArgsArray);
+        } else {
+            if (setAccessible) m.setAccessible(true);
+            return m.invoke(instance, argsArray);
+        }
+    }
+
     /** true iff all args match the corresponding types */
     public static boolean typesMatch(Object[] argsArray, Class<?>[] 
parameterTypes) {
         if (argsArray.length != parameterTypes.length)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/eb4ac4c1/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
 
b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
index b6bb63c..b7d3975 100644
--- 
a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
+++ 
b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
@@ -129,6 +129,24 @@ public class ReflectionsTest {
     }
     
     @Test
+    public void testMethodInvocation() throws Exception {
+        Method m1Short = CI1.class.getMethod("m1", String.class, int.class);
+        Method m1Long = CI1.class.getMethod("m1", String.class, int.class, 
int.class, int[].class);
+        
+        Assert.assertEquals(Reflections.invokeMethodFromArgs(CI1.class, 
m1Short, Arrays.<Object>asList("hello", 3)), "hello3");
+        Assert.assertEquals(Reflections.invokeMethodFromArgs(CI1.class, 
m1Long, Arrays.<Object>asList("hello", 3, 4, 5)), "hello12");
+    }
+    
+    @Test
+    public void testGetMethod() throws Exception {
+        Method m1Short = CI1.class.getMethod("m1", String.class, int.class);
+        Method m1Long = CI1.class.getMethod("m1", String.class, int.class, 
int.class, int[].class);
+        
+        Assert.assertEquals(Reflections.getMethodFromArgs(CI1.class, "m1", 
Arrays.<Object>asList("hello", 3)).get(), m1Short);
+        Assert.assertEquals(Reflections.getMethodFromArgs(CI1.class, "m1", 
Arrays.<Object>asList("hello", 3, 4, 5)).get(), m1Long);
+    }
+    
+    @Test
     public void testConstruction() throws Exception {
         Assert.assertEquals(Reflections.invokeConstructorFromArgs(CI1.class, 
new Object[] {"hello", 3}).get().constructorArgs, ImmutableList.of("hello", 3));
         Assert.assertEquals(Reflections.invokeConstructorFromArgs(CI1.class, 
new Object[] {"hello", 3, 4, 5}).get().constructorArgs, 
ImmutableList.of("hello", 3, 4, 5));

Reply via email to