001: /* RhinoInterpreter.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Fri Feb 9 00:23:47 2007, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2007 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zkmax.scripting.rhino;
020:
021: import org.mozilla.javascript.Context;
022: import org.mozilla.javascript.Scriptable;
023: import org.mozilla.javascript.Function;
024: import org.mozilla.javascript.Undefined;
025: import org.mozilla.javascript.ScriptRuntime;
026: import org.mozilla.javascript.ImporterTopLevel;
027:
028: import org.zkoss.zk.ui.Page;
029: import org.zkoss.zk.ui.UiException;
030: import org.zkoss.zk.scripting.util.GenericInterpreter;
031:
032: /**
033: * Rhino-based JavaScript interpreter.
034: *
035: * @author tomyeh
036: */
037: public class RhinoInterpreter extends GenericInterpreter {
038: private Scriptable _global;
039:
040: public RhinoInterpreter() {
041: }
042:
043: /** Returns the top-level scope.
044: */
045: /*package*/Scriptable getGlobalScope() {
046: return _global;
047: }
048:
049: /** Returns the native interpreter, or null if it is not initialized
050: * or destroyed.
051: * From application's standpoint, it never returns null, and the returned
052: * object must be an instance of {@link org.mozilla.javascript.Scriptable}
053: * @since 3.0.2
054: */
055: public Object getNativeInterpreter() {
056: return _global;
057: }
058:
059: //GenericInterpreter//
060: protected void exec(String script) {
061: Context.getCurrentContext().evaluateString(_global, script,
062: "zk", 1, null);
063: }
064:
065: protected boolean contains(String name) {
066: return _global.has(name, _global);
067: }
068:
069: protected Object get(String name) {
070: final Object val = _global.get(name, _global);
071: if (val == Scriptable.NOT_FOUND || val == Undefined.instance
072: || val == null)
073: return null;
074:
075: return Context.getCurrentContext().jsToJava(val,
076: ScriptRuntime.ObjectClass);
077: }
078:
079: protected void set(String name, Object value) {
080: _global.put(name, _global, toJS(value));
081: }
082:
083: private Object toJS(Object value) {
084: return value == null || (value instanceof Number)
085: || (value instanceof String)
086: || (value instanceof Boolean) ? value : Context
087: .toObject(value, _global);
088: }
089:
090: protected void unset(String name) {
091: _global.delete(name);
092: }
093:
094: protected void beforeExec() {
095: Context.enter();
096: }
097:
098: protected void afterExec() {
099: Context.exit();
100: }
101:
102: //Interpreter//
103: public void init(Page owner, String zslang) {
104: super .init(owner, zslang);
105:
106: final Context ctx = Context.enter();
107: try {
108: _global = new GlobalScope(ctx);
109: } finally {
110: Context.exit();
111: }
112: }
113:
114: public void destroy() {
115: _global = null;
116: super .destroy();
117: }
118:
119: /**TODO: feasible but need to read manual/source first
120: public Class getClass(String clsnm) {
121: }
122: */
123: /** Returns the method.
124: * <p>Note: JavaScript identifies a function with the name only.
125: */
126: public org.zkoss.xel.Function getFunction(String name,
127: Class[] argTypes) {
128: Context.enter();
129: try {
130: final Object val = _global.get(name, _global);
131: if (!(val instanceof Function))
132: return null;
133: return new RhinoFunction((Function) val);
134: } finally {
135: Context.exit();
136: }
137: }
138:
139: //supporting class//
140: /** Extends ImporterTopLevel to support ZK namespaces.
141: */
142: private class GlobalScope extends ImporterTopLevel {
143: private GlobalScope(Context ctx) {
144: super (ctx);
145: }
146:
147: /* Not sure the side effect yet, so disable it
148: public boolean has(String name, Scriptable start) {
149: return super.has(name, start) || getFromNamespace(name) != UNDEFINED;
150: }*/
151: public Object get(String name, Scriptable start) {
152: final Object val = super .get(name, start);
153: if (val == Scriptable.NOT_FOUND
154: || val == Undefined.instance) {
155: final Object v = getFromNamespace(name);
156: if (v != UNDEFINED)
157: return toJS(v);
158: }
159: return val;
160: }
161: }
162:
163: private class RhinoFunction implements org.zkoss.xel.Function {
164: private final Function _func;
165:
166: private RhinoFunction(Function func) {
167: if (func == null)
168: throw new IllegalArgumentException("null");
169: _func = func;
170: }
171:
172: //-- Function --//
173: public Class[] getParameterTypes() {
174: return new Class[0];
175: }
176:
177: public Class getReturnType() {
178: return Object.class;
179: }
180:
181: public Object invoke(Object obj, Object[] args)
182: throws Exception {
183: final Context ctx = Context.enter();
184: try {
185: final Scriptable scope = getGlobalScope();
186: return _func.call(ctx, scope, scope, args);
187: } finally {
188: Context.exit();
189: }
190: }
191:
192: public java.lang.reflect.Method toMethod() {
193: return null;
194: }
195: }
196: }
|