Package com.google.gwt.dev.shell.ie

Source Code of com.google.gwt.dev.shell.ie.IDispatchProxy

/*
* Copyright 2006 Google Inc.
*
* 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 com.google.gwt.dev.shell.ie;

import com.google.gwt.dev.shell.CompilingClassLoader;
import com.google.gwt.dev.shell.JavaDispatch;
import com.google.gwt.dev.shell.JavaDispatchImpl;
import com.google.gwt.dev.shell.JsValueGlue;
import com.google.gwt.dev.shell.LowLevel;

import org.eclipse.swt.internal.ole.win32.COM;
import org.eclipse.swt.internal.ole.win32.IDispatch;
import org.eclipse.swt.ole.win32.Variant;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
* Wraps an arbitrary Java Object as an Automation-compatible server. The class
* was motivated by the need to expose Java objects into JavaScript.
*
* <p>
* <b>Features</b>
* </p>
* <ul>
* <li>Implements the <code>IDispatch</code> interface for you</li>
* <li>If the COM client keeps a reference to this object, this object is
* prevented from being garbage collected</li>
* <li>Manages a JNI global ref on the target object so that it can be
* reliabily passed back and forth between Java and external code </li>
* <li>An instance of this class with no target is used to globally access all
* static methods or fields.</li>
* </ul>
*
* <p>
* <b>Limitations</b>
* </p>
* <ul>
* <li>Only late-bound dispatch is supported</li>
* <li>Named arguments are not supported (see {@link #GetIDsOfNames)).</li>
* </ul>
*/
class IDispatchProxy extends IDispatchImpl {

  // A magic dispid for getting a global ref to this object.
  public static final int DISPID_MAGIC_GETGLOBALREF = 0xC131FB56;

  private final CompilingClassLoader classLoader;

  private boolean isDisposed = false;

  private final JavaDispatch javaDispatch;

  private final int myGlobalRef;

  /**
   * This constructor initializes as the static dispatcher, which handles only
   * static method calls and field references.
   *
   * @param cl this class's classLoader
   */
  IDispatchProxy(CompilingClassLoader cl) {
    javaDispatch = new JavaDispatchImpl(cl);
    classLoader = cl;
    myGlobalRef = 0;
  }

  /**
   * This constructor initializes a dispatcher, around a particular instance.
   *
   * @param cl this class's classLoader
   * @param target the object being wrapped as an IDispatch
   */
  IDispatchProxy(CompilingClassLoader cl, Object target) {
    javaDispatch = new JavaDispatchImpl(cl, target);
    classLoader = cl;
    myGlobalRef = LowLevel.newGlobalRefInt(this);
  }

  /**
   * Must be called when the object is no longer needed (to release the global
   * reference on the target object).
   */
  public void dispose() {
    // Release the global ref on myself.
    if (myGlobalRef != 0) {
      LowLevel.deleteGlobalRefInt(myGlobalRef);
    }
    super.dispose();
    isDisposed = true;
  }

  public Object getTarget() {
    return javaDispatch.getTarget();
  }

  /**
   * Determine whether the proxy has already been disposed (this shouldn't be
   * necessary, but is needed by ModuleSpaceIE6 to workaround a bug in IE).
   */
  public boolean isDisposed() {
    return isDisposed;
  }

  protected void getIDsOfNames(String[] names, int[] ids)
      throws HResultException {
    ids[0] = classLoader.getDispId(names[0]);
    if (ids[0] == -1 || names.length >= 2) {
      throw new HResultException(DISP_E_UNKNOWNNAME);
    }
  }

  protected Variant invoke(int dispId, int flags, Variant[] params)
      throws HResultException, InvocationTargetException {
    try {
      // Whatever the caller asks for, try to find it via reflection.
      //
      if (dispId == DISPID_MAGIC_GETGLOBALREF && myGlobalRef != 0) {
        // Handle specially.
        //
        return new Variant(myGlobalRef);
      } else if (dispId == 0) {
        if ((flags & COM.DISPATCH_METHOD) != 0) {
          // implicit call -- "m()"
          // not supported -- fall through to unsupported failure
        } else if ((flags & COM.DISPATCH_PROPERTYGET) != 0) {
          // implicit toString -- "'foo' + m"
          return new Variant(getTarget().toString());
        }

      } else if (dispId > 0) {
        if (javaDispatch.isMethod(dispId)) {
          Method method = javaDispatch.getMethod(dispId);
          if ((flags & COM.DISPATCH_METHOD) != 0) {
            // This is a method call.
            return callMethod(classLoader, getTarget(), params, method);
          } else if (flags == COM.DISPATCH_PROPERTYGET) {
            // The function is being accessed as a property.
            IDispatchImpl funcObj = new MethodDispatch(classLoader, method);
            IDispatch disp = new IDispatch(funcObj.getAddress());
            disp.AddRef();
            return new Variant(disp);
          }
        } else if (javaDispatch.isField(dispId)) {
          Field field = javaDispatch.getField(dispId);
          if (flags == COM.DISPATCH_PROPERTYGET) {
            return SwtOleGlue.convertObjectToVariant(classLoader,
                field.getType(), javaDispatch.getFieldValue(dispId));
          } else if ((flags & (COM.DISPATCH_PROPERTYPUT | COM.DISPATCH_PROPERTYPUTREF)) != 0) {
            javaDispatch.setFieldValue(dispId, JsValueGlue.get(new JsValueIE6(
                params[0]), field.getType(), "Setting field '"
                + field.getName() + "'"));
            return new Variant();
          }
        }
      } else {
        // The specified member id is out of range.
        throw new HResultException(COM.DISP_E_MEMBERNOTFOUND);
      }
    } catch (IllegalArgumentException e) {
      // should never, ever happen
      e.printStackTrace();
      throw new HResultException(e);
    }

    System.err.println("IDispatchProxy cannot be invoked with flags: "
        + Integer.toHexString(flags));
    throw new HResultException(COM.E_NOTSUPPORTED);
  }
}
TOP

Related Classes of com.google.gwt.dev.shell.ie.IDispatchProxy

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.