2f163e7f2d1a7e42f63a32f80ecd5ee5d6fa3ada
[org.ibex.js.git] / src / org / ibex / js / JSReflection.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.js; 
6
7 import java.lang.reflect.*;
8
9 /** Automatic JS-ification via Reflection (not for use in the core) */
10 public class JSReflection extends JS.Immutable {
11     private static final JS.Method METHOD = new JS.Method();
12
13     public static JS wrap(Object o) throws JSExn {
14         if (o == null) return null;
15         if (o instanceof String) return JSU.S((String)o);
16         if (o instanceof Boolean) return JSU.B(((Boolean)o).booleanValue());
17         if (o instanceof Number) return JSU.N((Number)o);
18         if (o instanceof JS) return (JS)o;
19         if (o instanceof Object[]) {
20             throw new JSExn("Reflection onto Object[] not supported yet");
21         }
22         throw new JSExn("Reflection object tried to return a " + o.getClass().getName());
23     }
24
25     public static class Array extends JS.Immutable {
26         final Object[] arr;
27         public Array(Object[] arr) { this.arr = arr; }
28         // FEATURE: Add a JSCounterEnumeration
29         public Enumeration keys() throws JSExn {
30             return new Enumeration(null) {
31                 private int n = 0;
32                 public boolean _hasNext() { return n < arr.length; }
33                 public JS _next() { return JSU.N(n++); }
34             };
35         }
36         public JS get(JS key) throws JSExn { return wrap(arr[JSU.toInt(key)]); }
37     }
38
39     public Enumeration keys() throws JSExn { throw new JSExn("JSReflection.keys() not supported yet"); }
40
41     public JS get(JS key) throws JSExn {
42         String k = JSU.toString(key);
43         Class c = this.getClass();
44         while(c != null) {
45             try {
46                 Field f = c.getField(k);
47                 if (f != null) return wrap(f.get(this));
48             } catch (NoSuchFieldException nfe) {
49             } catch (IllegalAccessException nfe) {
50             } catch (SecurityException nfe) { }
51             c = c.getSuperclass();
52         }
53
54         try {
55             java.lang.reflect.Method[] methods = this.getClass().getMethods();
56             for(int i=0; i<methods.length; i++) if (methods[i].getName().equals(k)) return METHOD;
57         } catch (SecurityException nfe) { }
58         return null;
59     }
60
61     public void put(JS key, JS val) throws JSExn {
62         throw new JSExn("put() not supported yet");
63     }
64
65     public JS call(JS method, JS[] args) throws JSExn {
66         String k = JSU.toString(method);
67         try {
68             java.lang.reflect.Method[] methods = this.getClass().getMethods();
69             for(int j=0; j<methods.length; j++) {
70                 if (methods[j].getName().equals(k) &&
71                     methods[j].getParameterTypes().length == args.length) {
72                     return wrap(methods[j].invoke(this, (Object[])args));
73                 }
74             }
75         } catch (IllegalAccessException nfe) {
76         } catch (InvocationTargetException it) {
77             Throwable ite = it.getTargetException();
78             if (ite instanceof JSExn) throw ((JSExn)ite);
79             JSU.warn(ite);
80             throw new JSExn("unhandled reflected exception: " + ite.toString());
81         } catch (SecurityException nfe) { }
82         throw new JSExn("called a reflection method with the wrong number of arguments");
83     }
84