KickJava   Java API By Example, From Geeks To Geeks.

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


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.ModuleSpace;
20 import com.google.gwt.dev.util.log.AbstractTreeLogger;
21
22 import org.eclipse.swt.internal.ole.win32.COM;
23 import org.eclipse.swt.internal.ole.win32.COMObject;
24 import org.eclipse.swt.internal.ole.win32.DISPPARAMS;
25 import org.eclipse.swt.internal.ole.win32.GUID;
26 import org.eclipse.swt.internal.win32.OS;
27 import org.eclipse.swt.ole.win32.OleAutomation;
28 import org.eclipse.swt.ole.win32.Variant;
29
30 import java.lang.reflect.InvocationTargetException JavaDoc;
31 import java.lang.reflect.Method JavaDoc;
32 import java.util.Arrays JavaDoc;
33
34 /**
35  * Basic IDispatch implementation for use by
36  * {@link com.google.gwt.shell.ie.IDispatchProxy} and
37  * {@link com.google.gwt.shell.ie.IDispatchStatic}.
38  */

39 abstract class IDispatchImpl extends COMObject {
40
41   /**
42    * An exception for wrapping bad HR's.
43    */

44   protected static class HResultException extends Exception JavaDoc {
45     private int hr;
46
47     private String JavaDoc source;
48
49     /**
50      * Constructs a standard bad HR exception.
51      */

52     public HResultException(int hr) {
53       super(Integer.toString(hr));
54       this.hr = hr;
55       source = "Java";
56     }
57
58     /**
59      * Constructs a DISP_E_EXCEPTION bad HR.
60      */

61     public HResultException(String JavaDoc message) {
62       super(message);
63       hr = COM.DISP_E_EXCEPTION;
64       source = "Java";
65     }
66
67     /**
68      * Constructs a DISP_E_EXCEPTION bad HR.
69      */

70     public HResultException(Throwable JavaDoc e) {
71       super(AbstractTreeLogger.getStackTraceAsString(e), e);
72       hr = COM.DISP_E_EXCEPTION;
73       source = "Java";
74     }
75
76     /**
77      * If the HR is DISP_E_EXCEPTION, this method will fill in the EXCEPINFO
78      * structure. Otherwise, it does nothing.
79      */

80     public void fillExcepInfo(int pExcepInfo) {
81       if (hr == COM.DISP_E_EXCEPTION) {
82         String JavaDoc desc = getMessage();
83         // 0: wCode (size = 2)
84
// 4: bstrSource (size = 4)
85
// 8: bstrDescription (size = 4)
86
// 28: scode (size = 4)
87
//
88
OS.MoveMemory(pExcepInfo + 0, new short[] {(short) hr}, 2);
89
90         if (source != null) {
91           int bstrSource = SwtOleGlue.sysAllocString(source);
92           OS.MoveMemory(pExcepInfo + 4, new int[] {bstrSource}, 4);
93         }
94
95         if (desc != null) {
96           int bstrDesc = SwtOleGlue.sysAllocString(desc);
97           OS.MoveMemory(pExcepInfo + 8, new int[] {bstrDesc}, 4);
98         }
99
100         OS.MoveMemory(pExcepInfo + 28, new int[] {0}, 4);
101       }
102     }
103
104     /**
105      * Gets the HR.
106      */

107     public int getHResult() {
108       return hr;
109     }
110   }
111
112   // This one isn't defined in SWT for some reason.
113
protected static final int DISP_E_UNKNOWNNAME = 0x80020006;
114
115   protected static Variant callMethod(CompilingClassLoader cl, Object JavaDoc jthis,
116       Variant[] params, Method JavaDoc method) throws InvocationTargetException JavaDoc,
117       HResultException {
118     // TODO: make sure we have enough args! It's okay if there are too many.
119
Object JavaDoc[] javaParams = SwtOleGlue.convertVariantsToObjects(
120         method.getParameterTypes(), params, "Calling method '"
121             + method.getName() + "'");
122
123     Object JavaDoc result = null;
124     try {
125       try {
126         result = method.invoke(jthis, javaParams);
127       } catch (IllegalAccessException JavaDoc e) {
128         // should never, ever happen
129
e.printStackTrace();
130         throw new RuntimeException JavaDoc(e);
131       }
132     } catch (NullPointerException JavaDoc e) {
133       /*
134        * The JavaScript expected the method to be static, having forgotten an
135        * instance reference (most often "this.").
136        */

137       StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
138       sb.append("Instance method '");
139       sb.append(method.getName());
140       sb.append("' needed a qualifying instance ");
141       sb.append("(did you forget to prefix the call with 'this.'?)");
142       throw new HResultException(sb.toString());
143     } finally {
144       for (int i = 0; i < javaParams.length; i++) {
145         if (javaParams[i] instanceof OleAutomation) {
146           OleAutomation tmp = (OleAutomation) javaParams[i];
147           tmp.dispose();
148         }
149       }
150     }
151
152     // Convert it to a variant (if the return type is void, return
153
// a VT_EMPTY variant -- 'undefined' in JavaScript).
154
//
155
Class JavaDoc returnType = method.getReturnType();
156     if (returnType.equals(Void.TYPE)) {
157       return new Variant();
158     }
159     return SwtOleGlue.convertObjectToVariant(cl, returnType, result);
160   }
161
162   protected int refCount;
163
164   public IDispatchImpl() {
165     super(new int[] {2, 0, 0, 1, 3, 5, 8});
166   }
167
168   // CHECKSTYLE_OFF
169
public int AddRef() {
170     return ++refCount;
171   }
172
173   // CHECKSTYLE_ON
174

175   public int method0(int[] args) {
176     return QueryInterface(args[0], args[1]);
177   }
178
179   public int method1(int[] args) {
180     return AddRef();
181   }
182
183   // method3 GetTypeInfoCount - not implemented
184

185   // method4 GetTypeInfo - not implemented
186

187   public int method2(int[] args) {
188     return Release();
189   }
190
191   public int method5(int[] args) {
192     return GetIDsOfNames(args[0], args[1], args[2], args[3], args[4]);
193   }
194
195   public int method6(int[] args) {
196     return Invoke(args[0], args[1], args[2], args[3], args[4], args[5],
197         args[6], args[7]);
198   }
199
200   // CHECKSTYLE_OFF
201
public int QueryInterface(int riid, int ppvObject) {
202     if (riid == 0 || ppvObject == 0) {
203       return COM.E_NOINTERFACE;
204     }
205     GUID guid = new GUID();
206     COM.MoveMemory(guid, riid, GUID.sizeof);
207
208     if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) {
209       COM.MoveMemory(ppvObject, new int[] {getAddress()}, 4);
210       AddRef();
211       return COM.S_OK;
212     }
213
214     if (COM.IsEqualGUID(guid, COM.IIDIDispatch)) {
215       COM.MoveMemory(ppvObject, new int[] {getAddress()}, 4);
216       AddRef();
217       return COM.S_OK;
218     }
219
220     COM.MoveMemory(ppvObject, new int[] {0}, 4);
221     return COM.E_NOINTERFACE;
222   }
223
224   public int Release() {
225     if (--refCount == 0) {
226       dispose();
227     }
228     return refCount;
229   }
230
231   // CHECKSTYLE_ON
232

233   /**
234    * Override this method to implement GetIDsOfNames().
235    */

236   protected abstract void getIDsOfNames(String JavaDoc[] names, int[] ids)
237       throws HResultException;
238
239   /**
240    * Override this method to implement Invoke().
241    */

242   protected abstract Variant invoke(int dispId, int flags, Variant[] params)
243       throws HResultException, InvocationTargetException JavaDoc;
244
245   private Variant[] extractVariantArrayFromDispParamsPtr(int pDispParams) {
246     DISPPARAMS dispParams = new DISPPARAMS();
247     COM.MoveMemory(dispParams, pDispParams, DISPPARAMS.sizeof);
248     Variant[] variants = new Variant[dispParams.cArgs];
249     // Reverse the order as we pull the variants in.
250
for (int i = 0, n = dispParams.cArgs; i < n; ++i) {
251       int varArgAddr = dispParams.rgvarg + Variant.sizeof * i;
252       variants[n - i - 1] = Variant.win32_new(varArgAddr);
253     }
254     return variants;
255   }
256
257   // CHECKSTYLE_OFF
258
private final int GetIDsOfNames(int riid, int rgszNames, int cNames,
259       int lcid, int rgDispId) {
260
261     try {
262       if (cNames < 1) {
263         return COM.E_INVALIDARG;
264       }
265
266       // Extract the requested names and build an answer array init'ed with -1.
267
//
268
String JavaDoc[] names = SwtOleGlue.extractStringArrayFromOleCharPtrPtr(
269           rgszNames, cNames);
270       int[] ids = new int[names.length];
271       Arrays.fill(ids, -1);
272
273       getIDsOfNames(names, ids);
274       OS.MoveMemory(rgDispId, ids, ids.length * 4);
275     } catch (HResultException e) {
276       return e.getHResult();
277     } catch (Throwable JavaDoc e) {
278       e.printStackTrace();
279       return COM.E_FAIL;
280     }
281
282     return COM.S_OK;
283   }
284
285   private int Invoke(int dispIdMember, int riid, int lcid, int dwFlags,
286       int pDispParams, int pVarResult, int pExcepInfo, int pArgErr) {
287
288     HResultException ex = null;
289     Variant[] vArgs = null;
290     Variant result = null;
291     try {
292       vArgs = extractVariantArrayFromDispParamsPtr(pDispParams);
293       result = invoke(dispIdMember, dwFlags, vArgs);
294       if (pVarResult != 0) {
295         Variant.win32_copy(pVarResult, result);
296       }
297     } catch (HResultException e) {
298       // Log to the console for detailed examination.
299
//
300
e.printStackTrace();
301       ex = e;
302
303     } catch (InvocationTargetException JavaDoc e) {
304       // If we get here, it means an exception is being thrown from
305
// Java back into JavaScript
306

307       Throwable JavaDoc t = e.getTargetException();
308       ex = new HResultException(t);
309       ModuleSpace.setThrownJavaException(t);
310     } catch (Exception JavaDoc e) {
311       // Log to the console for detailed examination.
312
//
313
e.printStackTrace();
314       ex = new HResultException(e);
315     } finally {
316       // We allocated variants for all arguments, so we must dispose them all.
317
//
318
for (int i = 0; i < vArgs.length; ++i) {
319         if (vArgs[i] != null) {
320           vArgs[i].dispose();
321         }
322       }
323
324       if (result != null) {
325         result.dispose();
326       }
327     }
328
329     if (ex != null) {
330       // Set up an exception for IE to throw.
331
//
332
ex.fillExcepInfo(pExcepInfo);
333       return ex.getHResult();
334     }
335
336     return COM.S_OK;
337   }
338   // CHECKSTYLE_ON
339
}
340
Popular Tags