简体   繁体   中英

How to pass Javascript native types to Nashorn objects from Java?

For security reasons I'd like to pass to JS functions in Nashorn native Java types.

If I create an engine and I run the following:

        NashornScriptEngineFactory nashornScriptEngineFactory = new      NashornScriptEngineFactory();
        ScriptEngine engine = nashornScriptEngineFactory.getScriptEngine();
        engine.eval(script);
        Invocable invocable = (Invocable) engine;
        JSObject objectWork = (JSObject) engine.get("objectWork");
        objectWork.call(null,"eee");

with script being

function objectWork(arg){
   print ("arg is "+ typeof arg);
   print ("arg.getClass()"+ arg.getClass());

   for (var k in arg){
        print(k);
   }
}

The output is

arg is string
arg.getClass()class java.lang.String

I'm not so happy about the 2nd and I don't know if getClass is exposing any method of the java.lang.Class object. Is there a way to pass something that wraps the Java String in a native one extending Nashorn own JSObject?

JS String primitive type values are java.lang.String objects. For example,

jjs> "hello".getClass()
class java.lang.String
jjs> "hello".class
class java.lang.String

ie, there is no separate "JS String" type used in nashorn. Nashorn tries to avoid wrapping Java/JS types as much as possible.

What is the specific issue you're worried about? Reflective access to String via "Class" object? Please note that by default Java reflection is not allowed to scripts if you run under SecurityManager.

$ jjs -J-Djava.security.manager
jjs> "hello".class
class java.lang.String
jjs> "hello".class.getMethods()
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "nashorn.JavaReflection")
jjs>

So, unless you give "nashorn.JavaReflection" RuntimePermission to a script, it won't be able to do any Java reflection from script. So, getting access to Class object of any Java object won't pose any security thread.

A trivial, yet working solution. Just have the engine load a piece of JS code like

function strclone(str){
 return new String(str);
}

and then call it from Java everytime. That will result in a JSObject and in a propert JS string that can be passed to JS functions:

JSObject strclone = (JSObject) engine.get("strclone");
JSObject jsString = strclone.call(null,"some Java string");
someOtherJsMethod.call(null, jsString);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM