xref: /trunk/main/cli_ure/source/uno_bridge/cli_proxy.h (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef INCLUDED_CLI_PROXY_H
25 #define INCLUDED_CLI_PROXY_H
26 
27 #pragma warning(push, 1)
28 #include "uno/environment.hxx"
29 #pragma warning(pop)
30 #include "uno/mapping.hxx"
31 #include "uno/dispatcher.h"
32 #include "cli_bridge.h"
33 #include "cli_environment.h"
34 
35 #using <mscorlib.dll>
36 #using <cli_ure.dll>
37 
38 namespace srrp = System::Runtime::Remoting::Proxies;
39 namespace srrm = System::Runtime::Remoting::Messaging;
40 namespace srr = System::Runtime::Remoting;
41 namespace sr = System::Reflection;
42 namespace sc = System::Collections;
43 using namespace uno;
44 
45 namespace cli_uno
46 {
47 
48 public ref class UnoInterfaceInfo
49 {
50 public:
51     UnoInterfaceInfo(Bridge const * bridge, uno_Interface* unoI,
52                      typelib_InterfaceTypeDescription* td);
53     ~UnoInterfaceInfo();
54     uno_Interface * m_unoI; // wrapped interface
55     System::Type ^ m_type;
56     typelib_InterfaceTypeDescription* m_typeDesc;
57 
58     Bridge const* m_bridge;
59 };
60 
61 public ref class  UnoInterfaceProxy: public srrp::RealProxy,
62                                       public srr::IRemotingTypeInfo
63 {
64     /** used for IRemotingTypeInfo.TypeName
65      */
66     System::String ^ m_sTypeName;
67     /** The list is filled with UnoInterfaceInfo objects. The list can only
68         grow and elements are never changed. If an element was added it
69         must not be changed!
70      */
71     sc::ArrayList ^ m_listIfaces;
72     /** The number of UNO interfaces this proxy represents. It corresponds
73         to the number of elements in m_listIfaces.
74     */
75     int m_numUnoIfaces;
76     /** The list is filled with additional UnoInterfaceProxy object due
77         to aggregation via bridges.  Though the latter is strongly
78         discouraged, this has to be supported.
79     */
80     sc::ArrayList ^ m_listAdditionalProxies;
81     int m_nlistAdditionalProxies;
82 
83     UnoInterfaceInfo ^ findInfo( ::System::Type ^ type );
84 
85     Bridge const* m_bridge;
86     System::String ^ m_oid;
87 
88 #if OSL_DEBUG_LEVEL >= 2
89     /** The string contains all names of UNO interfaces which are
90         represented by this proxy. It is used to print out the interfaces
91         when this proxy dies. In the destructor it is not allowed to
92         access m_listIfaces or any other managed object.
93     */
94      rtl_uString * _sInterfaces;
95 //     /** Count of interfaces. Used in conjunction with _sInterfaces.
96 //      */
97     int _numInterfaces;
98 #endif
99 
100 public:
101 
102     /** Creates a proxy and registers it on the dot NET side.
103      */
104     static System::Object ^ create(Bridge * bridge,
105                                   uno_Interface * pUnoI,
106                                   typelib_InterfaceTypeDescription* pTd,
107                                   const rtl::OUString& oid);
108 
109     /** RealProxy::Invoke */
110     virtual srrm::IMessage ^ Invoke(srrm::IMessage ^ msg) override;
111 
112     /** Must be called from within a synchronized section.
113         Add only the interface if it is not already contained.
114         This method is called from the constructor and as a result
115         of IRemotingTypeInfo::CanCastTo
116      */
117     void addUnoInterface(uno_Interface* pUnoI,
118                          typelib_InterfaceTypeDescription* pTd);
119     ~UnoInterfaceProxy();
120 
121     /**
122      */
123     inline System::String ^ getOid()
124         { return m_oid; }
125 
126     //IRemotingTypeInfo ----------------------------------------------
127     virtual bool CanCastTo(System::Type ^ fromType, System::Object ^ o);
128 
129     // IRemotingTypeInfo::TypeName.  MC++ spelled a property as a pair of
130     // __property get_X/set_X methods; C++/CLI has property syntax, and the
131     // accessors have to be virtual because this implements an interface.
132     property System::String ^ TypeName
133     {
134         virtual System::String ^ get()
135         {
136             return m_sTypeName;
137         }
138         virtual void set(System::String ^ name)
139         {
140             m_sTypeName = name;
141         }
142     }
143 
144 
145 private:
146     UnoInterfaceProxy(
147         Bridge * bridge,
148         uno_Interface * pUnoI,
149         typelib_InterfaceTypeDescription* pTD,
150         const rtl::OUString& oid );
151 
152     static srrm::IMessage ^ constructReturnMessage(System::Object ^ retVal,
153                            cli::array< System::Object ^ > ^ outArgs,
154                            typelib_InterfaceMethodTypeDescription* mtd,
155                            srrm::IMessage ^ msg, System::Object ^ exc);
156 
157     static System::String ^ m_methodNameString =
158                            gcnew System::String("__MethodName");
159     static System::String ^ m_typeNameString = gcnew System::String("__TypeName");
160     static System::String ^ m_ArgsString = gcnew System::String("__Args");
161     static System::String ^ m_CallContextString =
162                            gcnew System::String("__CallContext");
163     static System::String ^ m_system_Object_String =
164                            gcnew System::String("System.Object");
165     static System::String ^ m_methodSignatureString =
166                            gcnew System::String("__MethodSignature");
167     static System::String ^ m_Equals_String =  gcnew System::String("Equals");
168     static System::String ^ m_GetHashCode_String =
169                            gcnew System::String("GetHashCode");
170     static System::String ^ m_GetType_String = gcnew System::String("GetType");
171     static System::String ^ m_ToString_String = gcnew System::String("ToString");
172 
173 protected:
174      srrm::IMessage ^ invokeObject(sc::IDictionary ^ properties,
175                                   srrm::LogicalCallContext ^ context,
176                                   srrm::IMethodCallMessage ^ mcm);
177 };
178 
179 
180 //Cannot make this __gc because a managed type cannot derive from unmanaged type
181 struct CliProxy: public uno_Interface
182 {
183     mutable oslInterlockedCount m_ref;
184     const Bridge* m_bridge;
185     const gcroot<System::Object ^> m_cliI;
186     gcroot<System::Type ^> m_type;
187     const com::sun::star::uno::TypeDescription m_unoType;
188     const gcroot<System::String ^> m_oid;
189     const rtl::OUString m_usOid;
190 
191     enum MethodKind {MK_METHOD = 0, MK_SET, MK_GET};
192     /** The array contains MethodInfos  of the cli object. Each one reflects an
193         implemented interface method of the interface for which this proxy was
194         created. The MethodInfos are from the object's method and not from the
195         interface type. That is, they can be used to invoke the methods. The
196         order of the MethodInfo objects corresponds to the order of the
197         interface methods (see member m_type). Position 0 contains the
198         MethodInfo of the first method of the interface which represents the
199         root of the inheritance chain. The last MethodInfo represents the last
200         method of the furthest derived interface.
201 
202         The array is completely initialized in the constructor of this object.
203 
204         When the uno_DispatchMethod is called for this proxy then it receives
205         a typelib_TypeDescription of the member which is either an attribute
206         (setter or getter) or method. After determining the position of the
207         method within the UNO interface one can use the position to obtain the
208         MethodInfo of the corresponding cli method. To obtain the index for the
209         m_arMethodInfos array the function position has to be decreased by 3.
210         This is becaus, the cli interface does not contain the XInterface
211         methods.
212     */
213     gcroot< cli::array< sr::MethodInfo ^ > ^ > m_arMethodInfos;
214 
215     /** This array is similar to m_arMethodInfos but it contains the MethodInfo
216         objects of the interface (not the object). When a call is made from uno
217         to cli then the uno method name is compared to the cli method name. The
218         cli method name can be obtained from the MethodInfo object in this
219         array. The name of the actual implemented method may not be the same as
220         the interface method.
221     */
222     gcroot< cli::array< sr::MethodInfo ^ > ^ > m_arInterfaceMethodInfos;
223 
224     /** Maps the position of the method in the UNO interface to the position of
225         the corresponding MethodInfo in m_arMethodInfos. The Uno position must
226         not include the XInterface methods. For example,
227         pos 0 = XInterface::queryInterface
228         pos 1 = XInterface::acquire
229         pos 2 = XInterface::release
230 
231         That is the real Uno position has to be deducted by 3. Then
232         arUnoPosToCliPos[pos] contains the index for m_arMethodInfos.
233 
234      */
235     gcroot< cli::array< System::Int32 > ^ > m_arUnoPosToCliPos;
236 
237     /** Count of inherited interfaces of the cli interface.
238      */
239     int m_nInheritedInterfaces;
240     /** Contains the number of methods of each interface.
241      */
242     gcroot< cli::array< System::Int32 > ^ > m_arInterfaceMethodCount;
243 
244     CliProxy( Bridge const* bridge, System::Object ^ cliI,
245                  typelib_TypeDescription const* pTD,
246                  const rtl::OUString& usOid);
247     ~CliProxy();
248 
249     static uno_Interface* create(Bridge const * bridge,
250                                  System::Object ^ cliI,
251                                  typelib_TypeDescription const * TD,
252                                  rtl::OUString const & usOid );
253 
254     /** Prepares an array (m_arMethoInfos) containing MethodInfo object of the
255         interface and all inherited interfaces. At index null is the first
256         method of the base interface and at the last position is the last method
257         of the furthest derived interface.
258         If a UNO call is received then one can determine the position of the
259         method (or getter or setter for an attribute) from the passed type
260         information. The position minus 3 (there is no XInterface in the cli
261         mapping) corresponds to the index of the cli interface method in the
262         array.
263     */
264     void makeMethodInfos();
265 
266     /**Obtains a MethodInfo which can be used to invoke the cli object.
267        Internally it maps nUnoFunctionPos to an index that is used to get the
268        corresponding MethodInfo object from m_arMethoInfos. The mapping table
269        is dynamically initialized. If the cli interface has no base interface
270        or exactly one then the mapping table is initialized in one go at the
271        first call. In all ensuing calls the MethodInfo object is immediately
272        retrieved through the mapping table.
273 
274        If the interface has more than one interface in its inheritance chain,
275        that is Type.GetInterfaces returns more than one Type, then the mapping
276        table is partially initialized. On the first call the mappings for the
277        methods of the belonging interface are created.
278 
279        The implementation assumes that the order of interface methods as
280        provided by InterfaceMapping.InterfaceMethods corresponds to the order
281        of methods in the interface declaration.
282 
283        @param nUnoFunctionPos
284        Position of the method in the uno interface.
285      */
286     sr::MethodInfo ^ getMethodInfo(int nUnoFunctionPos,
287                                   const rtl::OUString & usMethodName,
288                                   MethodKind mk);
289 
290     void SAL_CALL uno_DispatchMethod(
291         struct _uno_Interface * pUnoI,
292         const struct _typelib_TypeDescription * pMemberType,
293         void * pReturn,
294         void * pArgs[],
295         uno_Any ** ppException );
296 
297     inline void acquire() const;
298     inline void release() const;
299 };
300 }
301 #endif
302