I have to execute a given String as JavaScript code, e.g. eval('Foo.setMessage("Hello!")')
, from within a class called Engine
. Here, setMessage()
is a public static method of the Foo
class. Because I want to access some properties of the Engine
object from within the setMessage()
method, how can I obtain a reference to the Engine
object?
I do know how to get the caller class name using Reflection
or CurrentThreadStack
or Throwable
(see the code below), but these do not return a caller object reference.
//----------------------------------------------------------------
@John: I have followed your four steps and made the follo开发者_开发问答wing code. However, in the Foo
class, I cann't get the right Engine
object which is calling the setMessage()
method. Thanks.
import javax.script.*;
public class Engine {
public static ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("ECMAScript");
public String engineName;
public String message;
public Engine(String name) {
this.engineName = name;
}
public void eval(String script) {
try {
Engine.scriptEngine.eval(script);
//to do something more
} catch (ScriptException e) {
System.out.println(e.toString());
}
}
public static void main(String[] args) {
Engine firstEngine = new Engine("First engine");
Engine.scriptEngine.put("firstEngine", firstEngine);
firstEngine.eval("Packages.Foo.setMessage('Hello!');");
Engine secondEngine = new Engine("Second engine");
Engine.scriptEngine.put("secondEngine", secondEngine);
secondEngine.eval("Packages.Foo.setMessage('Hello!');");
}
}
public class Foo {
public static void setMessage(String msg){
Engine myEngine = (Engine)Engine.scriptEngine.get("What engine to get: first engine or second engine???");
myEngine.message = msg;
System.out.println(myEngine.engineName);
}
}
Please help, thanks, John
You cannot get caller's "this", if you mean that.
If the caller is needed at a method, pass it as a parameter?
Step 1: Expose the current script engine as a global variable.
Step 2: Save your engine object in the script engine.
Step 3: Pass the engine object as parameter from javascript.
Step 4: Get your engine instance from Foo.setMessage(SctriptEngine,String)
method.
Step 1:
// expose the current script engine as a global variable
scriptEngine.put("scriptEngine", scriptEngine);
Step 2:
//save your engine object
scriptEngine.put("myEngine", /*YourEngine instance*/);
Step 3:
var imps = JavaImporter(java.io,java.util,/*imports*/);
with(imps){
Foo.setMessage(scriptEngine,"message");
}
Step 4:
public class Foo {
// save ScriptEngine instance if you don't want to pass it as parameter
public static void setMessage(ScriptEngine engine,String msg) {
YourEngine myEngine = (YourEngine)engine.get("myEngine");
// use myEngine...
// or
// ScriptContext sc = engine.getContext();
// YourEngine myEngine = (YourEngine)sc.getAttribute("myEngine");
}
}
UPDATED: keep the same key name(e.g. myEngine) for all Engine
objects. Also it is good to prefix key name with current thread name or id as long as the resultant key name is unique across threads.
String keyName = Thread.currentThread().getName() + "myEngine";
or
String keyName = Thread.currentThread().getId() + "myEngine";//preferred
精彩评论