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