RedBridge: Wiki: Home — Project Kenai
RedBridge Wiki
This project is merging into JRuby Embed. Please see JRuby Embed Wiki.
RedBridge is an implementation of JSR223 Scripting for the Java Platform on top of JRuby Embed API. Inheriting the features of JRuby Embed API, RedBridge enables to share various types of variables and constants between Java and Ruby. In addition, users can choose a Ruby runtime and other resources' instance type from threadsafe, singlethread, and singleton.
Contents [hide]
- 1 RedBridge Wiki
- 2 Download
- 3 Configurations
- 3.1 Class Path
- 3.2 Context Instance Model
- 3.3 Local Variable Behavior
- 3.4 CompileMode
- 3.5 Line Number
- 4 ScriptEngineManager for JRuby
- 5 Code Examples
- 5.1 Simple Eval
- 5.2 Simple Eval 2
- 5.3 Eval with Bindings
- 5.4 Eval with Bindings 2
- 5.5 Eval with ScriptContext
- 5.6 Eval with ScriptContext 2
- 5.7 Parse Once, Eval Many Times
- 5.8 Java Interface Implementation
- 5.9 Java Interface Implementation 2
- 5.10 Method Invocation: invokeFunction
- 5.11 Method Invocation2: invokeMethod
- 5.12 Compile(not just parsing, real compilation) Mode
- 6 References
Download
RedBridge version is 0.0.1.1 is available to download at:
http://kenai.com/projects/redbridge/downloads
RedBridge needs patched JRuby and JRuby Embed API, both of which are at http://kenai.com/projects/jruby-embed/downloads.
Configurations
You can configure RedBridge(JRuby engine) using System properties. Currently, class paths, a context instance model, and local variables' behavior can be configured.
Class Path
Propety Name: org.jruby.embed.class.path (or java.class.path)
Either org.jruby.embed.class.path or java.class.path property names is used to configure class path to load jar archive and/or ruby scripts. RedBridge sees org.jruby.embed.class.path first. When no path is tied to the name, org.jruby.embed.class.path, RedBridge sees java.class.path next. The format of the paths is the same of Java's class path syntax, so :(colon) separated path string on Unix and OS X or ;(semi-colon) separated one on Windows Be sure to set classpaths before you instantiate (JRuby)ScriptEngineManager.
Example:
1.String classPath ="/Users/yoko/Tools/jruby-1.3.1/lib/ruby/1.8";2.System.setProperty("org.jruby.embed.class.path", classPath);3.ScriptEngineManager manager =newScriptEngineManager();4.// for OS X users5.//JRubyScriptEngineManager manager = new JRubyScriptEngineManager();6.ScriptEngine engine = manager.getEngineByName("jruby");
Context Instance Model
Property Name: org.jruby.embed.localcontext.scope
Value: theadsafe (default), singlethread, or singletonA context of RedBridge holds context specific values such as name-value pairs for sharing variables between Java and Ruby, Ruby runtime, defautl I/O streams, and a few more. These context specific values are saved in one of three types, threadsafe, singlethread, and singleton. Like class path setting, be sure to set the model before you instantiate (JRuby)ScriptEngineManager.
- ThreadSafe
Default. Script's parsings and evaluations should be safely performed on a multi-threaded environment such as servlet container. A supposed usage is that ScriptEngine is instantiateted in servlet's init() method and evaluates scripts in servlet's service() method.
Example:1.System.setProperty("org.jruby.embed.localcontext.scope","threadsafe");2.ScriptEngineManager manager =newScriptEngineManager();3.// for OS X users4.//JRubyScriptEngineManager manager = new JRubyScriptEngineManager();5.ScriptEngine engine = manager.getEngineByName("jruby");
- SingleThread
This model pretends as if there is only one thread in the world, and does not mind race condition at all. Users are resposnsible to thread safety. If you want to instantiate ScriptEngine in servlet's service() method, this model would be the best suited one.
Example:1.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");2.ScriptEngineManager manager =newScriptEngineManager();3.// for OS X users4.//JRubyScriptEngineManager manager = new JRubyScriptEngineManager();5.ScriptEngine engine = manager.getEngineByName("jruby");
- Singleton
This model uses a well known Singleton pattern, and the only one instance of a local context will exist on JVM.
Example:1.System.setProperty("org.jruby.embed.localcontext.scope","singleton");2.ScriptEngineManager manager =newScriptEngineManager();3.// for OS X users4.//JRubyScriptEngineManager manager = new JRubyScriptEngineManager();5.ScriptEngine engine = manager.getEngineByName("jruby");
Local Variable Behavior
Property Name: org.jruby.embed.localvariable.behavior
Value: transient (default), persistent, or globalRedBrdige enables to share Ruby's local, instance, global variables, and constants. To share these variables between Ruby and Java, RedBridge offers three types of local variable behaviors, transient, persistent, and global.
- Transient Local Variable Behavior
Default. Variables' scope is faithful to Ruby semantics, so local variable does not survive over the multiple evaluations. After the each evaluation, local variable will vanish. However, instance and global variables, and constants survive unless those are removed explicitly. If you use global variables, the variables can be referred literally globally in Ruby runtime and exist as long as the runtime is alive.
Example:1.System.setProperty("org.jruby.embed.localvariable.behavior","transient");2.ScriptEngineManager manager =newScriptEngineManager();3.// for OS X users4.//JRubyScriptEngineManager manager = new JRubyScriptEngineManager();5.ScriptEngine engine = manager.getEngineByName("jruby");
- Persistent Local Variable Behavior
When this type is chosen, RedBridge keeps sharing all local variables' over multiple evaluations. This might not be a semantically correct usage, but is useful in some cases especially for users who have BSF background.
Example:1.System.setProperty("org.jruby.embed.localvariable.behavior","persistent");2.ScriptEngineManager manager =newScriptEngineManager();3.// for OS X users4.//JRubyScriptEngineManager manager = new JRubyScriptEngineManager();5.ScriptEngine engine = manager.getEngineByName("jruby");
- Global Local Variable Behavior
This behavior might be convenient to users who have used JSR 223 reference implementation released at scripging.dev.java.net and don't want change any code. With names like Ruby's local variable name, variables are mapped to Ruby's global variables.Only global variables can be shared between Ruby and Java, when this behavior is chosen.
Example:1.System.setProperty("org.jruby.embed.localvariable.behavior","global");2.ScriptEngineManager manager =newScriptEngineManager();3.// for OS X users4.//JRubyScriptEngineManager manager = new JRubyScriptEngineManager();5.ScriptEngine engine = manager.getEngineByName("jruby");
CompileMode
Property Name: org.jruby.embed.compilemode
Value: off (default), jit, or forceExperimental feature. JRuby has two options to compile Ruby scripts. This configuration provides users a way fo setting a compile mode. When jit or force is specified, only a global variable can be shared between Ruby and Java.
Example:
1.System.setProperty("org.jruby.embed.compilemode","jit");2.ScriptEngineManager manager =newScriptEngineManager();3.// for OS X users4.//JRubyScriptEngineManager manager = new JRubyScriptEngineManager();5.ScriptEngine engine = manager.getEngineByName("jruby");
Line Number
Attribute Name: org.jruby.embed.linenumber
Value: 1, 2, 3,,,, (integer)When you want to specify a line number to display for parse errors and backtraces, use this attribute.
Example:
01.importjavax.script.ScriptContext;02.importjavax.script.ScriptEngine;03.importjavax.script.ScriptException;04.importorg.jruby.embed.jsr223.JRubyScriptEngineManager;05.06.publicclassLineNumberSample {07.privatefinalString script =08."puts \"Hello World.\"\n"+09."puts \"Error is here.";10.11.privateLineNumberSample()throwsScriptException {12.JRubyScriptEngineManager manager =newJRubyScriptEngineManager();13.ScriptEngine engine = manager.getEngineByName("jruby");14.try{15.engine.eval(script);// Since no line number is given, 0 is applied to.16.}catch(Exception e) {17.;18.}19.try{20.engine.getContext().setAttribute("org.jruby.embed.linenumber",1, ScriptContext.ENGINE_SCOPE);21.engine.eval(script);22.}catch(Exception e) {23.;24.}25.try{26.engine.getContext().setAttribute("org.jruby.embed.linenumber",2, ScriptContext.ENGINE_SCOPE);27.engine.eval(script);28.}catch(Exception e) {29.;30.}31.}32.33.publicstaticvoidmain(String[] args)34.throwsScriptException {35.newLineNumberSample();36.}37.}
Outpus:
ScriptEngineManager for JRuby
RedBridge has a JRubyScriptEngineManager class defined, which is used as a substitue of javax.script.ScriptEngineManager. This class is mainly for OS X users. OS X users have had a problem when they use JRuby engine on JDK 1.5 and have JDK 1.6 in their System. After Java update 4 has been installed, JRuby engine can't be instantiated in a JSR 223 way even on JDK 1.6. This class fixes this kind of issue.
If no classloader is set in the argument of JRubyScriptEngineManager constructor, JRubyScriptEngineManager uses system classloader to find jar archives of JSR 223 engines. You can set an appropriate classloader to the constructor. The example below uses Thread.currentThread().getContextClassLoader().
Example:
1.JRubyScriptEngineManager manager =newJRubyScriptEngineManager(Thread.currentThread().getContextClassLoader());2.ScriptEngine engine = manager.getEngineByName("jruby");
Code Examples
Simple Eval
01.packageredbridge;02.03.importjavax.script.ScriptEngine;04.importjavax.script.ScriptEngineManager;05.importjavax.script.ScriptException;06.07.publicclassEvalStringSample {08.09.privateEvalStringSample()throwsScriptException {10.System.out.println("["+ getClass().getName() +"]");11.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");12.System.setProperty("org.jruby.embed.localvariable.behavior","persistent");13.ScriptEngineManager manager =newScriptEngineManager();14.ScriptEngine engine = manager.getEngineByName("jruby");15.engine.eval("p=9.0");16.engine.eval("q = Math.sqrt p");17.engine.eval("puts \"square root of #{p} is #{q}\"");18.System.out.println("q = "+ engine.get("q"));19.}20.21.publicstaticvoidmain(String[] args)throwsScriptException {22.newEvalStringSample();23.}24.}
Output
Local variables survive over multiple eval() invocations. Variables and constants defined only in Ruby scripts are available to use in Java after scripts are evaluated.
Simple Eval 2
01.packageredbridge;02.03.importjava.io.FileNotFoundException;04.importjava.io.FileReader;05.importjava.io.Reader;06.importjavax.script.ScriptEngine;07.importjavax.script.ScriptEngineManager;08.importjavax.script.ScriptException;09.10.publicclassEvalReaderSample {11.privatefinalstaticString basedir ="/Users/yoko/NetBeansProjects/Birch";12.13.privateEvalReaderSample()throwsScriptException, FileNotFoundException {14.System.out.println("["+ getClass().getName() +"]");15.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");16.ScriptEngineManager manager =newScriptEngineManager();17.ScriptEngine engine = manager.getEngineByName("jruby");18.String filename = basedir +"/src/ruby/calendar.rb";19.Reader reader =newFileReader(filename);20.Object result = engine.eval(reader);21.System.out.println("Next year is "+ result +".");22.}23.24.publicstaticvoidmain(String[] args)throwsScriptException, FileNotFoundException {25.newEvalReaderSample();26.}27.}Output01.# calendar.rb [Birch]02.03.require'date'04.05.classCalendar06.definitialize07.@today= DateTime.now08.end09.10.defnext_year11.@today.year +112.end13.end14.c = Calendar.new15.c.next_year
Eval with Bindings
A constant, PI, is injected Ruby by Java.
Output01.packageredbridge;02.03.importjava.io.FileNotFoundException;04.importjavax.script.Bindings;05.importjavax.script.ScriptContext;06.importjavax.script.ScriptEngine;07.importjavax.script.ScriptEngineManager;08.importjavax.script.ScriptException;09.importjavax.script.SimpleBindings;10.11.publicclassEvalStringBindingsSample {12.13.privateEvalStringBindingsSample()throwsScriptException, FileNotFoundException {14.System.out.println("["+ getClass().getName() +"]");15.ScriptEngineManager manager =newScriptEngineManager();16.ScriptEngine engine = manager.getEngineByName("jruby");17.String script =18."def get_perimeter(x, y)\n"+19."x + 2.0 * y + PI / 2.0 * x\n"+20."end\n"+21."get_perimeter(1.5, 1.5)";22.Bindings bindings =newSimpleBindings();23.bindings.put("PI",3.1415);24.Double result = (Double) engine.eval(script, bindings);25.System.out.println(result.toString());26.}27.28.publicstaticvoidmain(String[] args)throwsScriptException, FileNotFoundException {29.newEvalStringBindingsSample();30.}31.}
Eval with Bindings 2
Tow instance variables, @month and @day, are injected Ruby by Java.
01.packageredbridge;02.03.importjava.io.FileNotFoundException;04.importjava.io.FileReader;05.importjava.io.Reader;06.importjavax.script.Bindings;07.importjavax.script.ScriptContext;08.importjavax.script.ScriptEngine;09.importjavax.script.ScriptEngineManager;10.importjavax.script.ScriptException;11.importjavax.script.SimpleBindings;12.13.publicclassEvalReaderBindingsSample {14.privatefinalstaticString basedir ="/Users/yoko/NetBeansProjects/Birch";15.16.privateEvalReaderBindingsSample()throwsScriptException, FileNotFoundException {17.System.out.println("["+ getClass().getName() +"]");18.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");19.ScriptEngineManager manager =newScriptEngineManager();20.ScriptEngine engine = manager.getEngineByName("jruby");21.String filename = basedir +"/src/ruby/count_down.rb";22.Reader reader =newFileReader(filename);23.Bindings bindings =newSimpleBindings();24.bindings.put("@month",1);25.bindings.put("@day",1);26.engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);27.String result = (String) engine.eval(reader, bindings);28.System.out.println(result.toString());29.}30.31.publicstaticvoidmain(String[] args)throwsScriptException, FileNotFoundException {32.newEvalReaderBindingsSample();33.}34.}Output01.# count_down.rb [Birch]02.03.require'date'04.05.defcount_down_birthday06.now = DateTime.now07.year = now.year08.days = DateTime.new(year,@month,@day).yday - now.yday09.ifdays <010.this_year = DateTime.new(year,12,31).yday - now.yday11.next_year = DateTime.new(year +1,@month,@day).yday12.days = this_year + next_year13.end14.return"Happy Birthday!"ifdays ==015.return"You have #{days} day(s) to your next birthday!"16.end17.count_down_birthday
Eval with ScriptContext
Output01.packageredbridge;02.03.importjava.util.List;04.importjavax.script.ScriptContext;05.importjavax.script.ScriptEngine;06.importjavax.script.ScriptEngineManager;07.importjavax.script.ScriptException;08.importjavax.script.SimpleScriptContext;09.10.publicclassEvalStringScriptContextSample {11.12.privateEvalStringScriptContextSample()throwsScriptException {13.System.out.println("["+ getClass().getName() +"]");14.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");15.ScriptEngineManager manager =newScriptEngineManager();16.ScriptEngine engine = manager.getEngineByName("jruby");17.String script =18."def norman_window(x, y)\n"+19."return get_area(x, y), get_perimeter(x, y)\n"+20."end\n"+21."def get_area(x, y)\n"+22."x * y + Math::PI / 8.0 * x ** 2.0\n"+23."end\n"+24."def get_perimeter(x, y)\n"+25."x + 2.0 * y + Math::PI / 2.0 * x\n"+26."end\n"+27."norman_window width, height";28.ScriptContext context =newSimpleScriptContext();29.context.setAttribute("width",1, ScriptContext.ENGINE_SCOPE);30.context.setAttribute("height",3, ScriptContext.ENGINE_SCOPE);31.List<Double> result = (List<Double>) engine.eval(script, context);32.for(inti=0; i<result.size(); i++) {33.System.out.println(result.get(i));34.}35.}36.37.publicstaticvoidmain(String[] args)throwsScriptException {38.newEvalStringScriptContextSample();39.}40.}
Eval with ScriptContext 2
01.packageredbridge;02.03.importjava.io.FileNotFoundException;04.importjava.io.FileReader;05.importjava.io.Reader;06.importjava.util.List;07.importjavax.script.ScriptContext;08.importjavax.script.ScriptEngine;09.importjavax.script.ScriptEngineManager;10.importjavax.script.ScriptException;11.importjavax.script.SimpleScriptContext;12.13.publicclassEvalReaderScriptContextSample {14.privatefinalstaticString basedir ="/Users/yoko/NetBeansProjects/Birch";15.16.privateEvalReaderScriptContextSample()throwsScriptException, FileNotFoundException {17.System.out.println("["+ getClass().getName() +"]");18.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");19.ScriptEngineManager manager =newScriptEngineManager();20.ScriptEngine engine = manager.getEngineByName("jruby");21.String filename = basedir +"/src/ruby/norman_window_dimensions2.rb";22.Reader reader =newFileReader(filename);23.ScriptContext context =newSimpleScriptContext();24.context.setAttribute("@x",4.0, ScriptContext.ENGINE_SCOPE);25.context.setAttribute("@y",1.0, ScriptContext.ENGINE_SCOPE);26.List<Double> result = (List<Double>) engine.eval(reader, context);27.for(inti=0; i<result.size(); i++) {28.System.out.println(result.get(i));29.}30.}31.32.publicstaticvoidmain(String[] args)throwsScriptException, FileNotFoundException {33.newEvalReaderScriptContextSample();34.}35.}Output01.#norman_window_dimensions2.rb [Birch]02.03.defnorman_window04.returnget_area, get_perimeter05.end06.07.defget_area08.@x*@y+ Math::PI/8.0*@x**2.009.end10.11.defget_perimeter12.@x+2.0*@y+ Math::PI/2.0*@x13.end14.15.norman_window
Parse Once, Eval Many Times
01.packageredbridge;02.03.importjavax.script.Compilable;04.importjavax.script.CompiledScript;05.importjavax.script.ScriptEngine;06.importjavax.script.ScriptEngineManager;07.importjavax.script.ScriptException;08.09.publicclassCompileStringSample {10.11.privateCompileStringSample()throwsScriptException {12.System.out.println("["+ getClass().getName() +"]");13.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");14.ScriptEngineManager manager =newScriptEngineManager();15.ScriptEngine engine = manager.getEngineByName("jruby");16.String script =17."def norman_window(x, y)\n"+18."puts \"Dimensions of a #{x} x #{y} Norman window are\"\n"+19."puts \"area: #{get_area(x, y)}\"\n"+20."puts \"perimeter: #{get_perimeter(x, y)}\"\n"+21."end\n"+22."def get_area(x, y)\n"+23."x * y + Math::PI / 8.0 * x ** 2.0\n"+24."end\n"+25."def get_perimeter(x, y)\n"+26."x + 2.0 * y + Math::PI / 2.0 * x\n"+27."end\n"+28."norman_window width, height";29.engine.put("width",2);30.engine.put("height",1);31.CompiledScript cs = ((Compilable)engine).compile(script);32.cs.eval();33.engine.put("width",1);34.engine.put("height",2);35.cs.eval();36.engine.put("width",2);37.engine.put("height",2);38.cs.eval();39.}40.41.publicstaticvoidmain(String[] args)throwsScriptException {42.newCompileStringSample();43.}44.}
Output
After the parsing, setting different values to the "width" and "height" local variables, this program repeats eval three times in total. This feature would work well with Java Servlet. What if a Servlet parses Ruby scripts once in its init() method and just execute them in every HTTP request? Probably, we can expect performance improvement.
In future release, I want to add a compile-once-execute-many-times feature.
Java Interface Implementation
Java Interface
1.packageredbridge;2.3.publicinterfaceSphere {4.doublevolume(doubleradius);5.doublesurface_area(doubleradius);6.}
Ruby Implementation
1.# sphere.rb [Birch]2.defvolume(r)3.4.0/3.0* Math::PI* r **3.04.end5.6.defsurface_area(r)7.4.0* Math::PI* r **2.08.end
Usage
01.packageredbridge;02.03.importjava.io.FileNotFoundException;04.importjava.io.FileReader;05.importjava.io.Reader;06.importjavax.script.Invocable;07.importjavax.script.ScriptEngine;08.importjavax.script.ScriptEngineManager;09.importjavax.script.ScriptException;10.11.publicclassGetInterfaceSample {12.privatefinalstaticString basedir ="/Users/yoko/NetBeansProjects/Birch";13.14.privateGetInterfaceSample()throwsScriptException, FileNotFoundException {15.System.out.println("["+ getClass().getName() +"]");16.ScriptEngineManager manager =newScriptEngineManager();17.ScriptEngine engine = manager.getEngineByName("jruby");18.String filename = basedir +"/src/ruby/sphere.rb";19.Reader reader =newFileReader(filename);20.engine.eval(reader);21.Sphere sphere = ((Invocable)engine).getInterface(Sphere.class);22.doubleradius =3.0;23.System.out.println("Volume of a "+ radius +" radius sphere is "+ sphere.volume(radius));24.System.out.println("Surface area of a "+ radius +" radius sphere is "+ sphere.surface_area(radius));25.radius =4;26.System.out.println("Volume of a "+ radius +" radius sphere is "+ sphere.volume(radius));27.System.out.println("Surface area of a "+ radius +" radius sphere is "+ sphere.surface_area(radius));28.}29.30.publicstaticvoidmain(String[] args)throwsScriptException, FileNotFoundException {31.newGetInterfaceSample();32.}33.}
Output
Java Interface Implementation 2
Java Interface
1.packageredbridge;2.3.publicinterfacePositionFunction {4.String velocity(doublet);5.String position(doublet);6.}
Ruby Implementation
01.# position_function.rb [Birch]02.03.classPositionFunction04.include Java::redbridge.PositionFunction05.attr:v0,:s006.definitialize(v0, s0, system)07.@v0= v008.@s0= s009.if"english"== system.downcase10.@g= -32.011.@unit_v="ft./sec"12.@unit_s="ft."13.end14.if"metric"== system.downcase15.@g= -9.816.@unit_v="m/sec"17.@unit_s="m"18.end19.end20.21.defposition(t)22."#{1.0 / 2.0 * @g * t ** 2.0 + @v0 * t + @s0} #{@unit_s}"23.end24.25.defvelocity(t)26."#{@g * t + @v0} #{@unit_v}"27.end28.end29.PositionFunction.new(initial_velocity, initial_height, system)
Usage
01.packageredbridge;02.03.importjava.io.FileNotFoundException;04.importjava.io.FileReader;05.importjava.io.Reader;06.importjavax.script.Bindings;07.importjavax.script.Invocable;08.importjavax.script.ScriptEngine;09.importjavax.script.ScriptEngineManager;10.importjavax.script.ScriptException;11.12.publicclassGetInterfaceWithReceiverSample {13.privatefinalstaticString basedir ="/Users/yoko/NetBeansProjects/Birch";14.15.privateGetInterfaceWithReceiverSample()throwsScriptException, FileNotFoundException {16.System.out.println("["+ getClass().getName() +"]");17.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");18.ScriptEngineManager manager =newScriptEngineManager();19.ScriptEngine engine = manager.getEngineByName("jruby");20.String filename = basedir +"/src/ruby/position_function.rb";21.Reader reader =newFileReader(filename);22.Bindings bindings = engine.createBindings();23.bindings.put("initial_velocity",30.0);24.bindings.put("initial_height",30.0);25.bindings.put("system","metric");26.Object receiver = engine.eval(reader, bindings);27.PositionFunction pf = ((Invocable)engine).getInterface(receiver, PositionFunction.class);28.doublet =3.0;29.System.out.println("Height after "+ t +" sec is "+ pf.position(t));30.t =1.0;31.System.out.println("Velocity after "+ t +" sec is "+ pf.velocity(t));32.33.reader =newFileReader(filename);34.bindings = engine.createBindings();35.bindings.put("initial_velocity",30.0);36.bindings.put("initial_height",30.0);37.bindings.put("system","english");38.receiver = engine.eval(reader, bindings);39.pf = ((Invocable)engine).getInterface(receiver, PositionFunction.class);40.t =2.0;41.System.out.println("Height after "+ t +" sec is "+ pf.position(t));42.System.out.println("Velocity after "+ t +" sec is "+ pf.velocity(t));43.}44.45.publicstaticvoidmain(String[] args)throwsScriptException, FileNotFoundException {46.newGetInterfaceWithReceiverSample();47.}48.}
Output
Method Invocation: invokeFunction
Ruby
01.# count_down.rb [Birch]02.03.require'date'04.05.defcount_down_birthday06.now = DateTime.now07.year = now.year08.days = DateTime.new(year,@month,@day).yday - now.yday09.ifdays <010.this_year = DateTime.new(year,12,31).yday - now.yday11.next_year = DateTime.new(year +1,@month,@day).yday12.days = this_year + next_year13.end14.return"Happy Birthday!"ifdays ==015.return"You have #{days} day(s) to your next birthday!"16.end17.count_down_birthdayOutput01.packageredbridge;02.03.importjava.io.FileNotFoundException;04.importjava.io.FileReader;05.importjava.io.Reader;06.importjavax.script.Bindings;07.importjavax.script.Invocable;08.importjavax.script.ScriptContext;09.importjavax.script.ScriptEngine;10.importjavax.script.ScriptEngineManager;11.importjavax.script.ScriptException;12.importjavax.script.SimpleBindings;13.14.publicclassInvokeFunctionSample {15.privatefinalstaticString basedir ="/Users/yoko/NetBeansProjects/Birch";16.17.privateInvokeFunctionSample()throwsScriptException, FileNotFoundException, NoSuchMethodException {18.System.out.println("["+ getClass().getName() +"]");19.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");20.ScriptEngineManager manager =newScriptEngineManager();21.ScriptEngine engine = manager.getEngineByName("jruby");22.String filename = basedir +"/src/ruby/count_down.rb";23.Reader reader =newFileReader(filename);24.Bindings bindings =newSimpleBindings();25.bindings.put("@month",6);26.bindings.put("@day",6);27.Object result = engine.eval(reader, bindings);28.System.out.println(result.toString());29.30.String method ="count_down_birthday";31.bindings.put("@month",12);32.bindings.put("@day",31);33.engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);34.Object[] args =null;35.result = ((Invocable)engine).invokeFunction(method, args);36.System.out.println(result.toString());37.bindings.put("@month",6);38.bindings.put("@day",3);39.engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);40.result = ((Invocable)engine).invokeFunction(method, args);41.System.out.println(result.toString());42.}43.44.publicstaticvoidmain(String[] args)throwsScriptException, FileNotFoundException, NoSuchMethodException {45.newInvokeFunctionSample();46.}47.}
Method Invocation2: invokeMethod
Ruby
01.# tree_with_localvars.rb [Birch]02.03.classTree04.attr_reader:name,:shape,:foliage,:flower05.definitialize(name, shape, foliage, flower)06.@name= name07.@shape= shape08.@foliage= foliage09.@flower= flower10.end11.defto_s12."#{name.capitalize} is a #{shape} shaped, #{foliage} tree, and blooms #{flower.color} flowers in #{flower.bloomtime}."13.end14.defupdate(color, bloomtime)15.@flower.color = color16.@flower.bloomtime = bloomtime17.end18.end19.20.classFlower21.attr_accessor:color,:bloomtime22.definitialize(color, bloomtime)23.@color= color24.@bloomtime= bloomtime25.end26.end27.28.Tree.new(name, shape, foliage, Flower.new(color, bloomtime))
Output01.packageredbridge;02.03.importjava.io.FileNotFoundException;04.importjava.io.FileReader;05.importjava.io.Reader;06.importjavax.script.Bindings;07.importjavax.script.Invocable;08.importjavax.script.ScriptContext;09.importjavax.script.ScriptEngine;10.importjavax.script.ScriptEngineManager;11.importjavax.script.ScriptException;12.importjavax.script.SimpleBindings;13.14.publicclassInvokeMethodSample {15.privatefinalstaticString basedir ="/Users/yoko/NetBeansProjects/Birch";16.17.privateInvokeMethodSample()throwsScriptException, FileNotFoundException, NoSuchMethodException {18.System.out.println("["+ getClass().getName() +"]");19.System.setProperty("org.jruby.embed.localcontext.scope","singlethread");20.ScriptEngineManager manager =newScriptEngineManager();21.ScriptEngine engine = manager.getEngineByName("jruby");22.String filename = basedir +"/src/ruby/tree_with_localvars.rb";23.Reader reader =newFileReader(filename);24.Bindings bindings =newSimpleBindings();25.bindings.put("name","cedar");26.bindings.put("shape","pyramidal");27.bindings.put("foliage","evergreen");28.bindings.put("color","nondescript");29.bindings.put("bloomtime","April - May");30.Object receiver = engine.eval(reader, bindings);31.Object[] args =null;32.String result = (String) ((Invocable)engine).invokeMethod(receiver,"to_s", args);33.System.out.println(result);34.35.args =newObject[]{"pink","March - April"};36.((Invocable)engine).invokeMethod(receiver,"update", args);37.bindings.put("@name","cherry blossom");38.bindings.put("@shape","round");39.bindings.put("@foliage","deciduous");40.engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);41.args =null;42.result = (String) ((Invocable)engine).invokeMethod(receiver,"to_s", args);43.System.out.println(result);44.}45.46.publicstaticvoidmain(String[] args)throwsScriptException, FileNotFoundException, NoSuchMethodException {47.newInvokeMethodSample();48.}49.}
Compile(not just parsing, real compilation) Mode
Output001.packageredbridge;002.003.importjava.io.FileNotFoundException;004.importjava.io.FileReader;005.importjava.io.Reader;006.importjava.util.Calendar;007.importjavax.script.Compilable;008.importjavax.script.CompiledScript;009.importjavax.script.ScriptEngine;010.importjavax.script.ScriptEngineManager;011.importjavax.script.ScriptException;012.013.publicclassCompiledModeSample {014.privatefinalstaticString jrubyhome ="/Users/yoko/Tools/jruby-1.3.0";015.privateintiteration =50;016.017.privateCompiledModeSample()throwsScriptException, FileNotFoundException {018.System.out.println("["+ getClass().getName() +"]");019.System.setProperty("org.jruby.embed.localcontext.scope","singleton");020.setLoadPaths();021.String filename = jrubyhome +"/test/testEnumerator.rb";022.Reader reader =newFileReader(filename);023.runWithCompileModeOff(reader);024.runWithCompileModeForce(reader);025.runWithCompileModeJit(reader);026.027.runMultipleTimesWithModeOff(reader);028.runMultipleTimesWithModeForce(reader);029.runMultipleTimesWithModeJit(reader);030.}031.032.privatevoidsetLoadPaths() {033.String[] paths = {034.jrubyhome +"/lib/ruby/1.8",035.jrubyhome +"/lib/ruby/site_ruby/1.8",036.jrubyhome037.};038.String separator = System.getProperty("path.separator");039.String classPath ="";040.for(inti=0; i < paths.length; i++) {041.classPath = classPath + paths[i] + separator;042.}043.classPath = classPath.substring(0, classPath.length()-1);044.System.setProperty("org.jruby.embed.class.path", classPath);045.}046.047.privatevoidrunWithCompileModeOff(Reader reader)throwsScriptException {048.ScriptEngineManager manager =newScriptEngineManager();049.ScriptEngine engine = manager.getEngineByName("jruby");050.engine.eval(reader);051.longstart = Calendar.getInstance().getTimeInMillis();052.engine.eval(reader);053.longend = Calendar.getInstance().getTimeInMillis();054.System.out.println("Mode OFF: "+ (end - start));055.}056.057.privatevoidrunMultipleTimesWithModeOff(Reader reader)throwsScriptException {058.ScriptEngineManager manager =newScriptEngineManager();059.ScriptEngine engine = manager.getEngineByName("jruby");060.engine.eval(reader);061.CompiledScript cs = ((Compilable)engine).compile(reader);062.longstart = Calendar.getInstance().getTimeInMillis();063.for(inti=0; i<iteration; i++) {064.cs.eval();065.}066.longend = Calendar.getInstance().getTimeInMillis();067.System.out.println("Mode OFF ("+ iteration +" times): "+ (end - start));068.}069.070.privatevoidrunWithCompileModeJit(Reader reader)throwsScriptException {071.System.setProperty("org.jruby.embed.compilemode","jit");072.ScriptEngineManager manager =newScriptEngineManager();073.ScriptEngine engine = manager.getEngineByName("jruby");074.engine.eval(reader);075.longstart = Calendar.getInstance().getTimeInMillis();076.engine.eval(reader);077.longend = Calendar.getInstance().getTimeInMillis();078.System.out.println("Mode JIT: "+ (end - start));079.}080.081.privatevoidrunMultipleTimesWithModeJit(Reader reader)throwsScriptException {082.System.setProperty("org.jruby.embed.compilemode","jit");083.ScriptEngineManager manager =newScriptEngineManager();084.ScriptEngine engine = manager.getEngineByName("jruby");085.engine.eval(reader);086.CompiledScript cs = ((Compilable)engine).compile(reader);087.longstart = Calendar.getInstance().getTimeInMillis();088.for(inti=0; i<iteration; i++) {089.cs.eval();090.}091.longend = Calendar.getInstance().getTimeInMillis();092.System.out.println("Mode JIT ("+ iteration +" times): "+ (end - start));093.}094.095.privatevoidrunWithCompileModeForce(Reader reader)throwsScriptException {096.System.setProperty("org.jruby.embed.compilemode","force");097.ScriptEngineManager manager =newScriptEngineManager();098.ScriptEngine engine = manager.getEngineByName("jruby");099.engine.eval(reader);100.longstart = Calendar.getInstance().getTimeInMillis();101.engine.eval(reader);102.longend = Calendar.getInstance().getTimeInMillis();103.System.out.println("Mode FORCE: "+ (end - start));104.}105.106.privatevoidrunMultipleTimesWithModeForce(Reader reader)throwsScriptException {107.System.setProperty("org.jruby.embed.compilemode","force");108.ScriptEngineManager manager =newScriptEngineManager();109.ScriptEngine engine = manager.getEngineByName("jruby");110.engine.eval(reader);111.CompiledScript cs = ((Compilable)engine).compile(reader);112.longstart = Calendar.getInstance().getTimeInMillis();113.for(inti=0; i<iteration; i++) {114.cs.eval();115.}116.longend = Calendar.getInstance().getTimeInMillis();117.System.out.println("Mode FORCE ("+ iteration +" times): "+ (end - start));118.}119.120.publicstaticvoidmain(String[] args)throwsScriptException, FileNotFoundException {121.newCompiledModeSample();122.}123.}
References
浙公网安备 33010602011771号