blob: 3ac71d7c32e322e6028c8bb034594f0a55e282d9 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.script.javascript;
27
28import javax.script.Invocable;
29import 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 */
50final 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}