/*******************************************************************************
* Copyright 2011 Google Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.google.gwt.dev.shell.mac;
import com.google.gdt.eclipse.designer.mac.BrowserShellMac;
import com.google.gdt.eclipse.designer.mac.BrowserShellMac.DispatchMethod;
import com.google.gwt.dev.shell.CompilingClassLoader;
import com.google.gwt.dev.shell.JsValue;
import com.google.gwt.dev.shell.JsValueGlue;
import com.google.gwt.dev.shell.MethodAdaptor;
import com.google.gwt.dev.shell.ModuleSpace;
import java.lang.reflect.InvocationTargetException;
/**
* Wraps an arbitrary Java Method as a Dispatchable component. The class was
* motivated by the need to expose Java objects into JavaScript.
*/
class MethodDispatch implements DispatchMethod {
private final CompilingClassLoader classLoader;
private final MethodAdaptor method;
public MethodDispatch(CompilingClassLoader classLoader, MethodAdaptor method) {
this.classLoader = classLoader;
this.method = method;
}
public long invoke(long jsthisInt, long[] jsargsInt) {
JsValue jsthis = new JsValueSaf(jsthisInt);
JsValue jsargs[] = new JsValue[jsargsInt.length];
for (int i = 0; i < jsargsInt.length; ++i) {
jsargs[i] = new JsValueSaf(jsargsInt[i]);
}
JsValueSaf returnValue = new JsValueSaf();
Class<?>[] paramTypes = method.getParameterTypes();
int argc = paramTypes.length;
Object args[] = new Object[argc];
// too many arguments are ok: the extra will be silently ignored
if (jsargs.length < argc) {
throw new RuntimeException("Not enough arguments to " + method);
}
Object jthis = null;
if (method.needsThis()) {
jthis = JsValueGlue.get(jsthis, classLoader,
method.getDeclaringClass(), "invoke this");
}
for (int i = 0; i < argc; ++i) {
args[i] = JsValueGlue.get(jsargs[i], classLoader, paramTypes[i],
"invoke args");
}
try {
Object result;
try {
result = method.invoke(jthis, args);
} catch (IllegalAccessException e) {
// should never, ever happen
e.printStackTrace();
throw new RuntimeException(e);
}
JsValueGlue.set(returnValue, classLoader, method.getReturnType(),
result);
long jsResult = returnValue.getJsValue();
return jsResult;
} catch (InstantiationException e) {
// If we get here, it means an exception is being thrown from
// Java back into JavaScript
ModuleSpace.setThrownJavaException(e.getCause());
} catch (InvocationTargetException e) {
// If we get here, it means an exception is being thrown from
// Java back into JavaScript
Throwable t = e.getTargetException();
ModuleSpace.setThrownJavaException(t);
}
return BrowserShellMac.jsUndefined();
}
}