1 /* 2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.script.javascript; 27 28 import javax.script.Invocable; 29 import sun.org.mozilla.javascript.internal.*; 30 31 /** 32 * This class implements Rhino-like JavaAdapter to help implement a Java 33 * interface in JavaScript. We support this using Invocable.getInterface. 34 * Using this JavaAdapter, script author could write: 35 * 36 * var r = new java.lang.Runnable() { 37 * run: function() { script... } 38 * }; 39 * 40 * r.run(); 41 * new java.lang.Thread(r).start(); 42 * 43 * Note that Rhino's JavaAdapter support allows extending a Java class and/or 44 * implementing one or more interfaces. This JavaAdapter implementation does 45 * not support these. 46 * 47 * @author A. Sundararajan 48 * @since 1.6 49 */ 50 final class JavaAdapter extends ScriptableObject implements Function { 51 private JavaAdapter(Invocable engine) { 52 this.engine = engine; 53 } 54 55 static void init(Context cx, Scriptable scope, boolean sealed) 56 throws RhinoException { 57 RhinoTopLevel topLevel = (RhinoTopLevel) scope; 58 Invocable engine = topLevel.getScriptEngine(); 59 JavaAdapter obj = new JavaAdapter(engine); 60 obj.setParentScope(scope); 61 obj.setPrototype(getFunctionPrototype(scope)); 62 /* 63 * Note that we can't use defineProperty. A property of this 64 * name is already defined in Context.initStandardObjects. We 65 * simply overwrite the property value! 66 */ 67 ScriptableObject.putProperty(topLevel, "JavaAdapter", obj); 68 } 69 70 public String getClassName() { 71 return "JavaAdapter"; 72 } 73 74 public Object call(Context cx, Scriptable scope, Scriptable thisObj, 75 Object[] args) throws RhinoException { 76 return construct(cx, scope, args); 77 } 78 79 public Scriptable construct(Context cx, Scriptable scope, Object[] args) 80 throws RhinoException { 81 if (args.length == 2) { 82 Class<?> clazz = null; 83 Object obj1 = args[0]; 84 if (obj1 instanceof Wrapper) { 85 Object o = ((Wrapper)obj1).unwrap(); 86 if (o instanceof Class && ((Class)o).isInterface()) { 87 clazz = (Class) o; 88 } 89 } else if (obj1 instanceof Class) { 90 if (((Class)obj1).isInterface()) { 91 clazz = (Class) obj1; 92 } 93 } 94 if (clazz == null) { 95 throw Context.reportRuntimeError("JavaAdapter: first arg should be interface Class"); 96 } 97 98 Scriptable topLevel = ScriptableObject.getTopLevelScope(scope); 99 return cx.toObject(engine.getInterface(args[1], clazz), topLevel); 100 } else { 101 throw Context.reportRuntimeError("JavaAdapter requires two arguments"); 102 } 103 } 104 105 private Invocable engine; 106 }