aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterfaceAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterfaceAdapter.java')
-rw-r--r--trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterfaceAdapter.java156
1 files changed, 156 insertions, 0 deletions
diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterfaceAdapter.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterfaceAdapter.java
new file mode 100644
index 0000000..877e6a2
--- /dev/null
+++ b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterfaceAdapter.java
@@ -0,0 +1,156 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Igor Bukanov
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.javascript;
+
+import java.lang.reflect.Method;
+
+/**
+ * Adapter to use JS function as implementation of Java interfaces with
+ * single method or multiple methods with the same signature.
+ */
+public class InterfaceAdapter
+{
+ private final Object proxyHelper;
+
+ /**
+ * Make glue object implementing interface cl that will
+ * call the supplied JS function when called.
+ * Only interfaces were all methods have the same signature is supported.
+ *
+ * @return The glue object or null if <tt>cl</tt> is not interface or
+ * has methods with different signatures.
+ */
+ static Object create(Context cx, Class cl, Callable function)
+ {
+ if (!cl.isInterface()) throw new IllegalArgumentException();
+
+ Scriptable topScope = ScriptRuntime.getTopCallScope(cx);
+ ClassCache cache = ClassCache.get(topScope);
+ InterfaceAdapter adapter;
+ adapter = (InterfaceAdapter)cache.getInterfaceAdapter(cl);
+ ContextFactory cf = cx.getFactory();
+ if (adapter == null) {
+ Method[] methods = cl.getMethods();
+ if (methods.length == 0) {
+ throw Context.reportRuntimeError2(
+ "msg.no.empty.interface.conversion",
+ String.valueOf(function),
+ cl.getClass().getName());
+ }
+ boolean canCallFunction = false;
+ canCallFunctionChecks: {
+ Class[] argTypes = methods[0].getParameterTypes();
+ // check that the rest of methods has the same signature
+ for (int i = 1; i != methods.length; ++i) {
+ Class[] types2 = methods[i].getParameterTypes();
+ if (types2.length != argTypes.length) {
+ break canCallFunctionChecks;
+ }
+ for (int j = 0; j != argTypes.length; ++j) {
+ if (types2[j] != argTypes[j]) {
+ break canCallFunctionChecks;
+ }
+ }
+ }
+ canCallFunction= true;
+ }
+ if (!canCallFunction) {
+ throw Context.reportRuntimeError2(
+ "msg.no.function.interface.conversion",
+ String.valueOf(function),
+ cl.getClass().getName());
+ }
+ adapter = new InterfaceAdapter(cf, cl);
+ cache.cacheInterfaceAdapter(cl, adapter);
+ }
+ return VMBridge.instance.newInterfaceProxy(
+ adapter.proxyHelper, cf, adapter, function, topScope);
+ }
+
+ private InterfaceAdapter(ContextFactory cf, Class cl)
+ {
+ this.proxyHelper
+ = VMBridge.instance.getInterfaceProxyHelper(
+ cf, new Class[] { cl });
+ }
+
+ public Object invoke(ContextFactory cf,
+ final Object target,
+ final Scriptable topScope,
+ final Method method,
+ final Object[] args)
+ {
+ ContextAction action = new ContextAction() {
+ public Object run(Context cx)
+ {
+ return invokeImpl(cx, target, topScope, method, args);
+ }
+ };
+ return cf.call(action);
+ }
+
+ Object invokeImpl(Context cx,
+ Object target,
+ Scriptable topScope,
+ Method method,
+ Object[] args)
+ {
+ int N = (args == null) ? 0 : args.length;
+
+ Callable function = (Callable)target;
+ Scriptable thisObj = topScope;
+ Object[] jsargs = new Object[N + 1];
+ jsargs[N] = method.getName();
+ if (N != 0) {
+ WrapFactory wf = cx.getWrapFactory();
+ for (int i = 0; i != N; ++i) {
+ jsargs[i] = wf.wrap(cx, topScope, args[i], null);
+ }
+ }
+
+ Object result = function.call(cx, topScope, thisObj, jsargs);
+ Class javaResultType = method.getReturnType();
+ if (javaResultType == Void.TYPE) {
+ result = null;
+ } else {
+ result = Context.jsToJava(result, javaResultType);
+ }
+ return result;
+ }
+}