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