Source code: com/memoire/silk/SilkJavaMethod.java
1
2
3 package com.memoire.silk;
4 import com.memoire.silk.*;
5
6
7 import java.lang.reflect.*;
8
9 /** @author Peter Norvig, peter@norvig.com http://www.norvig.com
10 * Copyright 1998 Peter Norvig, see http://www.norvig.com/license.html */
11
12 public class SilkJavaMethod extends SilkProcedure {
13
14 Class[] argClasses;
15 Method method;
16 boolean isStatic;
17
18 public SilkJavaMethod(String methodName, Object targetClassName,
19 Object argClassNames) {
20 this.name = targetClassName + "." + methodName;
21 try {
22 argClasses = classArray(argClassNames);
23 method = toClass(targetClassName).getMethod(methodName, argClasses);
24 isStatic = Modifier.isStatic(method.getModifiers());
25 } catch (ClassNotFoundException e) {
26 error("Bad class, can't get method " + name);
27 } catch (NoSuchMethodException e) {
28 error("Can't get method " + name);
29 }
30
31 }
32
33 /** Apply the method to a list of arguments. **/
34 public Object apply(SilkScheme interpreter, Object args) {
35 try {
36 if (isStatic) return method.invoke(null, toArray(args));
37 else return method.invoke(first(args), toArray(rest(args)));
38 } catch (IllegalAccessException e) { ; }
39 catch (IllegalArgumentException e) { ; }
40 catch (InvocationTargetException e) { ; }
41 catch (NullPointerException e) { ; }
42 return error("Bad Java Method application:" + this
43 + stringify(args) + ", ");
44 }
45
46 public static Class toClass(Object arg) throws ClassNotFoundException {
47 if (arg instanceof Class) return (Class)arg;
48 arg = stringify(arg, false);
49
50 if (arg.equals("void")) return java.lang.Void.TYPE;
51 else if (arg.equals("boolean")) return java.lang.Boolean.TYPE;
52 else if (arg.equals("char")) return java.lang.Character.TYPE;
53 else if (arg.equals("byte")) return java.lang.Byte.TYPE;
54 else if (arg.equals("short")) return java.lang.Short.TYPE;
55 else if (arg.equals("int")) return java.lang.Integer.TYPE;
56 else if (arg.equals("long")) return java.lang.Long.TYPE;
57 else if (arg.equals("float")) return java.lang.Float.TYPE;
58 else if (arg.equals("double")) return java.lang.Double.TYPE;
59 else return Class.forName((String)arg);
60 }
61
62 /** Convert a list of Objects into an array. Peek at the argClasses
63 * array to see what's expected. That enables us to convert between
64 * Double and Integer, something Java won't do automatically. **/
65 public Object[] toArray(Object args) {
66 int n = length(args);
67 int diff = n - argClasses.length;
68 if (diff != 0)
69 error(Math.abs(diff) + " too " + ((diff>0) ? "many" : "few")
70 + " args to " + name);
71 Object[] array = new Object[n];
72 for(int i = 0; i < n && i < argClasses.length; i++) {
73 if (argClasses[i] == java.lang.Integer.TYPE)
74 array[i] = new Integer((int)num(first(args)));
75 else
76 array[i] = first(args);
77 args = rest(args);
78 }
79 return array;
80 }
81
82 /** Convert a list of class names into an array of Classes. **/
83 public Class[] classArray(Object args) throws ClassNotFoundException {
84 int n = length(args);
85 Class[] array = new Class[n];
86 for(int i = 0; i < n; i++) {
87 array[i] = toClass(first(args));
88 args = rest(args);
89 }
90 return array;
91 }
92
93 }