Package com.google.gdt.eclipse.designer.webkit.jsni

Source Code of com.google.gdt.eclipse.designer.webkit.jsni.MethodDispatch

/*******************************************************************************
* 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.gdt.eclipse.designer.webkit.jsni;

import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

import com.google.gdt.eclipse.designer.webkit.jsni.LowLevelWebKit.DispatchMethod;
import com.google.gwt.dev.shell.designtime.DispatchIdOracle;
import com.google.gwt.dev.shell.designtime.JsValue;
import com.google.gwt.dev.shell.designtime.JsValueGlue;
import com.google.gwt.dev.shell.designtime.MethodAdaptor;
import com.google.gwt.dev.shell.designtime.ModuleSpace;

/**
* Wraps an arbitrary Java Method as a Dispatchable component. The class was motivated by the need
* to expose Java objects into JavaScript.
*/
class MethodDispatch<H extends Number> implements DispatchMethod<H> {
  private final WeakReference<ClassLoader> classLoaderRef;
  private final WeakReference<DispatchIdOracle> dispatchIdOracleRef;
  private final MethodAdaptor method;

  public MethodDispatch(ClassLoader classLoader, DispatchIdOracle dispIdOracle, MethodAdaptor method) {
    this.classLoaderRef = new WeakReference<ClassLoader>(classLoader);
    this.dispatchIdOracleRef = new WeakReference<DispatchIdOracle>(dispIdOracle);
    this.method = method;
  }

  public H invoke(H jsContext, H jsthisInt, List<H> jsargsInt, List<H> exception) {
    ClassLoader classLoader = classLoaderRef.get();
    if (classLoader == null) {
      throw new RuntimeException("Invalid class loader.");
    }
    DispatchIdOracle dispatchIdOracle = dispatchIdOracleRef.get();
    if (dispatchIdOracle == null) {
      throw new RuntimeException("Invalid dispatch oracle.");
    }
    LowLevelWebKit.pushJsContext(jsContext);
    JsValue jsthis = new JsValueWebKit<H>(jsthisInt);
    JsValue jsargs[] = new JsValue[jsargsInt.size()];
    for (int i = 0; i < jsargsInt.size(); ++i) {
      jsargs[i] = new JsValueWebKit<H>(jsargsInt.get(i));
    }
    JsValueWebKit<H> returnValue = new JsValueWebKit<H>();
    try {
      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, dispatchIdOracle, method.getReturnType(), result);
        H jsResult = returnValue.getJsValue();
        // Native code will eat an extra ref.
        LowLevelWebKit.gcProtect(jsContext, jsResult);
        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());
        // Native code eats the same ref it gave us.
        exception.add(LowLevelWebKit.getJsNull(jsContext));
        // Native code eats the same ref it gave us.
        return LowLevelWebKit.getJsUndefined(jsContext);
      } 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);
        // Native code eats the same ref it gave us.
        exception.add(LowLevelWebKit.getJsNull(jsContext));
        // Native code eats the same ref it gave us.
        return LowLevelWebKit.getJsUndefined(jsContext);
      }
    } finally {
      LowLevelWebKit.popJsContext(jsContext);
    }
  }
}
TOP

Related Classes of com.google.gdt.eclipse.designer.webkit.jsni.MethodDispatch

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.