KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > shell > ie > IDispatchProxy


1 /*
2  * Copyright 2006 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.ie;
17
18 import com.google.gwt.dev.shell.CompilingClassLoader;
19 import com.google.gwt.dev.shell.JavaDispatch;
20 import com.google.gwt.dev.shell.JavaDispatchImpl;
21 import com.google.gwt.dev.shell.JsValueGlue;
22 import com.google.gwt.dev.shell.LowLevel;
23
24 import org.eclipse.swt.internal.ole.win32.COM;
25 import org.eclipse.swt.internal.ole.win32.IDispatch;
26 import org.eclipse.swt.ole.win32.Variant;
27
28 import java.lang.reflect.Field JavaDoc;
29 import java.lang.reflect.InvocationTargetException JavaDoc;
30 import java.lang.reflect.Method JavaDoc;
31
32 /**
33  * Wraps an arbitrary Java Object as an Automation-compatible server. The class
34  * was motivated by the need to expose Java objects into JavaScript.
35  *
36  * <p>
37  * <b>Features</b>
38  * </p>
39  * <ul>
40  * <li>Implements the <code>IDispatch</code> interface for you</li>
41  * <li>If the COM client keeps a reference to this object, this object is
42  * prevented from being garbage collected</li>
43  * <li>Manages a JNI global ref on the target object so that it can be
44  * reliabily passed back and forth between Java and external code </li>
45  * <li>An instance of this class with no target is used to globally access all
46  * static methods or fields.</li>
47  * </ul>
48  *
49  * <p>
50  * <b>Limitations</b>
51  * </p>
52  * <ul>
53  * <li>Only late-bound dispatch is supported</li>
54  * <li>Named arguments are not supported (see {@link #GetIDsOfNames)).</li>
55  * </ul>
56  */

57 class IDispatchProxy extends IDispatchImpl {
58
59   // A magic dispid for getting a global ref to this object.
60
public static final int DISPID_MAGIC_GETGLOBALREF = 0xC131FB56;
61
62   private final CompilingClassLoader classLoader;
63
64   private boolean isDisposed = false;
65
66   private final JavaDispatch javaDispatch;
67
68   private final int myGlobalRef;
69
70   /**
71    * This constructor initializes as the static dispatcher, which handles only
72    * static method calls and field references.
73    *
74    * @param cl this class's classLoader
75    */

76   IDispatchProxy(CompilingClassLoader cl) {
77     javaDispatch = new JavaDispatchImpl(cl);
78     classLoader = cl;
79     myGlobalRef = 0;
80   }
81
82   /**
83    * This constructor initializes a dispatcher, around a particular instance.
84    *
85    * @param cl this class's classLoader
86    * @param target the object being wrapped as an IDispatch
87    */

88   IDispatchProxy(CompilingClassLoader cl, Object JavaDoc target) {
89     javaDispatch = new JavaDispatchImpl(cl, target);
90     classLoader = cl;
91     myGlobalRef = LowLevel.newGlobalRefInt(this);
92   }
93
94   /**
95    * Must be called when the object is no longer needed (to release the global
96    * reference on the target object).
97    */

98   public void dispose() {
99     // Release the global ref on myself.
100
if (myGlobalRef != 0) {
101       LowLevel.deleteGlobalRefInt(myGlobalRef);
102     }
103     super.dispose();
104     isDisposed = true;
105   }
106
107   public Object JavaDoc getTarget() {
108     return javaDispatch.getTarget();
109   }
110
111   /**
112    * Determine whether the proxy has already been disposed (this shouldn't be
113    * necessary, but is needed by ModuleSpaceIE6 to workaround a bug in IE).
114    */

115   public boolean isDisposed() {
116     return isDisposed;
117   }
118
119   protected void getIDsOfNames(String JavaDoc[] names, int[] ids)
120       throws HResultException {
121     ids[0] = classLoader.getDispId(names[0]);
122     if (ids[0] == -1 || names.length >= 2) {
123       throw new HResultException(DISP_E_UNKNOWNNAME);
124     }
125   }
126
127   protected Variant invoke(int dispId, int flags, Variant[] params)
128       throws HResultException, InvocationTargetException JavaDoc {
129     try {
130       // Whatever the caller asks for, try to find it via reflection.
131
//
132
if (dispId == DISPID_MAGIC_GETGLOBALREF && myGlobalRef != 0) {
133         // Handle specially.
134
//
135
return new Variant(myGlobalRef);
136       } else if (dispId == 0) {
137         if ((flags & COM.DISPATCH_METHOD) != 0) {
138           // implicit call -- "m()"
139
// not supported -- fall through to unsupported failure
140
} else if ((flags & COM.DISPATCH_PROPERTYGET) != 0) {
141           // implicit toString -- "'foo' + m"
142
return new Variant(getTarget().toString());
143         }
144
145       } else if (dispId > 0) {
146         if (javaDispatch.isMethod(dispId)) {
147           Method JavaDoc method = javaDispatch.getMethod(dispId);
148           if ((flags & COM.DISPATCH_METHOD) != 0) {
149             // This is a method call.
150
return callMethod(classLoader, getTarget(), params, method);
151           } else if (flags == COM.DISPATCH_PROPERTYGET) {
152             // The function is being accessed as a property.
153
IDispatchImpl funcObj = new MethodDispatch(classLoader, method);
154             IDispatch disp = new IDispatch(funcObj.getAddress());
155             disp.AddRef();
156             return new Variant(disp);
157           }
158         } else if (javaDispatch.isField(dispId)) {
159           Field JavaDoc field = javaDispatch.getField(dispId);
160           if (flags == COM.DISPATCH_PROPERTYGET) {
161             return SwtOleGlue.convertObjectToVariant(classLoader,
162                 field.getType(), javaDispatch.getFieldValue(dispId));
163           } else if ((flags & (COM.DISPATCH_PROPERTYPUT | COM.DISPATCH_PROPERTYPUTREF)) != 0) {
164             javaDispatch.setFieldValue(dispId, JsValueGlue.get(new JsValueIE6(
165                 params[0]), field.getType(), "Setting field '"
166                 + field.getName() + "'"));
167             return new Variant();
168           }
169         }
170       } else {
171         // The specified member id is out of range.
172
throw new HResultException(COM.DISP_E_MEMBERNOTFOUND);
173       }
174     } catch (IllegalArgumentException JavaDoc e) {
175       // should never, ever happen
176
e.printStackTrace();
177       throw new HResultException(e);
178     }
179
180     System.err.println("IDispatchProxy cannot be invoked with flags: "
181         + Integer.toHexString(flags));
182     throw new HResultException(COM.E_NOTSUPPORTED);
183   }
184 }
185
Popular Tags