KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgroups > blocks > MethodCall


1 package org.jgroups.blocks;
2
3
4 import org.apache.commons.logging.Log;
5 import org.apache.commons.logging.LogFactory;
6
7 import java.io.Externalizable JavaDoc;
8 import java.io.IOException JavaDoc;
9 import java.io.ObjectInput JavaDoc;
10 import java.io.ObjectOutput JavaDoc;
11 import java.lang.reflect.InvocationTargetException JavaDoc;
12 import java.lang.reflect.Method JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.Iterator JavaDoc;
16
17
18
19
20 /**
21  * A method call is the JavaGroup representation of a remote method.
22  * It includes the name of the method (case sensitive) and a list of arguments.
23  * A method call is serializable and can be passed over the wire.
24  * @author Bela Ban
25  * @version $Revision: 1.16 $
26  */

27 public class MethodCall implements Externalizable JavaDoc {
28
29     static final long serialVersionUID=7873471327078957662L;
30
31     /** the name of the method, case sensitive */
32     protected String JavaDoc method_name=null;
33
34     /** the arguments of the method */
35     protected Object JavaDoc[] args=null;
36
37     /** the class types, e.g. new Class[]{String.class, int.class} */
38     protected Class JavaDoc[] types=null;
39
40     /** the signature, e.g. new String[]{String.class.getName(), int.class.getName()} */
41     protected String JavaDoc[] signature=null;
42
43     /** the Method of the call */
44     protected Method JavaDoc method=null;
45
46     protected static final Log log=LogFactory.getLog(MethodCall.class);
47
48     /** which mode to use */
49     protected short mode=OLD;
50
51     /** infer the method from the arguments */
52     protected static final short OLD=1;
53
54     /** explicitly ship the method, caller has to determine method himself */
55     protected static final short METHOD=2;
56
57     /** use class information */
58     protected static final short TYPES=3;
59
60     /** provide a signature, similar to JMX */
61     protected static final short SIGNATURE=4;
62
63
64     /**
65      * creates an empty method call, this is always invalid, until
66      * <code>setName()</code> has been called
67      */

68     public MethodCall() {
69     }
70
71
72     public MethodCall(Method JavaDoc method) {
73         this(method, null);
74     }
75
76     public MethodCall(Method JavaDoc method, Object JavaDoc[] arguments) {
77         init(method);
78         if(arguments != null) args=arguments;
79     }
80
81     /**
82      *
83      * @param method_name
84      * @param args
85      * @deprecated Use one of the constructors that take class types as arguments
86      */

87     public MethodCall(String JavaDoc method_name, Object JavaDoc[] args) {
88         this.method_name=method_name;
89         this.mode=OLD;
90         this.args=args;
91     }
92
93
94     public MethodCall(String JavaDoc method_name, Object JavaDoc[] args, Class JavaDoc[] types) {
95         this.method_name=method_name;
96         this.args=args;
97         this.types=types;
98         this.mode=TYPES;
99     }
100
101     public MethodCall(String JavaDoc method_name, Object JavaDoc[] args, String JavaDoc[] signature) {
102         this.method_name=method_name;
103         this.args=args;
104         this.signature=signature;
105         this.mode=SIGNATURE;
106     }
107
108     void init(Method JavaDoc method) {
109         this.method=method;
110         this.mode=METHOD;
111         method_name=method.getName();
112     }
113
114
115     public int getMode() {
116         return mode;
117     }
118
119
120
121     /**
122      * returns the name of the method to be invoked using this method call object
123      * @return a case sensitive name, can be null for an invalid method call
124      */

125     public String JavaDoc getName() {
126         return method_name;
127     }
128
129     /**
130      * sets the name for this MethodCall and allowing you to reuse the same object for
131      * a different method invokation of a different method
132      * @param n - a case sensitive method name
133      */

134     public void setName(String JavaDoc n) {
135         method_name=n;
136     }
137
138     /**
139      * returns an ordered list of arguments used for the method invokation
140      * @return returns the list of ordered arguments
141      */

142     public Object JavaDoc[] getArgs() {
143         return args;
144     }
145
146     public void setArgs(Object JavaDoc[] args) {
147         if(args != null)
148             this.args=args;
149     }
150
151     public Method JavaDoc getMethod() {
152         return method;
153     }
154
155
156
157
158     /**
159      *
160      * @param target_class
161      * @return
162      * @throws Exception
163      */

164     Method JavaDoc findMethod(Class JavaDoc target_class) throws Exception JavaDoc {
165         int len=args != null? args.length : 0;
166         Method JavaDoc m;
167
168         Method JavaDoc[] methods=getAllMethods(target_class);
169         for(int i=0; i < methods.length; i++) {
170             m=methods[i];
171             if(m.getName().equals(method_name)) {
172                 if(m.getParameterTypes().length == len)
173                     return m;
174             }
175         }
176
177         return null;
178     }
179
180
181     /**
182      * The method walks up the class hierarchy and returns <i>all</i> methods of this class
183      * and those inherited from superclasses and superinterfaces.
184      */

185     Method JavaDoc[] getAllMethods(Class JavaDoc target) {
186
187         Class JavaDoc superclass = target;
188         List JavaDoc methods = new ArrayList JavaDoc();
189         int size = 0;
190
191         while(superclass != null) {
192             Method JavaDoc[] m = superclass.getDeclaredMethods();
193             methods.add(m);
194             size += m.length;
195             superclass = superclass.getSuperclass();
196         }
197
198         Method JavaDoc[] result = new Method JavaDoc[size];
199         int index = 0;
200         for(Iterator JavaDoc i = methods.iterator(); i.hasNext();) {
201             Method JavaDoc[] m = (Method JavaDoc[])i.next();
202             System.arraycopy(m, 0, result, index, m.length);
203             index += m.length;
204         }
205         return result;
206     }
207
208     /**
209      * Returns the first method that matches the specified name and parameter types. The overriding
210      * methods have priority. The method is chosen from all the methods of the current class and all
211      * its superclasses and superinterfaces.
212      *
213      * @return the matching method or null if no mathching method has been found.
214      */

215     Method JavaDoc getMethod(Class JavaDoc target, String JavaDoc methodName, Class JavaDoc[] types) {
216
217         if (types == null) {
218             types = new Class JavaDoc[0];
219         }
220
221         Method JavaDoc[] methods = getAllMethods(target);
222         methods: for(int i = 0; i < methods.length; i++) {
223             Method JavaDoc m = methods[i];
224             if (!methodName.equals(m.getName())) {
225                 continue methods;
226             }
227             Class JavaDoc[] parameters = m.getParameterTypes();
228             if (types.length != parameters.length) {
229                 continue methods;
230             }
231             for(int j = 0; j < types.length; j++) {
232                 if (!types[j].equals(parameters[j])) {
233                     continue methods;
234                 }
235             }
236             return m;
237         }
238         return null;
239     }
240
241
242     /**
243      * Invokes the method with the supplied arguments against the target object.
244      * If a method lookup is provided, it will be used. Otherwise, the default
245      * method lookup will be used.
246      * @param target - the object that you want to invoke the method on
247      * @return an object
248      */

249     public Object JavaDoc invoke(Object JavaDoc target) throws Throwable JavaDoc {
250         Class JavaDoc cl;
251         Method JavaDoc meth=null;
252         Object JavaDoc retval=null;
253
254
255         if(method_name == null || target == null) {
256             if(log.isErrorEnabled()) log.error("method name or target is null");
257             return null;
258         }
259         cl=target.getClass();
260         try {
261             switch(mode) {
262                 case OLD:
263                     meth=findMethod(cl);
264                     break;
265                 case METHOD:
266                     if(this.method != null)
267                         meth=this.method;
268                     break;
269                 case TYPES:
270                     //meth=cl.getDeclaredMethod(method_name, types);
271
meth = getMethod(cl, method_name, types);
272                     break;
273                 case SIGNATURE:
274                     Class JavaDoc[] mytypes=null;
275                     if(signature != null)
276                         mytypes=getTypesFromString(cl, signature);
277                     //meth=cl.getDeclaredMethod(method_name, mytypes);
278
meth = getMethod(cl, method_name, mytypes);
279                     break;
280                 default:
281                     if(log.isErrorEnabled()) log.error("mode " + mode + " is invalid");
282                     break;
283             }
284
285             if(meth != null) {
286                 retval=meth.invoke(target, args);
287             }
288             else {
289                 if(log.isErrorEnabled()) log.error("method " + method_name + " not found");
290             }
291             return retval;
292         }
293         catch(InvocationTargetException JavaDoc inv_ex) {
294             throw inv_ex.getTargetException();
295         }
296         catch(NoSuchMethodException JavaDoc no) {
297             StringBuffer JavaDoc sb=new StringBuffer JavaDoc();
298             sb.append("found no method called ").append(method_name).append(" in class ");
299             sb.append(cl.getName()).append(" with (");
300             if(args != null) {
301                 for(int i=0; i < args.length; i++) {
302                     if(i > 0)
303                         sb.append(", ");
304                     sb.append((args[i] != null)? args[i].getClass().getName() : "null");
305                 }
306             }
307             sb.append(") formal parameters");
308             log.error(sb.toString());
309             throw no;
310         }
311         catch(Throwable JavaDoc e) {
312             // e.printStackTrace(System.err);
313
if(log.isErrorEnabled()) log.error("exception in invoke()", e);
314             throw e;
315         }
316     }
317
318     public Object JavaDoc invoke(Object JavaDoc target, Object JavaDoc[] args) throws Throwable JavaDoc {
319         if(args != null)
320             this.args=args;
321         return invoke(target);
322     }
323
324
325     Class JavaDoc[] getTypesFromString(Class JavaDoc cl, String JavaDoc[] signature) throws Exception JavaDoc {
326         String JavaDoc name;
327         Class JavaDoc parameter;
328         Class JavaDoc[] mytypes=new Class JavaDoc[signature.length];
329
330         for(int i=0; i < signature.length; i++) {
331             name=signature[i];
332             if("long".equals(name))
333                 parameter=long.class;
334             else if("int".equals(name))
335                 parameter=int.class;
336             else if("short".equals(name))
337                 parameter=short.class;
338             else if("char".equals(name))
339                 parameter=char.class;
340             else if("byte".equals(name))
341                 parameter=byte.class;
342             else if("float".equals(name))
343                 parameter=float.class;
344             else if("double".equals(name))
345                 parameter=double.class;
346             else if("boolean".equals(name))
347                 parameter=boolean.class;
348             else
349                 parameter=Class.forName(name, false, cl.getClassLoader());
350             mytypes[i]=parameter;
351         }
352         return mytypes;
353     }
354
355
356     public String JavaDoc toString() {
357         StringBuffer JavaDoc ret=new StringBuffer JavaDoc();
358         boolean first=true;
359         ret.append(method_name).append('(');
360         if(args != null) {
361             for(int i=0; i < args.length; i++) {
362                 if(first) {
363                     first=false;
364                 }
365                 else {
366                     ret.append(", ");
367                 }
368                 ret.append(args[i]);
369             }
370         }
371         ret.append(')');
372         return ret.toString();
373     }
374
375     public String JavaDoc toStringDetails() {
376         StringBuffer JavaDoc ret=new StringBuffer JavaDoc();
377         ret.append("MethodCall (name=" + method_name);
378         ret.append(", number of args=" + (args != null? args.length : 0) + ')');
379         if(args != null) {
380             ret.append("\nArgs:");
381             for(int i=0; i < args.length; i++) {
382                 ret.append("\n[" + args[i] + " (" +
383                            (args[i] != null? args[i].getClass().getName() : "null") + ")]");
384             }
385         }
386         return ret.toString();
387     }
388
389
390     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc {
391         out.writeUTF(method_name);
392         out.writeObject(args);
393         out.writeShort(mode);
394
395         switch(mode) {
396             case OLD:
397                 break;
398             case METHOD:
399                 out.writeObject(method.getParameterTypes());
400                 out.writeObject(method.getDeclaringClass());
401                 break;
402             case TYPES:
403                 out.writeObject(types);
404                 break;
405             case SIGNATURE:
406                 out.writeObject(signature);
407 // out.writeInt(signature != null? signature.length : 0);
408
// for(int i=0; i < signature.length; i++) {
409
// String s=signature[i];
410
// out.writeUTF(s);
411
// }
412
break;
413             default:
414                 if(log.isErrorEnabled()) log.error("mode " + mode + " is invalid");
415                 break;
416         }
417     }
418
419     public void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
420         method_name=in.readUTF();
421         args=(Object JavaDoc[])in.readObject();
422         mode=in.readShort();
423
424         switch(mode) {
425             case OLD:
426                 break;
427             case METHOD:
428                 Class JavaDoc[] parametertypes=(Class JavaDoc[])in.readObject();
429                 Class JavaDoc declaringclass=(Class JavaDoc)in.readObject();
430                 try {
431                     method=declaringclass.getDeclaredMethod(method_name, parametertypes);
432                 }
433                 catch(NoSuchMethodException JavaDoc e) {
434                     throw new IOException JavaDoc(e.toString());
435                 }
436                 break;
437             case TYPES:
438                 types=(Class JavaDoc[])in.readObject();
439                 break;
440             case SIGNATURE:
441                 signature=(String JavaDoc[])in.readObject();
442 // int len=in.readInt();
443
// if(len > 0) {
444
// signature=new String[len];
445
// for(int i=0; i < len; i++) {
446
// signature[i]=in.readUTF();
447
// }
448
// }
449
break;
450             default:
451                 if(log.isErrorEnabled()) log.error("mode " + mode + " is invalid");
452                 break;
453         }
454     }
455
456
457
458
459 }
460
461
462
463
Popular Tags