开发者

How to obtain a caller object reference from within a called method?

开发者 https://www.devze.com 2023-02-26 09:46 出处:网络
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. Becaus

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
0

精彩评论

暂无评论...
验证码 换一张
取 消