01: /*
02: * Copyright 2007 Google Inc.
03: *
04: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
05: * use this file except in compliance with the License. You may obtain a copy of
06: * the License at
07: *
08: * http://www.apache.org/licenses/LICENSE-2.0
09: *
10: * Unless required by applicable law or agreed to in writing, software
11: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13: * License for the specific language governing permissions and limitations under
14: * the License.
15: */
16: package com.google.gwt.dev.shell.mac;
17:
18: import com.google.gwt.dev.shell.CompilingClassLoader;
19: import com.google.gwt.dev.shell.JsValue;
20: import com.google.gwt.dev.shell.JsValueGlue;
21: import com.google.gwt.dev.shell.ModuleSpace;
22: import com.google.gwt.dev.shell.mac.LowLevelSaf.DispatchMethod;
23:
24: import java.lang.reflect.InvocationTargetException;
25: import java.lang.reflect.Method;
26: import java.lang.reflect.Modifier;
27:
28: /**
29: * Wraps an arbitrary Java Method as a Dispatchable component. The class was
30: * motivated by the need to expose Java objects into JavaScript.
31: */
32: class MethodDispatch implements DispatchMethod {
33:
34: private final CompilingClassLoader classLoader;
35:
36: private final Method method;
37:
38: public MethodDispatch(CompilingClassLoader classLoader,
39: Method method) {
40: this .classLoader = classLoader;
41: this .method = method;
42: }
43:
44: public int invoke(int execState, int jsthis Int, int[] jsargsInt) {
45: LowLevelSaf.pushExecState(execState);
46: JsValue jsthis = new JsValueSaf(jsthis Int);
47: JsValue jsargs[] = new JsValue[jsargsInt.length];
48: for (int i = 0; i < jsargsInt.length; ++i) {
49: jsargs[i] = new JsValueSaf(jsargsInt[i]);
50: }
51: JsValueSaf returnValue = new JsValueSaf();
52: try {
53: Class<?>[] paramTypes = method.getParameterTypes();
54: int argc = paramTypes.length;
55: Object args[] = new Object[argc];
56: if (jsargs.length < argc) {
57: throw new RuntimeException("Not enough arguments to "
58: + method);
59: }
60: if (jsargs.length > argc) {
61: throw new RuntimeException("Too many arguments to "
62: + method);
63: }
64: Object jthis = null;
65: if ((method.getModifiers() & Modifier.STATIC) == 0) {
66: jthis = JsValueGlue.get(jsthis , method
67: .getDeclaringClass(), "invoke this");
68: }
69: for (int i = 0; i < argc; ++i) {
70: args[i] = JsValueGlue.get(jsargs[i], paramTypes[i],
71: "invoke args");
72: }
73: try {
74: Object result;
75: try {
76: result = method.invoke(jthis , args);
77: } catch (IllegalAccessException e) {
78: // should never, ever happen
79: e.printStackTrace();
80: throw new RuntimeException(e);
81: }
82: JsValueGlue.set(returnValue, classLoader, method
83: .getReturnType(), result);
84: return returnValue.getJsValue();
85: } catch (InvocationTargetException e) {
86: // If we get here, it means an exception is being thrown from
87: // Java back into JavaScript
88: Throwable t = e.getTargetException();
89: ModuleSpace.setThrownJavaException(t);
90: LowLevelSaf.raiseJavaScriptException(execState,
91: LowLevelSaf.jsNull());
92: return LowLevelSaf.jsUndefined();
93: }
94: } finally {
95: LowLevelSaf.popExecState(execState);
96: }
97: }
98: }
|