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 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