d110f295e34ae179ef95b302d836e97bfd3be629
[scilab.git] / scilab / modules / external_objects_java / src / java / org / scilab / modules / external_objects_java / ScilabJavaMethod.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - 2011 - Calixte DENIZET <calixte@contrib.scilab.org>
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.external_objects_java;
14
15 import java.awt.Component;
16 import java.beans.IntrospectionException;
17 import java.beans.Introspector;
18 import java.beans.MethodDescriptor;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 import java.lang.reflect.Modifier;
26
27 import javax.swing.SwingUtilities;
28
29 /**
30  * A method wrapper
31  *
32  * @author Calixte DENIZET
33  */
34 @SuppressWarnings("serial")
35 public final class ScilabJavaMethod {
36
37     /**
38      * @param obj the object where invoking method
39      * @param returnType the class of the result
40      * @param args the ids of arguments
41      * @return the resulting object
42      */
43     public static Object invoke(String name, Class clazz, Object obj, Class[] returnType, int[] args) throws ScilabJavaException {
44         int nbargs = args.length;
45         Class[] cl = new Class[nbargs];
46         Object[] argsO = new Object[nbargs];
47
48         for (int i = 0; i < nbargs; i++) {
49             argsO[i] = ScilabJavaObject.arraySJO[args[i]].object;
50             cl[i] = ScilabJavaObject.arraySJO[args[i]].clazz;
51
52             if (argsO[i] != null && argsO[i] == cl[i]) {
53                 cl[i] = argsO[i].getClass();
54             }
55         }
56
57         return call(name, clazz, obj, returnType, argsO, cl);
58     }
59
60     /**
61      * @param obj the object where invoking method
62      * @param returnType the class of the result
63      * @param args the Object arguments
64      * @param argsClass the Class of the arguments
65      * @return the resulting object
66      */
67     public static Object call(final String name, final Class clazz, final Object obj, final Class[] returnType, final Object[] args, final Class[] argsClass) throws ScilabJavaException {
68         MethodDescriptor[] mdesc = null;
69         try {
70             mdesc = Introspector.getBeanInfo(clazz).getMethodDescriptors();
71             if (mdesc == null) {
72                 throw new ScilabJavaException("No method " + name + " in the class " + clazz.getName() + " or bad arguments type.");
73             }
74         } catch (IntrospectionException e) {
75             throw new ScilabJavaException("Impossible to get method names on the class " + clazz.getName());
76         }
77
78         try {
79             final Object[] info = FunctionArguments.findMethod(name, mdesc, argsClass, args);
80             final Method meth = (Method) info[0];
81             final Class returned = meth.getReturnType();
82             Object ret = null;
83             final Object[] _args;
84
85             if (!meth.isAccessible()) {
86                 try {
87                     meth.setAccessible(true);
88                 } catch (SecurityException e) { }
89             }
90
91             if (info.length == 2) {
92                 // Method with variable arguments, so they have been modified and are the second element of the returned array
93                 _args = (Object[]) info[1];
94             } else {
95                 _args = args;
96             }
97
98             if (Modifier.isStatic(meth.getModifiers())) {
99                 ret = meth.invoke(null, _args);
100             } else {
101                 if (Component.class.isAssignableFrom(obj.getClass())) {
102                     if (returned == Void.TYPE) {
103                         if (SwingUtilities.isEventDispatchThread()) {
104                             ret = meth.invoke(obj, _args);
105                         } else {
106                             SwingUtilities.invokeLater(new Runnable() {
107
108                                 public void run() {
109                                     try {
110                                         meth.invoke(obj, _args);
111                                     } catch (Exception e) {
112                                         System.err.println(e);
113                                     }
114                                 }
115                             });
116                         }
117                     } else {
118                         if (SwingUtilities.isEventDispatchThread()) {
119                             ret = meth.invoke(obj, _args);
120                         } else {
121                             final Object[] ref = new Object[1];
122                             SwingUtilities.invokeAndWait(new Runnable() {
123                                 public void run() {
124                                     try {
125                                         ref[0] = meth.invoke(obj, _args);
126                                     } catch (Exception e) {
127                                         System.err.println(e);
128                                     }
129                                 }
130                             });
131
132                             ret = ref[0];
133                         }
134                     }
135                 } else {
136                     ret = meth.invoke(obj, _args);
137                 }
138             }
139
140             returnType[0] = ret != null ? ret.getClass() : returned;
141
142             if (returned == double.class || returned == int.class ||
143                     returned == short.class || returned == float.class ||
144                     returned == boolean.class || returned == char.class ||
145                     returned == byte.class || returned == long.class) {
146                 returnType[0] = returned;
147             }
148             return ret;
149         } catch (IllegalAccessException e) {
150             throw new ScilabJavaException("Illegal access to the method " + name + ".");
151         } catch (IllegalArgumentException e) {
152             throw new ScilabJavaException("Illegal argument in the method " + name + ": \n" + e.getMessage());
153         } catch (NullPointerException e) {
154             throw new ScilabJavaException("The method " + name + " is called on a null object.");
155         } catch (ExceptionInInitializerError e) {
156             throw new ScilabJavaException("Initializer error with method " + name + ":\n" + e.getMessage());
157         } catch (InvocationTargetException e) {
158             throw new ScilabJavaException("An exception has been thrown in calling the method " + name + ":\n" + e.getCause().toString());
159         } catch (NoSuchMethodException e) {
160             throw new ScilabJavaException("No method " + name + " in the class " + clazz.getName() + " or bad arguments type.");
161         } catch (InterruptedException e) {
162             throw new ScilabJavaException("EDT has been interrupted...");
163         }
164     }
165 }