EMMA Coverage Report (generated Mon Mar 20 21:34:30 PST 2006)
[all classes][com.moesol.bindings.platform_sdk.component_services]

COVERAGE SUMMARY FOR SOURCE FILE [COM.java]

nameclass, %method, %block, %line, %
COM.java100% (1/1)77%  (24/31)57%  (345/601)60%  (94.4/157)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class COM100% (1/1)77%  (24/31)57%  (345/601)60%  (94.4/157)
COM (): void 0%   (0/1)0%   (0/3)0%   (0/1)
OleCreatePropertyFrame (HWND, int, int, String, IUnknown [], GUID [], int, in... 0%   (0/1)0%   (0/30)0%   (0/5)
addListener (IUnknown, IUnknown, GUID): int 0%   (0/1)0%   (0/8)0%   (0/2)
convertGuidArray (GUID []): GUID$Array 0%   (0/1)0%   (0/27)0%   (0/5)
disableApartmentChecking (IUnknown): void 0%   (0/1)0%   (0/6)0%   (0/3)
recordApartment (IUnknown): void 0%   (0/1)0%   (0/6)0%   (0/3)
removeListener (IUnknown, IUnknown, GUID): void 0%   (0/1)0%   (0/8)0%   (0/3)
dllGetClassObject (ByteBuffer, ByteBuffer): IUnknown 100% (1/1)38%  (29/77)33%  (6/18)
findIIDField (Class): Field 100% (1/1)40%  (4/10)33%  (1/3)
extractIID (Field): GUID 100% (1/1)45%  (5/11)33%  (1/3)
checkSafety (): void 100% (1/1)48%  (11/23)79%  (5.5/7)
mapExceptionToHRESULT (Throwable): int 100% (1/1)57%  (46/81)52%  (16/31)
getBindingsPath (): String 100% (1/1)58%  (7/12)75%  (3/4)
OleInitialize (): int 100% (1/1)62%  (8/13)80%  (4/5)
OleUninitialize (): void 100% (1/1)63%  (17/27)86%  (6/7)
CoCreateInstance (GUID, IUnknown, int, Object []): int 100% (1/1)71%  (34/48)77%  (7.7/10)
<static initializer> 100% (1/1)71%  (20/28)87%  (3.5/4)
CoCreateGuid (): GUID 100% (1/1)72%  (13/18)80%  (4/5)
findComServerValue (GUID, String): String 100% (1/1)77%  (46/60)73%  (5.9/8)
Invoke (IDispatch, int, GUID, int, short, Object [], Object []): void 100% (1/1)100% (12/12)100% (3/3)
computeStringForJavaException (Throwable): String 100% (1/1)100% (17/17)100% (5/5)
decInitCount (): void 100% (1/1)100% (5/5)100% (2/2)
extractIID (IUnknown): GUID 100% (1/1)100% (5/5)100% (1/1)
gc (): void 100% (1/1)100% (16/16)100% (6/6)
getGenericSinkInstanceCount (): int 100% (1/1)100% (2/2)100% (1/1)
getUnreleasedCount (): int 100% (1/1)100% (2/2)100% (1/1)
getVtableThunkCount (): int 100% (1/1)100% (2/2)100% (1/1)
incInitCount (): void 100% (1/1)100% (5/5)100% (2/2)
uncaughtJavaException (Throwable): int 100% (1/1)100% (8/8)100% (2/2)
wrapJavaWithNativeDispatch (IDispatch, Object []): void 100% (1/1)100% (17/17)100% (4/4)
wrapJavaWithVtableInterface (ComObject, Object []): void 100% (1/1)100% (14/14)100% (3/3)

1/*
2 * $Id: COM.java,v 1.38 2006/03/11 23:29:15 hastings Exp $
3 *
4 * (c) Copyright, Moebius Solutions, Inc., 2004
5 *
6 *                       All Rights Reserved
7 *
8 * This material may be reproduced by or for the U. S. Government
9 * pursuant to the copyright license under the clause at
10 * DFARS 252.227-7014 (OCT 2001).
11 */
12 
13package com.moesol.bindings.platform_sdk.component_services;
14 
15import java.io.PrintWriter;
16import java.io.StringWriter;
17import java.lang.reflect.Field;
18import java.net.MalformedURLException;
19import java.nio.ByteBuffer;
20import java.util.logging.Level;
21import java.util.logging.Logger;
22import java.util.prefs.BackingStoreException;
23 
24import com.moesol.bindings.NativeLibraryLoader;
25import com.moesol.bindings.platform_sdk.windows_api.HKEY;
26import com.moesol.bindings.platform_sdk.windows_api.HWND;
27import com.moesol.bindings.platform_sdk.windows_api.PlatformSDK;
28import com.moesol.bindings.platform_sdk.windows_api.Win32Exception;
29 
30/**
31 * @author robert
32 */
33public class COM {
34    private static final Logger logger = Logger.getLogger(COM.class.getName());
35    
36        static {
37                NativeLibraryLoader.loadLibrary("com_moesol_bindings");
38        }
39 
40        /** See CoCreateInstance */
41        public static final int CLSCTX_INPROC_SERVER = 0x1;
42        /** See CoCreateInstance */
43        public static final int CLSCTX_INPROC_HANDLER = 0x2;
44        /** See CoCreateInstance */
45        public static final int CLSCTX_LOCAL_SERVER = 0x4;
46        /** See CoCreateInstance */
47        public static final int CLSCTX_INPROC_SERVER16 = 0x8;
48        /** See CoCreateInstance */
49        public static final int CLSCTX_REMOTE_SERVER = 0x10;
50        /** See CoCreateInstance */
51        public static final int CLSCTX_INPROC_HANDLER16 = 0x20;
52        /** See CoCreateInstance, apparently CLSCTX_INPROC_SERVERX86 was deprecated */
53        public static final int CLSCTX_RESERVED1            = 0x40;
54        // public static final int CLSCTX_INPROC_SERVERX86 = 0x40;
55        /** See CoCreateInstance, apparently CLSCTX_INPROC_HANDLERX86 was deprecated */
56    public static final int CLSCTX_RESERVED2            = 0x80;
57        // public static final int CLSCTX_INPROC_HANDLERX86 = 0x80;
58        /** See CoCreateInstance, apparently CLSCTX_ESERVER_HANDLER was deprecated */
59    public static final int CLSCTX_RESERVED3            = 0x100;
60        // public static final int CLSCTX_ESERVER_HANDLER = 0x100;
61        /** See CoCreateInstance */
62        public static final int CLSCTX_RESERVED4            = 0x200;
63        /** See CoCreateInstance */
64        public static final int CLSCTX_NO_CODE_DOWNLOAD     = 0x400;
65        /** See CoCreateInstance */
66        public static final int CLSCTX_RESERVED5            = 0x800;
67        /** See CoCreateInstance */
68        public static final int CLSCTX_NO_CUSTOM_MARSHAL    = 0x1000;
69        /** See CoCreateInstance */
70        public static final int CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000;
71        /** See CoCreateInstance */
72        public static final int CLSCTX_NO_FAILURE_LOG       = 0x4000;
73        /** See CoCreateInstance */
74        public static final int CLSCTX_DISABLE_AAA          = 0x8000;
75        /** See CoCreateInstance */
76        public static final int CLSCTX_ENABLE_AAA           = 0x10000;
77        /** See CoCreateInstance */
78        public static final int CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000;
79 
80            
81        /** See CoCreateInstance */
82        public static final int CLSCTX_INPROC = (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER);
83        /** See CoCreateInstance */
84        public static final int CLSCTX_ALL = (CLSCTX_INPROC_SERVER
85                        | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER);
86        /** See CoCreateInstance */
87        public static final int CLSCTX_SERVER = (CLSCTX_INPROC_SERVER
88                        | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER);
89        /** See CoCreateInstance */
90        public static final int CLSCTX_LOCAL = (CLSCTX_INPROC_SERVER
91                        | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER);
92        
93        
94        /** See InprocServer32 in MSDN */
95        public static final String ThreadingModel_Apartment = "Apartment"; 
96        /** See InprocServer32 in MSDN */
97        public static final String ThreadingModel_Both = "Both";
98        /** See InprocServer32 in MSDN */
99        public static final String ThreadingModel_Free = "Free"; 
100        /** See InprocServer32 in MSDN */
101        public static final String ThreadingModel_Neutral = "Neutral";
102        
103        /**
104         * Adds a COM event listener to source. Internally, addListener
105     * uses the IConnectPointContainer of the source to find
106     * the IConnectionPoint and the add listener.
107         *
108         * @param source
109         * @param listener
110         * @param diid
111         */
112        public static int addListener(IUnknown source, IUnknown listener, GUID diid) {
113                IUnknown.Jni unk_jni = (IUnknown.Jni)source;
114                return IUnknown.Jni.MoeSolInternal.addListener(unk_jni, listener, diid);
115        }
116        
117        /**
118         * Removes a COM event listener from source.
119         * 
120         * @param source
121         * @param listener
122         * @param diid
123         */
124        public static void removeListener(IUnknown source, IUnknown listener, GUID diid) {
125                IUnknown.Jni unk_jni = (IUnknown.Jni)source;
126                IUnknown.Jni.MoeSolInternal.removeListener(unk_jni, listener, diid);
127        }
128        
129        /**
130         * The method should probably have default access instead of public. It is kept public
131         * for backward compatibility with older releases. This method will be marked deprecated
132         * with tlb2java automatically wraps java interfaces with native proxies.
133         * 
134         * @param java_sink
135         * @param out_iface
136         */
137        public static void wrapJavaWithNativeDispatch(IDispatch java_sink, Object[] out_iface) {
138                InterfaceBuilder ib = new InterfaceBuilder(out_iface);
139                jni_wrap(java_sink, ib.getIIDBytes(), ib.getResult());
140                out_iface[0] = ib.getResult();
141        }
142        
143        /**
144         * Note that tlb2java should auto-wrap when a java interface is passed in and it
145         * is not vtable based!
146         */
147        public static void wrapJavaWithVtableInterface(ComObject java_sink, Object[] out_iface) {
148                InterfaceBuilder ib = new InterfaceBuilder(out_iface);
149                out_iface[0] = java_sink.m_iunknown_support.queryInterface(ib.getIID());
150        }
151        
152        /**
153         * See CoCreateInstance
154         * 
155         * @param rclsid
156         * @param pUnkOuter
157         * @param dwClsContext
158         * @param out_iface
159         * 
160         * @return HRESULT
161         */
162        public static int CoCreateInstance(GUID rclsid, IUnknown pUnkOuter,
163                        int dwClsContext, Object[] out_iface) 
164        {
165                out_iface[0] = null;
166                if (pUnkOuter != null && !(pUnkOuter instanceof IUnknown.Jni)) {
167                        throw new COMException("Java objects cannot be outer unknown for aggregation", HRESULT.E_INVALIDARG);
168                }
169                IUnknown.Jni outer = (IUnknown.Jni)pUnkOuter;
170                
171                InterfaceBuilder ib = new InterfaceBuilder(out_iface);
172                int hr = jni_CoCreateInstance(rclsid._getStructureBytes(), outer,
173                                dwClsContext, ib.getIIDBytes(), ib.getResult());
174                if (HRESULT.FAILED(hr)) {
175                        throw new COMException(hr);
176                }
177                out_iface[0] = ib.getResult();
178                return hr;
179        }
180        
181        public static GUID CoCreateGuid() {
182                GUID guid = new GUID();
183                int hr = jni_CoCreateGuid(guid._getStructureBytes());
184                if (HRESULT.FAILED(hr)) {
185                        throw new COMException(hr);
186                }
187                return guid;
188        }
189        
190        public static int OleCreatePropertyFrame(
191                          HWND hwndOwner,    //Parent window of property sheet dialog box
192                          int x,            //Horizontal position for dialog box
193                          int y,            //Vertical position for dialog box
194                          String lpszCaption,
195                                             //Pointer to the dialog box caption
196                          IUnknown[] objects,
197                                             //Pointer to the objects for property sheet
198                          GUID[] lpPageClsID,
199                                             //Array of CLSIDs for each property page
200                          int lcid,         //Locale identifier for property sheet locale
201                          int dwReserved,  //Reserved
202                          Object lpvReserved //Reserved
203                        ) 
204        {
205                GUID.Array array = convertGuidArray(lpPageClsID);
206                
207                int hr = jni_OleCreatePropertyFrame(HWND._safeGetHandle(hwndOwner), x, y, lpszCaption, 
208                                objects.length, objects,
209                                lpPageClsID.length, array._getByteBuffer(), 
210                                lcid, dwReserved, lpvReserved);
211                if (HRESULT.FAILED(hr)) {
212                        throw new COMException(hr);
213                }
214                return hr;
215        }
216 
217        private static GUID.Array convertGuidArray(GUID[] lpPageClsID) {
218                ByteBuffer guid_bb = ByteBuffer.allocate(GUID.sizeof() * lpPageClsID.length);
219                GUID.Array array = new GUID.Array(guid_bb);
220                for (int i = 0; i < lpPageClsID.length; i++) {
221                        array.put(i, lpPageClsID[i]);
222                }
223                return array;
224        }
225 
226    
227        /**
228         * Turn off apartment thread checking for unk.
229         * @param unk
230         */
231        public static void disableApartmentChecking(IUnknown unk) {
232                IUnknown.Jni unk_jni = (IUnknown.Jni)unk;
233                IUnknown.Jni.MoeSolInternal.disableApartmentChecking(unk_jni);
234        }
235        
236        /**
237         * Turn on apartment thread checking for unk.
238         * @param unk
239         */
240        public static void recordApartment(IUnknown unk) {
241                IUnknown.Jni unk_jni = (IUnknown.Jni)unk;
242                IUnknown.Jni.MoeSolInternal.recordApartment(unk_jni);
243        }
244        
245        /**
246         * See OleInitialize. You do not need to call this method if you use an 
247         * {@code OleThread}.
248         * @return HRESULT
249         * @see OleThread
250         */
251        public static int OleInitialize() {
252                int hr = jni_OleInitialize();
253                if (HRESULT.FAILED(hr)) {
254                        throw new COMException(hr);
255                }
256                incInitCount();
257                return hr;
258        }
259        /**
260         * See OleUninitialize. You do not need to call this method if you use an
261         * {@code OleThread}.
262         * @see OleThread
263         */
264        public static void OleUninitialize() {
265                synchronized (COM.class) {
266                        decInitCount();
267                        if (g_init_count == 0) {
268                                checkSafety();
269                        }
270                }
271                jni_OleUninitialize();
272        }
273        private static void checkSafety() {
274                if (COM.getUnreleasedCount() == 0) {
275                        // Fast exit
276                        return;
277                }
278                
279                COM.gc();
280                
281                if (COM.getUnreleasedCount() != 0) {
282                        logger.log(Level.SEVERE,
283                                        "Unreleased ({0}) interfaces may crash JVM.", new Integer(
284                                                        COM.getUnreleasedCount()));
285                }
286                assert(COM.getUnreleasedCount() == 0);
287        }
288 
289        /**
290         * Call System.gc in a loop for upto one second to 
291         * release all COM interfaces.
292         * Since System.gc may not always call finalize on all finalizable
293         * objects we loop for upto one second calling System.gc and Thread.yield.
294         * If the unreleased count goes to zero return immediately.
295         */
296        public static void gc() {
297                long start_millis = System.currentTimeMillis();
298                long end_millis = start_millis + 1000;
299                while (COM.getUnreleasedCount() > 0 && (System.currentTimeMillis() < end_millis)) {
300                        System.gc();
301                        Thread.yield();
302                }
303        }
304 
305        static private long g_init_count;
306        static private synchronized void incInitCount() {
307                g_init_count++;
308        }
309        static private synchronized void decInitCount() {
310                g_init_count--;
311        }
312        static private native int jni_OleInitialize();
313        static private native void jni_OleUninitialize();
314        static private native int jni_CoCreateGuid(byte[] guidBytes);
315        static private native int jni_OleCreatePropertyFrame(
316                          long hwndOwner, int x, int y,
317                          String lpszCaption, int count_objects, IUnknown[] objects, int count_guids, ByteBuffer guid_bb,
318                          int lcid, int dwReserved, Object lpvReserved);
319        
320        static private native int jni_CoCreateInstance(byte[] rclsid, IUnknown.Jni pUnkOuter,
321                        int dwClsContext, byte[] riid, IUnknown out_ppv);
322        static private native void jni_wrap(IDispatch java_sink, byte[] diid, IUnknown out_ppv);
323        
324 
325        /**
326         * Get the IID of the most derived interface that <code>unk</code>
327         * represents. Used in the unit tests to confirm QI is working correctly.
328         * 
329         * @param unk
330         * 
331         * @return a GUID that is the IID of the most derived interface that
332         * <code>unk</code> represents.
333         */
334        public static GUID extractIID(IUnknown unk) {
335                return extractIID(findIIDField(unk.getClass()));
336        }
337        private static GUID extractIID(Field iid_field) {
338                try {
339                        return (GUID) iid_field.get(null);
340                } catch (Exception e) {
341                        throw new RuntimeException(e);
342                }
343        }
344        private static Field findIIDField(Class iface_type) {
345                try {
346                        return iface_type.getField("IID");
347                } catch (Exception e) {
348                        throw new RuntimeException(e);
349                }
350        }
351 
352    /**
353         * The unreleased count is the count of all IUnknown and subclasses that
354         * have native COM interfaces attached. To free these native COM interfaces
355         * the IUnknown.Release must be called.
356         * 
357         * @return Count of all COM interfaces that have not been released.
358         */
359    public static int getUnreleasedCount() {
360        return IUnknown.Jni.MoeSolInternal.getUnreleasedCount();
361    }
362    
363    /**
364     * @return the number of generic sinks that have not been released.
365     */
366    public static int getGenericSinkInstanceCount() {
367            return _getGenericSinkInstanceCount();
368    }
369    private static native int _getGenericSinkInstanceCount();
370 
371    /**
372     * @return the number of thunks that have not been relesed.
373     */
374    public static int getVtableThunkCount() {
375        return jni_getVtableThunkCount();
376    }
377    private static native int jni_getVtableThunkCount();
378    
379    static IUnknown dllGetClassObject(ByteBuffer bb_clsid, ByteBuffer bb_iid) {
380            GUID clsid = new GUID(bb_clsid);
381            GUID iid = new GUID(bb_iid);
382                try {
383                        String class_name = findComServerValue(clsid, "Class");
384                        Class server_class = ComInProcGroups.instance().getClass(clsid, class_name);
385                        ComClassFactory factory = new ComClassFactory(server_class);
386                        return factory.m_iunknown_support.queryInterface(iid);
387                } catch (ClassCastException e) {
388                        logger.log(Level.INFO, "caught", e);
389                        throw new COMException(COM.mapExceptionToHRESULT(e));
390                } catch (ClassNotFoundException e) {
391                        logger.log(Level.INFO, "caught", e);
392                        throw new COMException(COM.mapExceptionToHRESULT(e));
393                } catch (MalformedURLException e) {
394                        logger.log(Level.INFO, "caught", e);
395                        throw new COMException(COM.mapExceptionToHRESULT(e));
396                } catch (BackingStoreException e) {
397                        logger.log(Level.INFO, "caught", e);
398                        throw new COMException(COM.mapExceptionToHRESULT(e));
399                }
400    }
401    
402    static String findComServerValue(GUID clsid, String value_name) {
403            try {
404                    HKEY out_key[] = { null };
405                    PlatformSDK.RegOpenKeyEx(PlatformSDK.HKEY_CLASSES_ROOT, "CLSID\\" + clsid.toString() + "\\InProcServer32", 0, PlatformSDK.KEY_READ, out_key);
406                    try {
407                            String[] out_value = { null };
408                        PlatformSDK.RegQueryValue(out_key[0], value_name, out_value);
409                        return out_value[0];
410                    } finally {
411                            PlatformSDK.RegCloseKey(out_key[0]);
412                    }
413            } catch (Win32Exception we) {
414                    throw new COMException(mapExceptionToHRESULT(we));
415            }
416    }
417    
418    /**
419     * @return The full path to the com_moesol_bindings.dll.
420     */
421        static String getBindingsPath() {
422            String r = jni_getBindingsPath("com_moesol_bindings.dll");
423            if (r == null) {
424                    throw new Win32Exception(PlatformSDK.GetLastError());
425            }
426            return r;
427    }
428    
429    private static native String jni_getBindingsPath(String module);
430    
431    /**
432     * Called by JNI code to get the best HRESULT for {@code t}.
433     *  
434     * @param t
435     * @return HRESULT
436     */
437    static int uncaughtJavaException(Throwable t) {
438            logger.log(Level.FINE, "Java COM component threw exception", t);
439            return mapExceptionToHRESULT(t);
440    }
441    
442    /**
443     * Called by JNI code to get the stack track for {@code t}
444     * 
445     * @param t
446     * @return String representation of the stack trace for {@code t}
447     */
448    static String computeStringForJavaException(Throwable t) {
449            StringWriter sw = new StringWriter();
450            PrintWriter pw = new PrintWriter(sw);
451            t.printStackTrace(pw);
452            pw.close();
453            return sw.toString();
454    }
455 
456        /**
457         * @param t
458         * @return best HRESULT based on {@code t}.
459         */
460        public static int mapExceptionToHRESULT(Throwable t) {
461                if (t instanceof OutOfMemoryError) {
462                    return HRESULT.E_OUTOFMEMORY;
463            } else if (t instanceof UnsupportedOperationException) {
464                    return HRESULT.E_NOTIMPL;
465            } else if (t instanceof IllegalAccessException) {
466                    return HRESULT.E_ACCESSDENIED;
467            } else if (t instanceof IllegalArgumentException) {
468                    return HRESULT.E_INVALIDARG;
469            } else if (t instanceof NullPointerException) {
470                    return HRESULT.E_POINTER;
471            } else if (t instanceof IllegalStateException) {
472                    return HRESULT.E_UNEXPECTED;
473            } else if (t instanceof ClassCastException) {
474                    return HRESULT.DISP_E_TYPEMISMATCH;
475            } else if (t instanceof InstantiationException) {
476                    return HRESULT.CO_E_CLASS_CREATE_FAILED;
477            } else if (t instanceof IllegalAccessException) {
478                    return HRESULT.E_ACCESSDENIED;
479            } else if (t instanceof ClassNotFoundException) {
480                    return HRESULT.CLASS_E_CLASSNOTAVAILABLE;
481            } else if (t instanceof Win32Exception) {
482                    Win32Exception we = (Win32Exception)t;
483                    return HRESULT.HRESULT_FROM_WIN32(we.getLRESULT());
484            } else if (t instanceof MalformedURLException) {
485                    return HRESULT.MK_E_SYNTAX;
486            } else if (t instanceof BackingStoreException) {
487                    return HRESULT.REGDB_E_READREGDB;
488            } else if (t instanceof COMException) {
489                    COMException ce = (COMException)t;
490                    return ce.getHRESULT();
491            }
492                
493            return HRESULT.E_FAIL;
494        }
495        
496        public static void Invoke(IDispatch callee, int dispIdMember, GUID riid, int lcid, short wFlags,
497                           Object[] dispParams, Object[] varResult)
498        {
499                IDispatch.Jni inner_jni = (IDispatch.Jni) callee;
500                inner_jni.Invoke(dispIdMember, riid, lcid, wFlags, dispParams, varResult);
501}
502}

[all classes][com.moesol.bindings.platform_sdk.component_services]
EMMA 2.0.5312 (C) Vladimir Roubtsov