1 | /* |
2 | * $Id: ComObject.java,v 1.3 2006/03/07 17:52:26 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 | package com.moesol.bindings.platform_sdk.component_services; |
13 | |
14 | import java.nio.ByteBuffer; |
15 | |
16 | |
17 | |
18 | public class ComObject implements IUnknown { |
19 | |
20 | /** This field helps avoid most name conflicts and supports aggregation. */ |
21 | protected ComIUnknown m_iunknown_support; |
22 | |
23 | /** |
24 | * Initializes the COM interface map based on refelection. |
25 | * Each interface that this class implements that has IUnknown |
26 | * as a super class is included. For more control over the |
27 | * COM interface map used by the default implementation of QueryInterface |
28 | * see {@link #ComObjectRoot(boolean)}. |
29 | */ |
30 | protected ComObject() { |
31 | this(true); |
32 | } |
33 | |
34 | /** |
35 | * If {@code reflect_com_map} is true then initializes the COM |
36 | * interface based on reflection. Otherwise, the COM interface map is empty |
37 | * and must be filled in by the subclass. |
38 | * |
39 | * @param reflect_com_map |
40 | */ |
41 | protected ComObject(boolean reflect_com_map) { |
42 | ComIUnknownImpl unk_impl = new ComIUnknownImpl(this); |
43 | m_iunknown_support = unk_impl; |
44 | |
45 | if (reflect_com_map) { |
46 | unk_impl.reflectComMap(); |
47 | } |
48 | } |
49 | |
50 | // |
51 | // TODO: Optimization. If a java client is calling QueryInterface |
52 | // we might as well just return the java interface. The current |
53 | // implementation returns a java forward COM wrapper to a reverse COM |
54 | // wrapper. |
55 | // |
56 | |
57 | /** |
58 | * Provides an implementation of IUnknown.QueryInterface. |
59 | * |
60 | * @param out_iface See {@link IUnknown#QueryInterface(Object[])} |
61 | */ |
62 | public void QueryInterface(Object[] out_iface) { |
63 | InterfaceBuilder ib = new InterfaceBuilder(out_iface); |
64 | out_iface[0] = m_iunknown_support.queryInterface(ib.getIID()); |
65 | } |
66 | |
67 | /** |
68 | * Provides an implementation of IUnknown.QueryInterface |
69 | * |
70 | * @param iface_class See {@link IUnknown#QueryInterface(Class)} |
71 | */ |
72 | public IUnknown QueryInterface(Class iface_class) { |
73 | InterfaceBuilder ib = new InterfaceBuilder(iface_class); |
74 | return m_iunknown_support.queryInterface(ib.getIID()); |
75 | } |
76 | |
77 | // |
78 | // TODO: design consideration. FinalRelease adds a possible method name |
79 | // conflict. Instead why not have the reverse COM call Release for each |
80 | // release and then allow implementations to get the current reference count |
81 | // and see if the reference count has gone to zero? |
82 | // |
83 | |
84 | public int Release() { |
85 | // For java we rely on the GC |
86 | return 1; |
87 | } |
88 | |
89 | /** |
90 | * Override if you want to know when all external COM interfaces |
91 | * have been freed. |
92 | */ |
93 | protected void FinalRelease() { |
94 | // do nothing |
95 | } |
96 | |
97 | /** |
98 | * @param java_sink |
99 | * @return ComObjectRoot for {@code java_sink}. |
100 | */ |
101 | private static ComObject recoverComObject(Object java_sink) { |
102 | return (ComObject)java_sink; |
103 | } |
104 | |
105 | /** |
106 | * Called by native side when IUnknown::QueryInterface is called |
107 | * |
108 | * @param object_sink |
109 | * @param bb_iid |
110 | * @return IUnknown |
111 | */ |
112 | static IUnknown native_QueryInterface(Object object_sink, ByteBuffer bb_iid) { |
113 | ComObject com_object = recoverComObject(object_sink); |
114 | GUID iid = new GUID(bb_iid); |
115 | try { |
116 | return com_object.m_iunknown_support.queryInterface(iid); |
117 | } catch (COMException ce) { |
118 | // |
119 | // Quiet down exceptions from failed QueryInterface calls |
120 | // since it is quite common and not necessarily an error |
121 | // for a QI call to return E_NOINTERFACE. |
122 | // |
123 | if (ce.getHRESULT() == HRESULT.E_NOINTERFACE) { |
124 | return null; |
125 | } |
126 | throw ce; |
127 | } |
128 | } |
129 | |
130 | /** |
131 | * Called by native side when IUnknown::AddRef is called |
132 | * @param object_sink |
133 | * @return new ref count. |
134 | */ |
135 | static long native_AddRef(Object object_sink) { |
136 | ComObject com_object = recoverComObject(object_sink); |
137 | return com_object.m_iunknown_support.addRef(); |
138 | } |
139 | |
140 | /** |
141 | * Called by native side when IUnknown::Release is called. |
142 | * @param object_sink |
143 | * @return new ref count. |
144 | */ |
145 | static long native_Release(Object object_sink) { |
146 | ComObject com_object = recoverComObject(object_sink); |
147 | return com_object.m_iunknown_support.release(); |
148 | } |
149 | } |