52f7f9cc954cbb9e2af6904d602add3890b9d0f0
[org.ibex.core.git] / src / org / ibex / js / JSReflection.java
1 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] 
2 package org.ibex.js; 
3
4 import org.ibex.util.*; 
5 import java.io.*;
6 import java.util.*;
7 import java.lang.reflect.*;
8
9 /** Automatic JS-ification via Reflection (not for use in the core) */
10 public class JSReflection extends JS {
11
12     public static JS wrap(Object o) throws JSExn {
13         if (o == null) return null;
14         if (o instanceof String) return JS.S((String)o);
15         if (o instanceof Boolean) return JS.B(((Boolean)o).booleanValue());
16         if (o instanceof Number) return JS.N((Number)o);
17         if (o instanceof JS) return (JS)o;
18         if (o instanceof Object[]) {
19             // FIXME: get element type here
20         }
21         throw new JSExn("Reflection object tried to return a " + o.getClass().getName());
22     }
23
24     public static class Array extends JS {
25         final Object[] arr;
26         public Array(Object[] arr) { this.arr = arr; }
27         // FEATURE: Add a JSCounterEnumeration
28         public Enumeration keys() throws JSExn {
29             return new Enumeration(null) {
30                 private int n = 0;
31                 public boolean _hasMoreElements() { return n < arr.length; }
32                 public JS _nextElement() {
33                     return n >= arr.length ? null : JS.N(n++);
34                 }
35             };
36         }
37         public JS get(JS key) throws JSExn { return wrap(arr[toInt(key)]); }
38         public void put(JS key, JS val) throws JSExn { throw new JSExn("can't write to org.ibex.js.Reflection.Array's"); }
39     }
40
41     // FIXME public static class Hash { }
42     // FIXME public Enumeration keys() throws JSExn {  }
43
44     public JS get(JS key) throws JSExn {
45         String k = toString(key);
46         try {
47             Field f = this.getClass().getField(k);
48             return wrap(f.get(this));
49         } catch (NoSuchFieldException nfe) {
50         } catch (IllegalAccessException nfe) {
51         } catch (SecurityException nfe) { }
52
53         try {
54             Method[] methods = this.getClass().getMethods();
55             for(int i=0; i<methods.length; i++) if (methods[i].getName().equals(k)) return METHOD;
56         } catch (SecurityException nfe) { }
57         return null;
58     }
59
60     public void put(JS key, JS val) throws JSExn {
61         throw new JSExn("put() not supported yet");
62     }
63
64     public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
65         String k = toString(method);
66         try {
67             Method[] methods = this.getClass().getMethods();
68             for(int j=0; j<methods.length; j++) {
69                 if (methods[j].getName().equals(k) && methods[j].getParameterTypes().length == nargs) {
70                     Object[] args = new Object[nargs];
71                     for(int i = 0; i<args.length; i++) {
72                         if (i==0) args[i] = a0;
73                         else if (i==1) args[i] = a1;
74                         else if (i==2) args[i] = a2;
75                         else args[i] = rest[i-3];
76                     }
77                     return wrap(methods[j].invoke(this, args));
78                 }
79             }
80         } catch (IllegalAccessException nfe) {
81         } catch (InvocationTargetException it) {
82             Throwable ite = it.getTargetException();
83             if (ite instanceof JSExn) throw ((JSExn)ite);
84             JS.warn(ite);
85             throw new JSExn("unhandled reflected exception: " + ite.toString());
86         } catch (SecurityException nfe) { }
87         throw new JSExn("called a reflection method with the wrong number of arguments");
88     }
89