001: /* JRubyInterpreter.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Sat Feb 10 19:56:11 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.jruby;
020:
021: import java.util.Iterator;
022:
023: import org.jruby.Ruby;
024: import org.jruby.javasupport.Java;
025: import org.jruby.javasupport.JavaEmbedUtils;
026: import org.jruby.javasupport.JavaObject;
027: import org.jruby.javasupport.JavaUtil;
028: import org.jruby.runtime.IAccessor;
029: import org.jruby.runtime.GlobalVariable;
030: import org.jruby.runtime.Block;
031: import org.jruby.runtime.builtin.IRubyObject;
032: import org.jruby.internal.runtime.GlobalVariables;
033:
034: import org.zkoss.xel.Function;
035: import org.zkoss.zk.ui.Page;
036: import org.zkoss.zk.ui.UiException;
037: import org.zkoss.zk.scripting.util.GenericInterpreter;
038:
039: /**
040: * JRuby interpreter.
041: *
042: * @author tomyeh
043: */
044: public class JRubyInterpreter extends GenericInterpreter {
045: private Ruby _runtime;
046:
047: /** Returns the native interpreter, or null if it is not initialized
048: * or destroyed.
049: * From application's standpoint, it never returns null, and the returned
050: * object must be an instance of {@link org.jruby.Ruby}
051: * @since 3.0.2
052: */
053: public Object getNativeInterpreter() {
054: return _runtime;
055: }
056:
057: //GenericInterpreter//
058: protected void exec(String script) {
059: _runtime.evalScript(script);
060: }
061:
062: protected boolean contains(String name) {
063: return _runtime.getGlobalVariables().isDefined(
064: GlobalVariable.variableName(name));
065: }
066:
067: protected Object get(String name) {
068: IRubyObject ro = _runtime.getGlobalVariables().get(
069: GlobalVariable.variableName(name));
070: return rubyToJava(ro);
071: }
072:
073: protected void set(String name, Object value) {
074: _runtime.getGlobalVariables().define(
075: GlobalVariable.variableName(name), new Variable(value));
076: }
077:
078: protected void unset(String name) {
079: _runtime.getGlobalVariables().set(
080: GlobalVariable.variableName(name), _runtime.getNil());
081: }
082:
083: //Interpreter//
084: public void init(Page owner, String zslang) {
085: super .init(owner, zslang);
086:
087: _runtime = Ruby.getDefaultInstance();
088: _runtime.setGlobalVariables(new Variables(_runtime));
089: }
090:
091: public void destroy() {
092: JavaEmbedUtils.terminate(_runtime);
093: _runtime = null;
094:
095: super .destroy();
096: }
097:
098: /**TODO: need to digg out a solution from jruby's manual
099: public Class getClass(String clsnm) {
100: }
101: public Function getFunction(String name, Class[] argTypes) {
102: }
103: */
104:
105: //utilities//
106: private IRubyObject javaToRuby(Object value) {
107: IRubyObject ro = JavaUtil.convertJavaToRuby(_runtime, value);
108: if (ro instanceof JavaObject)
109: return _runtime.getModule("JavaUtilities").callMethod(
110: _runtime.getCurrentContext(), "wrap", ro);
111: return ro;
112: }
113:
114: private Object rubyToJava(IRubyObject value) {
115: return JavaUtil.convertArgument(Java.ruby_to_java(_runtime
116: .getObject(), value, Block.NULL_BLOCK), Object.class);
117: }
118:
119: /** The global scope. */
120: private class Variables extends GlobalVariables {
121: private Variables(Ruby runtime) {
122: super (runtime);
123:
124: //we have to copy variables from the origin one to this
125: GlobalVariables vars = runtime.getGlobalVariables();
126: for (Iterator it = vars.getNames(); it.hasNext();) {
127: final String nm = (String) it.next();
128: set(nm, vars.get(nm));
129: }
130: }
131:
132: public IRubyObject get(String name) {
133: IRubyObject ro = super .get(name);
134: if (ro == _runtime.getNil()) {
135: if (name.length() > 1 && name.charAt(0) == '$') //just in case
136: name = name.substring(1);
137: Object val = getFromNamespace(name);
138: if (val != UNDEFINED)
139: return javaToRuby(val);
140: }
141: return ro;
142: }
143: }
144:
145: /*ruby variable*/
146: private class Variable implements IAccessor {
147: private Object _value;
148:
149: public Variable(Object value) {
150: _value = value;
151: }
152:
153: public IRubyObject getValue() {
154: return javaToRuby(_value);
155: }
156:
157: public IRubyObject setValue(IRubyObject value) {
158: _value = rubyToJava(value);
159: return value;
160: }
161: }
162: }
|