/* * Copyright 2011 Chad Retz * * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * 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 org.gwtnode.dev.debug; import java.util.Stack; import org.gwtnode.core.JavaScriptFunctionArguments; import org.gwtnode.core.JavaScriptReturningFunctionWrapper; import org.gwtnode.core.JavaScriptUtils; import org.gwtnode.core.node.process.Process; import org.gwtnode.dev.debug.HostChannel.ReturnMessageCallback; import org.gwtnode.dev.debug.message.InvokeFromClientMessage; import org.gwtnode.dev.debug.message.ReturnMessage; import org.gwtnode.dev.debug.message.Value; import org.gwtnode.modules.fibers.Fiber; import org.gwtnode.modules.fibers.FiberReturningCallback; import com.google.gwt.core.client.JavaScriptException; /** * Invoker for Java executions * * @author Chad Retz */ class JavaInvoker<T> extends JavaScriptReturningFunctionWrapper<T> implements ReturnMessageCallback { private final HostChannel channel; private final SessionHandler handler; private final int paramCount; private final Stack<Fiber> waitingForReturn = new Stack<Fiber>(); public JavaInvoker(HostChannel channel, SessionHandler handler, int paramCount) { this.channel = channel; this.handler = handler; this.paramCount = paramCount; } @Override public T call(JavaScriptFunctionArguments args) { try { handler.getLog().debug("Called java invoker for %d params", paramCount); //first is the "this" object handler.getLog().debug("dispId type: " + args.get(1).getClass()); Value<?> thisObj = handler.getValueFromJavaScriptObject(args.get(0)); //second is the dispatch ID int dispId = Integer.valueOf(args.get(1).toString()); handler.getLog().debug("dispId: " + dispId); //the rest are arguments Value<?>[] argList = new Value<?>[args.length() - 2]; for (int i = 0; i < argList.length; i++) { argList[i] = handler.getValueFromJavaScriptObject(args.get(i + 2)); } //create the fiber and go with the message return Fiber.create(new FiberReturningCallback<T>() { @Override @SuppressWarnings("unchecked") public T onCreate(Object param) { //push me on the stack waitingForReturn.push(Fiber.current()); handler.getLog().debug("Sending invoke from client"); //send message channel.sendMessage((InvokeFromClientMessage) param, JavaInvoker.this); handler.getLog().debug("Waiting for response from server"); //wait ReturnMessage returnMessage = Fiber.yield(); handler.getLog().debug("Got response from server"); //handle message if (returnMessage.isException()) { throw new JavaScriptException(handler.getJavaScriptObjectFromValue( returnMessage.getReturnValue())); } else { return (T) handler.getJavaScriptObjectFromValue( returnMessage.getReturnValue()); } } }).<T>run(new InvokeFromClientMessage(dispId, thisObj, argList)); } catch (Exception e) { handler.getLog().error("Error: %s", JavaScriptUtils. appendException(e, new StringBuilder())); Process.get().exit(); //throw new RuntimeException(e); return null; } } @Override public void onMessage(ReturnMessage message) { if (waitingForReturn.isEmpty()) { handler.getLog().error("Unexpected return message"); } else { handler.getLog().debug("Letting fiber know I got response from server"); waitingForReturn.pop().run(message); } } }