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 __gc 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 __gc 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     srrm::IMessage* Invoke(srrm::IMessage* msg);
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     bool CanCastTo(System::Type* fromType, System::Object* o);
128 
129     __property System::String* get_TypeName()
130     {
131         return m_sTypeName;
132     }
133     __property void set_TypeName(System::String* name)
134     {
135         m_sTypeName = name;
136     }
137 
138 
139 private:
140     UnoInterfaceProxy(
141 		Bridge * bridge,
142 		uno_Interface * pUnoI,
143         typelib_InterfaceTypeDescription* pTD,
144 		const rtl::OUString& oid );
145 
146     static srrm::IMessage* constructReturnMessage(System::Object* retVal,
147                            System::Object* outArgs[],
148                            typelib_InterfaceMethodTypeDescription* mtd,
149                            srrm::IMessage* msg, System::Object* exc);
150 
151     static System::String* m_methodNameString =
152                            new System::String("__MethodName");
153     static System::String* m_typeNameString = new System::String("__TypeName");
154     static System::String* m_ArgsString = new System::String("__Args");
155     static System::String* m_CallContextString =
156                            new System::String("__CallContext");
157     static System::String* m_system_Object_String =
158                            new System::String("System.Object");
159     static System::String* m_methodSignatureString =
160                            new System::String("__MethodSignature");
161     static System::String* m_Equals_String =  new System::String("Equals");
162     static System::String* m_GetHashCode_String =
163                            new System::String("GetHashCode");
164     static System::String* m_GetType_String = new System::String("GetType");
165     static System::String* m_ToString_String = new System::String("ToString");
166 
167 protected:
168      srrm::IMessage* invokeObject(sc::IDictionary* properties,
169                                   srrm::LogicalCallContext* context,
170                                   srrm::IMethodCallMessage* mcm);
171 };
172 
173 
174 //Cannot make this __gc because a managed type cannot derive from unmanaged type
175 struct CliProxy: public uno_Interface
176 {
177     mutable oslInterlockedCount m_ref;
178     const Bridge* m_bridge;
179     const gcroot<System::Object*> m_cliI;
180     gcroot<System::Type*> m_type;
181     const com::sun::star::uno::TypeDescription m_unoType;
182     const gcroot<System::String*> m_oid;
183     const rtl::OUString m_usOid;
184 
185     enum MethodKind {MK_METHOD = 0, MK_SET, MK_GET};
186     /** The array contains MethodInfos  of the cli object. Each one reflects an
187         implemented interface method of the interface for which this proxy was
188         created. The MethodInfos are from the object's method and not from the
189         interface type. That is, they can be used to invoke the methods. The
190         order of the MethodInfo objects corresponds to the order of the
191         interface methods (see member m_type). Position 0 contains the
192         MethodInfo of the first method of the interface which represents the
193         root of the inheritance chain. The last MethodInfo represents the last
194         method of the furthest derived interface.
195 
196         The array is completely initialized in the constructor of this object.
197 
198         When the uno_DispatchMethod is called for this proxy then it receives
199         a typelib_TypeDescription of the member which is either an attribute
200         (setter or getter) or method. After determining the position of the
201         method within the UNO interface one can use the position to obtain the
202         MethodInfo of the corresponding cli method. To obtain the index for the
203         m_arMethodInfos array the function position has to be decreased by 3.
204         This is becaus, the cli interface does not contain the XInterface
205         methods.
206     */
207     gcroot<sr::MethodInfo*[]> m_arMethodInfos;
208 
209     /** This array is similar to m_arMethodInfos but it contains the MethodInfo
210         objects of the interface (not the object). When a call is made from uno
211         to cli then the uno method name is compared to the cli method name. The
212         cli method name can be obtained from the MethodInfo object in this
213         array. The name of the actual implemented method may not be the same as
214         the interface method.
215     */
216     gcroot<sr::MethodInfo*[]> m_arInterfaceMethodInfos;
217 
218     /** Maps the position of the method in the UNO interface to the position of
219         the corresponding MethodInfo in m_arMethodInfos. The Uno position must
220         not include the XInterface methods. For example,
221         pos 0 = XInterface::queryInterface
222         pos 1 = XInterface::acquire
223         pos 2 = XInterface::release
224 
225         That is the real Uno position has to be deducted by 3. Then
226         arUnoPosToCliPos[pos] contains the index for m_arMethodInfos.
227 
228      */
229     gcroot<System::Int32[]> m_arUnoPosToCliPos;
230 
231     /** Count of inherited interfaces of the cli interface.
232      */
233     int m_nInheritedInterfaces;
234     /** Contains the number of methods of each interface.
235      */
236     gcroot<System::Int32[]> m_arInterfaceMethodCount;
237 
238     CliProxy( Bridge const* bridge, System::Object* cliI,
239                  typelib_TypeDescription const* pTD,
240                  const rtl::OUString& usOid);
241     ~CliProxy();
242 
243     static uno_Interface* create(Bridge const * bridge,
244                                  System::Object* cliI,
245                                  typelib_TypeDescription const * TD,
246                                  rtl::OUString const & usOid );
247 
248     /** Prepares an array (m_arMethoInfos) containing MethodInfo object of the
249         interface and all inherited interfaces. At index null is the first
250         method of the base interface and at the last position is the last method
251         of the furthest derived interface.
252         If a UNO call is received then one can determine the position of the
253         method (or getter or setter for an attribute) from the passed type
254         information. The position minus 3 (there is no XInterface in the cli
255         mapping) corresponds to the index of the cli interface method in the
256         array.
257     */
258     void makeMethodInfos();
259 
260     /**Obtains a MethodInfo which can be used to invoke the cli object.
261        Internally it maps nUnoFunctionPos to an index that is used to get the
262        corresponding MethodInfo object from m_arMethoInfos. The mapping table
263        is dynamically initialized. If the cli interface has no base interface
264        or exactly one then the mapping table is initialized in one go at the
265        first call. In all ensuing calls the MethodInfo object is immediately
266        retrieved through the mapping table.
267 
268        If the interface has more then one interface in its inheritance chain,
269        that is Type.GetInterfaces return more then one Type, then the mapping
270        table is partially initiallized. On the first call the mappings for the
271        methods of the belonging interface are created.
272 
273        The implementation assumes that the order of interface methods as
274        provided by InterfaceMapping.InterfaceMethods corresponds to the order
275        of methods in the interface declaration.
276 
277        @param nUnoFunctionPos
278        Position of the method in the uno interface.
279      */
280     sr::MethodInfo* getMethodInfo(int nUnoFunctionPos,
281                                   const rtl::OUString & usMethodName,
282                                   MethodKind mk);
283 
284     void SAL_CALL uno_DispatchMethod(
285         struct _uno_Interface * pUnoI,
286         const struct _typelib_TypeDescription * pMemberType,
287         void * pReturn,
288         void * pArgs[],
289         uno_Any ** ppException );
290 
291     inline void acquire() const;
292     inline void release() const;
293 };
294 }
295 #endif
296