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