下面列出了怎么用javax.script.Invocable的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
/**
* Check that we can get interface out of a script object even after
* switching to use different ScriptContext.
*/
public void getInterfaceDifferentContext() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
final Object obj = e.eval("({ run: function() { } })");
// change script context
final ScriptContext ctxt = new SimpleScriptContext();
ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
e.setContext(ctxt);
final Runnable r = ((Invocable) e).getInterface(obj, Runnable.class);
r.run();
} catch (final Exception exp) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
@Test
public void currentGlobalMissingTest() throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine e = manager.getEngineByName("nashorn");
final Context ctx = new Context();
e.put("ctx", ctx);
e.eval("var obj = { foo: function(str) { return str.toUpperCase() } }");
e.eval("ctx.set(obj)");
final Invocable inv = (Invocable)e;
assertEquals("HELLO", inv.invokeMethod(ctx.get(), "foo", "hello"));
// try object literal
e.eval("ctx.set({ bar: function(str) { return str.toLowerCase() } })");
assertEquals("hello", inv.invokeMethod(ctx.get(), "bar", "HELLO"));
// try array literal
e.eval("var arr = [ 'hello', 'world' ]");
e.eval("ctx.set(arr)");
assertEquals("helloworld", inv.invokeMethod(ctx.get(), "join", ""));
}
/**
* Invokes the UDF with specified data.
*
* @param data data to pass to the invocable function
* @return The data transformed by the UDF in String format
*/
@Nullable
public String invoke(String data) throws ScriptException, IOException, NoSuchMethodException {
Invocable invocable = getInvocable();
if (invocable == null) {
throw new RuntimeException("No udf was loaded");
}
Object result = getInvocable().invokeFunction(functionName(), data);
if (result == null || ScriptObjectMirror.isUndefined(result)) {
return null;
} else if (result instanceof String) {
return (String) result;
} else {
String className = result.getClass().getName();
throw new RuntimeException(
"UDF Function did not return a String. Instead got: " + className);
}
}
private List<String> getFunctionParameters(String functionName) throws ScriptException {
List<String> cached = functionParametersMap.get(functionName);
if(cached != null) {
return cached;
}
Object what = engine.get(functionName);
if(what == null) {
throw new ScriptException("Cannot find JavaScript function \"" + functionName + "\"");
}
try {
String funcString = what.toString();
Object result = ((Invocable) engine).invokeFunction(ARGS_FUNCTION_NAME, funcString);
Object[] params = NashornUtil.asArray(result);
List<String> results = new ArrayList<String>(params.length);
for(Object param : params) {
results.add((String)param);
}
functionParametersMap.put(functionName, results);
return results;
}
catch(Exception ex) {
throw new ScriptException(ex);
}
}
@Test
public void invokeFunctionInGlobalScopeTest() throws Exception {
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
final ScriptContext ctxt = engine.getContext();
// define a function called "func"
engine.eval("func = function() { return 42 }");
// move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
// create a new Bindings and set as ENGINE_SCOPE
ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
// define new function that calls "func" now in GLOBAL_SCOPE
engine.eval("newfunc = function() { return func() }");
// call "newfunc" and check the return value
Object value = ((Invocable)engine).invokeFunction("newfunc");
assertTrue(((Number)value).intValue() == 42);
}
@Test
public void invokeFunctionWithCustomScriptContextTest() throws Exception {
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
// create an engine and a ScriptContext, but don't set it as default
ScriptContext scriptContext = new SimpleScriptContext();
// Set some value in the context
scriptContext.setAttribute("myString", "foo", ScriptContext.ENGINE_SCOPE);
// Evaluate script with custom context and get back a function
final String script = "function (c) { return myString.indexOf(c); }";
CompiledScript compiledScript = ((Compilable)engine).compile(script);
Object func = compiledScript.eval(scriptContext);
// Invoked function should be able to see context it was evaluated with
Object result = ((Invocable) engine).invokeMethod(func, "call", func, "o", null);
assertTrue(((Number)result).intValue() == 1);
}
@Test
/**
* Check that calling getInterface on mirror created by another engine
* results in IllegalArgumentException.
*/
public void getInterfaceMixEnginesTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine engine1 = m.getEngineByName("nashorn");
final ScriptEngine engine2 = m.getEngineByName("nashorn");
try {
Object obj = engine1.eval("({ run: function() {} })");
// pass object from engine1 to engine2 as 'thiz' for getInterface
((Invocable) engine2).getInterface(obj, Runnable.class);
fail("should have thrown IllegalArgumentException");
} catch (final Exception exp) {
if (!(exp instanceof IllegalArgumentException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Test
/**
* Check that invokeMethod throws NPE on null method name.
*/
public void invokeMethodNullNameTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
final Object obj = e.eval("({})");
((Invocable) e).invokeMethod(obj, null);
fail("should have thrown NPE");
} catch (final Exception exp) {
if (!(exp instanceof NullPointerException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Test
/**
* Check that invokeMethod throws NoSuchMethodException on missing method.
*/
public void invokeMethodMissingTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
final Object obj = e.eval("({})");
((Invocable) e).invokeMethod(obj, "nonExistentMethod");
fail("should have thrown NoSuchMethodException");
} catch (final Exception exp) {
if (!(exp instanceof NoSuchMethodException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Test
/**
* Check that calling getInterface on mirror created by another engine
* results in IllegalArgumentException.
*/
public void getInterfaceMixEnginesTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine engine1 = m.getEngineByName("nashorn");
final ScriptEngine engine2 = m.getEngineByName("nashorn");
try {
final Object obj = engine1.eval("({ run: function() {} })");
// pass object from engine1 to engine2 as 'thiz' for getInterface
((Invocable) engine2).getInterface(obj, Runnable.class);
fail("should have thrown IllegalArgumentException");
} catch (final Exception exp) {
if (!(exp instanceof IllegalArgumentException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Test
/**
* Check that calling method on null 'thiz' results in
* IllegalArgumentException.
*/
public void invokeMethodNullThizTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
((Invocable) e).invokeMethod(null, "toString");
fail("should have thrown IllegalArgumentException");
} catch (final Exception exp) {
if (!(exp instanceof IllegalArgumentException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
ScriptEngine engine = getEngine();
Invocable invocable = (Invocable) engine;
String url = getUrl();
String template = getTemplate(url);
Object html;
if (this.renderObject != null) {
Object thiz = engine.eval(this.renderObject);
html = invocable.invokeMethod(thiz, this.renderFunction, template, model, url);
}
else {
html = invocable.invokeFunction(this.renderFunction, template, model, url);
}
response.getWriter().write(String.valueOf(html));
}
catch (ScriptException ex) {
throw new ServletException("Failed to render script template", new StandardScriptEvalException(ex));
}
}
@Test
/**
* Try passing non-interface Class object for interface implementation.
*/
public void getNonInterfaceGetInterfaceTest() {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
try {
log(Objects.toString(((Invocable) engine).getInterface(Object.class)));
fail("Should have thrown IllegalArgumentException");
} catch (final Exception exp) {
if (!(exp instanceof IllegalArgumentException)) {
fail("IllegalArgumentException expected, got " + exp);
}
}
}
@Test
/**
* Check that we can get interface out of a script object even after
* switching to use different ScriptContext.
*/
public void getInterfaceDifferentContext() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
final Object obj = e.eval("({ run: function() { } })");
// change script context
final ScriptContext ctxt = new SimpleScriptContext();
ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
e.setContext(ctxt);
final Runnable r = ((Invocable) e).getInterface(obj, Runnable.class);
r.run();
} catch (final Exception exp) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
ScriptEngine engine = getEngine();
Invocable invocable = (Invocable) engine;
String url = getUrl();
String template = getTemplate(url);
Object html;
if (this.renderObject != null) {
Object thiz = engine.eval(this.renderObject);
html = invocable.invokeMethod(thiz, this.renderFunction, template, model, url);
}
else {
html = invocable.invokeFunction(this.renderFunction, template, model, url);
}
response.getWriter().write(String.valueOf(html));
}
catch (ScriptException ex) {
throw new ServletException("Failed to render script template", new StandardScriptEvalException(ex));
}
}
@Test
/**
* Check that invokeFunction calls functions only from current context's
* Bindings.
*/
public void invokeFunctionDifferentContextTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
// define an object with method on it
e.eval("function hello() { return 'Hello World!'; }");
final ScriptContext ctxt = new SimpleScriptContext();
ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
// change engine's current context
e.setContext(ctxt);
((Invocable) e).invokeFunction("hello"); // no 'hello' in new context!
fail("should have thrown NoSuchMethodException");
} catch (final Exception exp) {
if (!(exp instanceof NoSuchMethodException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Test
/**
* Check that getInterface on non-script object 'thiz' results in
* IllegalArgumentException.
*/
public void getInterfaceNonScriptObjectThizTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
((Invocable) e).getInterface(new Object(), Runnable.class);
fail("should have thrown IllegalArgumentException");
} catch (final Exception exp) {
if (!(exp instanceof IllegalArgumentException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Test
/**
* Check that invokeMethod throws NPE on null method name.
*/
public void invokeMethodNullNameTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
final Object obj = e.eval("({})");
((Invocable) e).invokeMethod(obj, null);
fail("should have thrown NPE");
} catch (final Exception exp) {
if (!(exp instanceof NullPointerException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
public void act(MapleClient c, MapleReactor reactor) {
try {
Invocable iv = getInvocable("reactors/" + reactor.getReactorId() + ".js", c);
if (iv == null) {
if (c.getPlayer().isShowPacket()) {
c.getPlayer().dropMessage(5, "未找到 反应堆 文件中的 " + reactor.getReactorId() + ".js 文件.");
}
FileoutputUtil.log(FileoutputUtil.Reactor_ScriptEx_Log, "未找到 反应堆 文件中的 " + reactor.getReactorId() + ".js 文件.");
return;
}
ScriptEngine scriptengine = (ScriptEngine) iv;
ReactorActionManager rm = new ReactorActionManager(c, reactor);
scriptengine.put("rm", rm);
iv.invokeFunction("act", new Object[0]);
} catch (ScriptException | NoSuchMethodException e) {
System.err.println("执行反应堆文件出错 反应堆ID: " + reactor.getReactorId() + ", 反应堆名称: " + reactor.getName() + " 错误信息: " + e);
FileoutputUtil.log(FileoutputUtil.Reactor_ScriptEx_Log, "执行反应堆文件出错 反应堆ID: " + reactor.getReactorId() + ", 反应堆名称: " + reactor.getName() + " 错误信息: " + e);
}
}
@Test
public void returnArrayInJS() throws Exception {
Object fn = engine.eval("(function(obj) {\n"
+ " return [ 1, 2, 'a', Math.PI, obj ];\n"
+ "})\n");
assertNotNull(fn);
Sum sum = new Sum();
Object raw = ((Invocable) engine).invokeMethod(fn, "call", null, sum);
ArrayLike res = ((Invocable) engine).getInterface(raw, ArrayLike.class);
if (res == null) {
assumeNotNashorn();
}
assertNotNull("Result looks like array", res);
List<?> list = ((Invocable) engine).getInterface(raw, List.class);
assertEquals("Length of five", 5, list.size());
assertEquals(1, list.get(0));
assertEquals(2, list.get(1));
assertEquals("a", list.get(2));
assertEquals(Math.PI, list.get(3));
assertEquals(sum, list.get(4));
}
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String
final String script = "function run() { print('run called'); }";
// evaluate script
engine.eval(script);
final Invocable inv = (Invocable) engine;
// get Runnable interface object from engine. This interface methods
// are implemented by script functions with the matching name.
final Runnable r = inv.getInterface(Runnable.class);
// start a new thread that runs the script implemented
// runnable interface
final Thread th = new Thread(r);
th.start();
th.join();
}
@Test
/**
* Check that invokeMethod throws NoSuchMethodException on missing method.
*/
public void invokeMethodMissingTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
final Object obj = e.eval("({})");
((Invocable) e).invokeMethod(obj, "nonExistentMethod");
fail("should have thrown NoSuchMethodException");
} catch (final Exception exp) {
if (!(exp instanceof NoSuchMethodException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Test
/**
* Check that attempt to call missing function results in
* NoSuchMethodException.
*/
public void invokeFunctionMissingTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
((Invocable)e).invokeFunction("NonExistentFunc");
fail("should have thrown NoSuchMethodException");
} catch (final Exception exp) {
if (!(exp instanceof NoSuchMethodException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Override
public boolean match(List<GrpcURL> providerUrls) {
String rule = super.getRule();
try {
engine.eval(super.getRule());
Invocable invocable = (Invocable) engine;
GrpcURL refUrl = super.getRefUrl();
Object obj = invocable.invokeFunction("route", refUrl, providerUrls);
if (obj instanceof Boolean) {
return (Boolean) obj;
} else {
return true;
}
} catch (ScriptException | NoSuchMethodException e) {
log.error("route error , rule has been ignored. rule: " + rule + ", url: " + providerUrls, e);
return true;
}
}
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String
final String script = "function hello(name) { print('Hello, ' + name); }";
// evaluate script
engine.eval(script);
// javax.script.Invocable is an optional interface.
// Check whether your script engine implements or not!
// Note that the JavaScript engine implements Invocable interface.
final Invocable inv = (Invocable) engine;
// invoke the global function named "hello"
inv.invokeFunction("hello", "Scripting!!" );
}
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String
final String script = "var obj = new Object(); obj.run = function() { print('run method called'); }";
// evaluate script
engine.eval(script);
// get script object on which we want to implement the interface with
final Object obj = engine.get("obj");
final Invocable inv = (Invocable) engine;
// get Runnable interface object from engine. This interface methods
// are implemented by script methods of object 'obj'
final Runnable r = inv.getInterface(obj, Runnable.class);
// start a new thread that runs the script implemented
// runnable interface
final Thread th = new Thread(r);
th.start();
th.join();
}
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String. This code defines a script object 'obj'
// with one method called 'hello'.
final String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
// evaluate script
engine.eval(script);
// javax.script.Invocable is an optional interface.
// Check whether your script engine implements or not!
// Note that the JavaScript engine implements Invocable interface.
final Invocable inv = (Invocable) engine;
// get script object on which we want to call the method
final Object obj = engine.get("obj");
// invoke the method named "hello" on the script object "obj"
inv.invokeMethod(obj, "hello", "Script Method !!" );
}
@Test
/**
* Check that invokeMethod throws NPE on null method name.
*/
public void invokeMethodNullNameTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
final Object obj = e.eval("({})");
((Invocable) e).invokeMethod(obj, null);
fail("should have thrown NPE");
} catch (final Exception exp) {
if (!(exp instanceof NullPointerException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}
@Test
public void invokeFunctionInGlobalScopeTest() throws Exception {
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
final ScriptContext ctxt = engine.getContext();
// define a function called "func"
engine.eval("func = function() { return 42 }");
// move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
// create a new Bindings and set as ENGINE_SCOPE
ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
// define new function that calls "func" now in GLOBAL_SCOPE
engine.eval("newfunc = function() { return func() }");
// call "newfunc" and check the return value
Object value = ((Invocable)engine).invokeFunction("newfunc");
assertTrue(((Number)value).intValue() == 42);
}
@Test
/**
* Check that calling method on non-script object 'thiz' results in
* IllegalArgumentException.
*/
public void invokeMethodNonScriptObjectThizTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
((Invocable) e).invokeMethod(new Object(), "toString");
fail("should have thrown IllegalArgumentException");
} catch (final Exception exp) {
if (!(exp instanceof IllegalArgumentException)) {
exp.printStackTrace();
fail(exp.getMessage());
}
}
}