9c2383005c364b5fd59fb8ee057806c4c9d69c27
[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             // FIXME: get element type here
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     // FIXME public static class Hash { }
40     // FIXME public Enumeration keys() throws JSExn {  }
41
42     public JS get(JS key) throws JSExn {
43         String k = JSU.toString(key);
44         try {
45             Field f = this.getClass().getField(k);
46             return wrap(f.get(this));
47         } catch (NoSuchFieldException nfe) {
48         } catch (IllegalAccessException nfe) {
49         } catch (SecurityException nfe) { }
50
51         try {
52             java.lang.reflect.Method[] methods = this.getClass().getMethods();
53             for(int i=0; i<methods.length; i++) if (methods[i].getName().equals(k)) return METHOD;
54         } catch (SecurityException nfe) { }
55         return null;
56     }
57
58     public void put(JS key, JS val) throws JSExn {
59         throw new JSExn("put() not supported yet");
60     }
61
62     public JS call(JS method, JS[] args) throws JSExn {
63         String k = JSU.toString(method);
64         try {
65             java.lang.reflect.Method[] methods = this.getClass().getMethods();
66             for(int j=0; j<methods.length; j++) {
67                 if (methods[j].getName().equals(k) &&
68                     methods[j].getParameterTypes().length == args.length) {
69                     return wrap(methods[j].invoke(this, (Object[])args));
70                 }
71             }
72         } catch (IllegalAccessException nfe) {
73         } catch (InvocationTargetException it) {
74             Throwable ite = it.getTargetException();
75             if (ite instanceof JSExn) throw ((JSExn)ite);
76             JSU.warn(ite);
77             throw new JSExn("unhandled reflected exception: " + ite.toString());
78         } catch (SecurityException nfe) { }
79         throw new JSExn("called a reflection method with the wrong number of arguments");
80     }
81