diff --git a/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java b/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java index 6688ec65ab24c4117178e9d81a2f58c5bf29be2c..787060c16143e93188cafe5007d64b84f4dc82dd 100644 --- a/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java +++ b/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java @@ -115,6 +115,31 @@ public final class RhinoScriptEngine extends AbstractScriptEngine //construct object used to implement getInterface implementor = new InterfaceImplementor(this) { + protected boolean isImplemented(Object thiz, Class iface) { + Context cx = enterContext(); + try { + if (thiz != null && !(thiz instanceof Scriptable)) { + thiz = cx.toObject(thiz, topLevel); + } + Scriptable engineScope = getRuntimeScope(context); + Scriptable localScope = (thiz != null)? (Scriptable) thiz : + engineScope; + for (Method method : iface.getMethods()) { + // ignore methods of java.lang.Object class + if (method.getDeclaringClass() == Object.class) { + continue; + } + Object obj = ScriptableObject.getProperty(localScope, method.getName()); + if (! (obj instanceof Function)) { + return false; + } + } + return true; + } finally { + cx.exit(); + } + } + protected Object convertResult(Method method, Object res) throws ScriptException { Class desiredType = method.getReturnType(); diff --git a/src/share/classes/com/sun/script/util/InterfaceImplementor.java b/src/share/classes/com/sun/script/util/InterfaceImplementor.java index c7aafb97ac8b4eb3038ae083216ac6b1f265552a..b209b4697e801b4e21b50a6077551ea450dd422c 100644 --- a/src/share/classes/com/sun/script/util/InterfaceImplementor.java +++ b/src/share/classes/com/sun/script/util/InterfaceImplementor.java @@ -82,12 +82,19 @@ public class InterfaceImplementor { if (iface == null || !iface.isInterface()) { throw new IllegalArgumentException("interface Class expected"); } + if (! isImplemented(thiz, iface)) { + return null; + } AccessControlContext accCtxt = AccessController.getContext(); return iface.cast(Proxy.newProxyInstance(iface.getClassLoader(), new Class[]{iface}, new InterfaceImplementorInvocationHandler(thiz, accCtxt))); } + protected boolean isImplemented(Object thiz, Class iface) { + return true; + } + // called to convert method result after invoke protected Object convertResult(Method method, Object res) throws ScriptException { diff --git a/test/javax/script/GetInterfaceTest.java b/test/javax/script/GetInterfaceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d780a6db08b905d5500d554784142d0dcb2868d4 --- /dev/null +++ b/test/javax/script/GetInterfaceTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6960211 + * @summary JavaScript engine allows creation of interface although methods not available. + */ + +import javax.script.*; + +public class GetInterfaceTest { + public static void main(String[] args) throws Exception { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine engine = manager.getEngineByName("js"); + + if (engine == null) { + System.out.println("Warning: No engine engine found; test vacuously passes."); + return; + } + + // don't define any function. + engine.eval(""); + + Runnable runnable = ((Invocable)engine).getInterface(Runnable.class); + if (runnable != null) { + throw new RuntimeException("runnable is not null!"); + } + + // now define "run" + engine.eval("function run() { println('this is run function'); }"); + runnable = ((Invocable)engine).getInterface(Runnable.class); + // should not return null now! + runnable.run(); + + // define only one method of "Foo2" + engine.eval("function bar() { println('bar function'); }"); + Foo2 foo2 = ((Invocable)engine).getInterface(Foo2.class); + if (foo2 != null) { + throw new RuntimeException("foo2 is not null!"); + } + + // now define other method of "Foo2" + engine.eval("function bar2() { println('bar2 function'); }"); + foo2 = ((Invocable)engine).getInterface(Foo2.class); + foo2.bar(); + foo2.bar2(); + } + + interface Foo { + public void bar(); + } + + interface Foo2 extends Foo { + public void bar2(); + } +}