/* JRubyInterpreter.java Purpose: Description: History: Sat Feb 10 19:56:11 2007, Created by tomyeh Copyright (C) 2007 Potix Corporation. All Rights Reserved. {{IS_RIGHT This program is distributed under LGPL Version 2.1 in the hope that it will be useful, but WITHOUT ANY WARRANTY. }}IS_RIGHT */ package org.zkoss.zk.scripting.jruby; import java.util.Iterator; import org.jruby.Ruby; import org.jruby.internal.runtime.GlobalVariables; import org.jruby.javasupport.JavaEmbedUtils; import org.jruby.javasupport.JavaObject; import org.jruby.javasupport.JavaUtil; import org.jruby.runtime.GlobalVariable; import org.jruby.runtime.IAccessor; import org.jruby.runtime.builtin.IRubyObject; import org.zkoss.zk.scripting.util.GenericInterpreter; import org.zkoss.zk.ui.Page; /** * JRuby interpreter. * * @author tomyeh */ public class JRubyInterpreter extends GenericInterpreter { private Ruby _runtime; /** Returns the native interpreter, or null if it is not initialized * or destroyed. * From application's standpoint, it never returns null, and the returned * object must be an instance of {@link org.jruby.Ruby} * @since 3.0.2 */ public Object getNativeInterpreter() { return _runtime; } //GenericInterpreter// protected void exec(String script) { _runtime.evalScriptlet(script); } protected boolean contains(String name) { return _runtime.getGlobalVariables().isDefined(GlobalVariable.variableName(name)); } protected Object get(String name) { IRubyObject ro = _runtime.getGlobalVariables().get(GlobalVariable.variableName(name)); return rubyToJava(ro); } protected void set(String name, Object value) { _runtime.getGlobalVariables().define(GlobalVariable.variableName(name), new Variable(value)); } protected void unset(String name) { _runtime.getGlobalVariables().set(GlobalVariable.variableName(name), _runtime.getNil()); } //Interpreter// public void init(Page owner, String zslang) { super.init(owner, zslang); _runtime = Ruby.newInstance(); _runtime.setGlobalVariables(new Variables(_runtime)); } public void destroy() { JavaEmbedUtils.terminate(_runtime); _runtime = null; super.destroy(); } /**TODO: need to dig out a solution from jruby's manual public Class getClass(String clsnm) { } public Function getFunction(String name, Class[] argTypes) { } */ //utilities// private IRubyObject javaToRuby(Object value) { IRubyObject ro = JavaUtil.convertJavaToRuby(_runtime, value); if (ro instanceof JavaObject) return _runtime.getModule("JavaUtilities").callMethod(_runtime.getCurrentContext(), "wrap", ro); return ro; } private Object rubyToJava(IRubyObject value) { return JavaUtil.convertRubyToJava(value, Object.class); } /** The global scope. */ private class Variables extends GlobalVariables { private Variables(Ruby runtime) { super(runtime); //we have to copy variables from the origin one to this GlobalVariables vars = runtime.getGlobalVariables(); for (Iterator it = vars.getNames().iterator(); it.hasNext();) { final String nm = (String) it.next(); set(nm, vars.get(nm)); } } public IRubyObject get(String name) { IRubyObject ro = super.get(name); if (ro == _runtime.getNil()) { if (name.length() > 1 && name.charAt(0) == '$') //just in case name = name.substring(1); Object val = getFromNamespace(name); if (val != UNDEFINED) return javaToRuby(val); } return ro; } } /*ruby variable*/ private class Variable implements IAccessor { private Object _value; public Variable(Object value) { _value = value; } public IRubyObject getValue() { return javaToRuby(_value); } public IRubyObject setValue(IRubyObject value) { _value = rubyToJava(value); return value; } } }