Java 7 Rhino-based JavaScript ScriptEngine set system property "rhino.opt.level" - java

The java documentation about the JavaScript ScriptEngine implementation says, that it is possible to set the system property "rhino.opt.level" if there is no security manager active. ("When security manager is not used, System property "rhino.opt.level" can be defined in the range [-1, 9]. By default, the value is set to -1 which means optimizer is disabled.", see http://docs.oracle.com/javase/7/docs/technotes/guides/scripting/programmer_guide/#jsengine)
My question now is, how this can be done. I tried setting it as an environment variable and in the code using
System.setProperty("rhino.opt.level", "9");
but it had no effect on the compiled scripts whatsoever. Is there a command line argument that needs to be passed to the jvm or something similar?
Edit: My test code:
String script = IOUtil.readTextFile("test.js", "UTF-8"); // reads the file's content
System.setProperty("rhino.opt.level", "9");
final ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
Compilable compiler = (Compilable) scriptEngine;
CompiledScript cs = compiler.compile(script);
cs.eval();

Related

Run python script using Pyrolite from java

I have a simple python script in my local machine, which returns a string. I want to run this script from java application and get the return value. I'm trying to do this using Pyrolite. I downloaded the jar files and added them to my java class path. But I'm not able to run the script.
I got the below sample code from readme.txt
NameServerProxy ns = NameServerProxy.locateNS(null);
PyroProxy remoteobject = new PyroProxy(ns.lookup("Your.Pyro.Object"));
Object result = remoteobject.call("pythonmethod", 42, "hello", new int[]{1,2,3});
String message = (String)result; // cast to the type that 'pythonmethod' returns
System.out.println("result message="+message);
remoteobject.close();
ns.close();
But this is not working for me. My system configuration is
OS: Windows 8
JDK: jdk1.7.0_51
Python: 2.6
Please help me with this.
This is how I have edited the code:
NameServerProxy ns = NameServerProxy.locateNS(null);
PyroProxy remoteobject = new PyroProxy();
Object result = remoteobject.call("C:\\trail1.py", null);
String message = (String)result; // cast to the type that 'pythonmethod' returns
System.out.println("result message="+message);
remoteobject.close();
ns.close();
I'm not positive that I understand what you're trying to do.
If you carefully read the tutorial, you'll see that you can't use Pyrolite the way you are. It specifies that you must have a python script running as a server, WITH a name server, where you must define some classes (for example Your.Pyro.Object).
Then you'll be able to call those objects you defined in that python script, but not the script itself.
To do what you want to do you'll need to call a function like C's fork(). Then you're able to call an executable, and you don't need Pyrolite.

Using Java Scripting API to create game content

So, I'll be using the Java Scripting API with JavaScript to do all the scripting for the game. Now, I've read over the documentation I can't seem to figure out how I could do a one time run of some of the scripts to get all the 'different types of objects data' to be fed to Java. I'm actually not quite sure how to save all that data to Java or if I should even try saving it to Java....
QUESTION: How can I import a bunch of scripting information at run-time into my application?
You can basically pass data between scripting environment and Java through the scripting API. For example,
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("JavaScript");
engine.eval("greeting='Hello'");
// Returning data from scripting environment to Java.
// The data can also be returned from a function
final String greeting = (String) engine.eval("greeting");
System.out.println(greeting); //prints Hello
//Passing data to scripting environment from Java
engine.put("who", "foo");
final String greetingFoo = (String) engine.eval("greeting + ', ' + who");
System.out.println(greetingFoo); //prints Hello, foo

Does Nashorn return native JavaScript objects?

I'm currently using the javax implementation of Rhino. By default Rhino uses a wrapper to return Java objects. Does Nashorn have similar behaviour or does it return JavaScript objects by default?
Thanks
Looks like it tries its best to return sensible objects. Using this code, then changing the XXX:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("nashorn");
engine.eval("function test() { return XXX; };");
Object result = ((Invocable)engine).invokeFunction("test");
System.out.println(result.getClass().getName());
Yields:
return 'hello world' = java.lang.String
return 1 = java.lang.Integer
return { name: 'Hello' } = jdk.nashorn.api.scripting.ScriptObjectMirror
Looks like that, even though the Java objects can be used within the JS code, it still references Java Objects (although they show up as function objects so there must be a wrapper there), we can't treat them as Javascript objects:
//"import"
var StringTokenizer = java.util.StringTokenizer;
print(typeof StringTokenizer);
var st = new StringTokenizer("this is a test");
print(typeof st);
java.util.StringTokenizer.prototype.name = 'myST';
print(st.name);
And here's the result:
testObj.js:9 TypeError: Cannot set property "name" of undefined
Now Javascript objects will be loaded as "jdk.nashorn.internal.scripts.JO" instances.
*If you want to test the above code more easily, just create an alias for your JDK's jjs (Nashorn Interpreter), e.g., if you create a file called test.js, you can run the program with:
$ jjs test.js
Mac OS = alias jjs=’/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/jjs’
Windows = Define an environment variable called ‘JAVA8_HOME’ and point to your jdk8 folder, then you can invoke jjs by running this command:
> “%JAVA8_HOME%\jre\bin\jjs” test.js

Call javascript(jQuery/Envjs) from java code

I am trying to execute Javascript code from Java. Javascript code uses jquery so I prepend the jquery.js before my code. But it throws following exception,
Exception in thread "main" javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "window" is not defined. (<Unknown source>#1) in <Unknown source> at line number 1
As I run this from the Java code, I understand that it does not have access to the window object so above exception. I found that EnvJs provides the implementation for the required environment so I tried to load that first by putting its content first while generating the script content to eval. But run into following exception,
Exception in thread "main" javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: TypeError: Cannot call property getCurrentContext in object [JavaPackage org.mozilla.javascript.Context]. It is not a function, it is "object". (<Unknown source>#1247) in <Unknown source> at line number 1247
Following is the code snippet,
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
String script = "Envjs code" + "jQuery code" + "my java script"; //code of envjs + jquery from the link provided at the end
engine.eval(script);
Invocable inv = (Invocable) engine;
inv.invokeFunction("myFunc", obj1, obj2);
I do not use any browser features so do not require object's like window. So ideally I do not want to load Envjs. Please let me know how to load jQuery code.
One more question - How to pass Json Object from Java code to Javascript function as parameter?
http://www.envjs.com/dist/env.rhino.1.2.js
http://code.jquery.com/jquery-1.9.0.min.js
It may be easier to do this with Rhino using the instructions from the Envjs Guide ( http://www.envjs.com/doc/guides#running-embed ).
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.tools.shell.Global;
import org.mozilla.javascript.tools.shell.Main;
...
Context cx = ContextFactory.getGlobal().enterContext();
cx.setOptimizationLevel(-1);
cx.setLanguageVersion(Context.VERSION_1_5);
Global global = Main.getGlobal();
global.init(cx);
Main.processSource(cx, "path/to/your/EnvJSfile");
Main.processSource(cx, "path/to/your/JQueryJSfile");
cx.evaluateString(global, "your JavaScript", "JavaScript", 1, null);
don't known about Envjs, but why simulate a browser environment in java?
for the second question:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
Compilable compilable = (Compilable) engine;
Bindings bindings = engine.createBindings();
String script = "function add(op1,op2){return op1+op2} add(a, b)";
CompiledScript jsFunction = compilable.compile(script);
bindings.put("a", 1);bindings.put("b", 2); //put java object into js runtime environment
Object result = jsFunction.eval(bindings);
System.out.println(result);
you can put whatever object into the bindings, a map, a list, or a pojo.

how to use java to get a js file and execute it and then get the result

How can I use java to get a js file located on a web server, then execute the function in the js file and get the result and use the result in java.
Can you guys give me some code snippet? Great thanks.
You can use the scripting engine built into Java:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public static void main(String[] args) throws Exception {
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
Object result = engine.eval("my-java-script-code")
System.out.println("Result returned by Javascript is: " + result);
}
Here is a more elaborate example.
There's three steps to this process:
Fetch the JS file from the server.
Execute some JS function from the file.
Extract the result.
The first step is fairly simple, there are lots of HTTP libraries in Java that will do this - you effectively want to emulate the simple functionality of something like wget or curl. The exact manner in which you do this will vary depending on what format you want the JS file in for the next step, but the process to get hold of the byte stream is straightforward.
The second step will require executing the JS in a Javascript engine. Java itself cannot interpret Javascript, so you'd need to obtain an engine to run it in - Rhino is a common choice for this. Since you'd need to run this outside of Java, you'll likely have to spawn a process for execution in Rhino using ProcessBuilder. Additionally, depending on the format of the Javascript you might need to create your own "wrapper" javascript that functions like a main class in Java and calls the method in question.
Finally you need to get the result out - obviously you don't have direct access to JavaScript objects from your Java program. The easiest way is going to be for the JS program to print the result to standard out (possibly serialising as something like JSON depending on the complexity of the object), which is being streamed directly to your Java app due to the way you launched the Rhino process. This could be another job for your JS wrapper script, if any. Otherwise, if the JS function has observable side effects (creates a file/modifies a database) then you'll be able to query those directly from Java.
Job done.
I hope you realise this question is far too vague to get full answers. Asking the public to design an entire system goes beyond the point where you'll get useful, actionable responses.
There are plenty of examples on the web of how to download a file from a URL.
Suns version of the JDK and JRE includes the Mozilla Rhino scripting engine.
Assuming you have stored the contents of the javascript file in a string called 'script', you can execute scripts as follows
String result = null;
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
try {
jsEngine.eval(script);
result = jsEngine.get("result")
} catch (ScriptException ex) {
ex.printStackTrace();
}
The result will be extracted from the engine and stored in the 'result' variable.
The is a tutorial on scripting in Java that might be useful.

Categories