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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_cppu.hxx" 30 31 #include "Proxy.hxx" 32 33 #include "sal/alloca.h" 34 #include "uno/dispatcher.h" 35 #include "typelib/typedescription.hxx" 36 #include "cppu/EnvDcp.hxx" 37 38 39 //#define LOG_LIFECYCLE_Proxy 40 #ifdef LOG_LIFECYCLE_Proxy 41 # include <iostream> 42 # define LOG_LIFECYCLE_Proxy_emit(x) x 43 44 #else 45 # define LOG_LIFECYCLE_Proxy_emit(x) 46 47 #endif 48 49 50 using namespace com::sun::star; 51 52 53 static bool relatesToInterface(typelib_TypeDescription * pTypeDescr) 54 SAL_THROW( () ) 55 { 56 switch (pTypeDescr->eTypeClass) 57 { 58 // case typelib_TypeClass_TYPEDEF: 59 case typelib_TypeClass_SEQUENCE: 60 { 61 switch (((typelib_IndirectTypeDescription *)pTypeDescr)->pType->eTypeClass) 62 { 63 case typelib_TypeClass_INTERFACE: 64 case typelib_TypeClass_UNION: // might relate to interface 65 case typelib_TypeClass_ANY: // might relate to interface 66 return true; 67 case typelib_TypeClass_SEQUENCE: 68 case typelib_TypeClass_STRUCT: 69 case typelib_TypeClass_EXCEPTION: 70 { 71 typelib_TypeDescription * pTD = 0; 72 TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType ); 73 bool bRel = relatesToInterface( pTD ); 74 TYPELIB_DANGER_RELEASE( pTD ); 75 return bRel; 76 } 77 default: 78 ; 79 } 80 return false; 81 } 82 case typelib_TypeClass_STRUCT: 83 case typelib_TypeClass_EXCEPTION: 84 { 85 // ...optimized... to avoid getDescription() calls! 86 typelib_CompoundTypeDescription * pComp = (typelib_CompoundTypeDescription *)pTypeDescr; 87 typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs; 88 for ( sal_Int32 nPos = pComp->nMembers; nPos--; ) 89 { 90 switch (pTypes[nPos]->eTypeClass) 91 { 92 case typelib_TypeClass_INTERFACE: 93 case typelib_TypeClass_UNION: // might relate to interface 94 case typelib_TypeClass_ANY: // might relate to interface 95 return true; 96 // case typelib_TypeClass_TYPEDEF: 97 case typelib_TypeClass_SEQUENCE: 98 case typelib_TypeClass_STRUCT: 99 case typelib_TypeClass_EXCEPTION: 100 { 101 typelib_TypeDescription * pTD = 0; 102 TYPELIB_DANGER_GET( &pTD, pTypes[nPos] ); 103 bool bRel = relatesToInterface( pTD ); 104 TYPELIB_DANGER_RELEASE( pTD ); 105 if (bRel) 106 return true; 107 } 108 default: 109 ; 110 } 111 } 112 if (pComp->pBaseTypeDescription) 113 return relatesToInterface( (typelib_TypeDescription *)pComp->pBaseTypeDescription ); 114 break; 115 } 116 case typelib_TypeClass_UNION: // might relate to interface 117 case typelib_TypeClass_ANY: // might relate to interface 118 case typelib_TypeClass_INTERFACE: 119 return true; 120 121 default: 122 ; 123 } 124 return false; 125 } 126 127 extern "C" { static void SAL_CALL s_Proxy_dispatch( 128 uno_Interface * pUnoI, 129 typelib_TypeDescription const * pMemberType, 130 void * pReturn, 131 void * pArgs[], 132 uno_Any ** ppException) 133 SAL_THROW_EXTERN_C() 134 { 135 Proxy * pThis = static_cast<Proxy *>(pUnoI); 136 137 typelib_MethodParameter param; 138 sal_Int32 nParams = 0; 139 typelib_MethodParameter * pParams = 0; 140 typelib_TypeDescriptionReference * pReturnTypeRef = 0; 141 // sal_Int32 nOutParams = 0; 142 143 switch (pMemberType->eTypeClass) 144 { 145 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 146 if (pReturn) 147 { 148 pReturnTypeRef = 149 ((typelib_InterfaceAttributeTypeDescription *) 150 pMemberType)->pAttributeTypeRef; 151 nParams = 0; 152 pParams = NULL; 153 } 154 else 155 { 156 param.pTypeRef = ((typelib_InterfaceAttributeTypeDescription *) 157 pMemberType)->pAttributeTypeRef; 158 param.bIn = sal_True; 159 param.bOut = sal_False; 160 nParams = 1; 161 pParams = ¶m; 162 } 163 break; 164 case typelib_TypeClass_INTERFACE_METHOD: 165 { 166 typelib_InterfaceMethodTypeDescription * method_td = 167 (typelib_InterfaceMethodTypeDescription *) pMemberType; 168 pReturnTypeRef = method_td->pReturnTypeRef; 169 nParams = method_td->nParams; 170 pParams = method_td->pParams; 171 break; 172 } 173 default: 174 OSL_ENSURE( sal_False, "### illegal member typeclass!" ); 175 abort(); 176 } 177 178 pThis->dispatch( pReturnTypeRef, 179 pParams, 180 nParams, 181 pMemberType, 182 pReturn, 183 pArgs, 184 ppException ); 185 }} 186 187 extern "C" void SAL_CALL Proxy_free(uno_ExtEnvironment * /*pEnv*/, void * pProxy) SAL_THROW_EXTERN_C() 188 { 189 Proxy * pThis = static_cast<Proxy * >(reinterpret_cast<uno_Interface *>(pProxy)); 190 delete pThis; 191 } 192 193 extern "C" { 194 static void SAL_CALL s_Proxy_acquire(uno_Interface * pUnoI) SAL_THROW_EXTERN_C() 195 { 196 Proxy * pProxy = static_cast<Proxy *>(pUnoI); 197 pProxy->acquire(); 198 } 199 200 static void SAL_CALL s_Proxy_release(uno_Interface * pUnoI) SAL_THROW_EXTERN_C() 201 { 202 Proxy * pProxy = static_cast<Proxy *>(pUnoI); 203 pProxy->release(); 204 } 205 206 static void s_acquireAndRegister_v(va_list * pParam) 207 { 208 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); 209 rtl_uString * pOid = va_arg(*pParam, rtl_uString *); 210 typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *); 211 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); 212 213 pUnoI->acquire(pUnoI); 214 pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr); 215 } 216 } 217 218 Proxy::Proxy(uno::Mapping const & to_from, 219 uno_Environment * pTo, 220 uno_Environment * pFrom, 221 uno_Interface * pUnoI, 222 typelib_InterfaceTypeDescription * pTypeDescr, 223 rtl::OUString const & rOId, 224 cppu::helper::purpenv::ProbeFun * probeFun, 225 void * pProbeContext 226 ) 227 SAL_THROW(()) 228 : m_nRef (1), 229 m_from (pFrom), 230 m_to (pTo), 231 m_from_to (pFrom, pTo), 232 m_to_from (to_from), 233 m_pUnoI (pUnoI), 234 m_pTypeDescr (pTypeDescr), 235 m_aOId (rOId), 236 m_probeFun (probeFun), 237 m_pProbeContext(pProbeContext) 238 { 239 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::Proxy(<>)", this)); 240 241 typelib_typedescription_acquire((typelib_TypeDescription *)m_pTypeDescr); 242 if (!((typelib_TypeDescription *)m_pTypeDescr)->bComplete) 243 typelib_typedescription_complete((typelib_TypeDescription **)&m_pTypeDescr); 244 245 OSL_ENSURE(((typelib_TypeDescription *)m_pTypeDescr)->bComplete, "### type is incomplete!"); 246 247 uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get()); 248 249 // uno_Interface 250 uno_Interface::acquire = s_Proxy_acquire; 251 uno_Interface::release = s_Proxy_release; 252 uno_Interface::pDispatcher = s_Proxy_dispatch; 253 } 254 255 extern "C" { static void s_releaseAndRevoke_v(va_list * pParam) 256 { 257 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); 258 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); 259 260 pEnv->revokeInterface(pEnv, reinterpret_cast<void *>(pUnoI)); 261 pUnoI->release(pUnoI); 262 }} 263 264 Proxy::~Proxy() 265 { 266 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::~Proxy()", this)); 267 268 uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI); 269 270 typelib_typedescription_release((typelib_TypeDescription *)m_pTypeDescr); 271 } 272 273 static uno::TypeDescription getAcquireMethod(void) 274 { 275 typelib_TypeDescriptionReference * type_XInterface = 276 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE); 277 278 typelib_TypeDescription * pTXInterfaceDescr = 0; 279 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface); 280 uno::TypeDescription acquire( 281 reinterpret_cast< typelib_InterfaceTypeDescription * >( 282 pTXInterfaceDescr)->ppAllMembers[1]); 283 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr); 284 285 return acquire; 286 } 287 288 static uno::TypeDescription getReleaseMethod(void) 289 { 290 typelib_TypeDescriptionReference * type_XInterface = 291 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE); 292 293 typelib_TypeDescription * pTXInterfaceDescr = 0; 294 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface); 295 uno::TypeDescription release( 296 reinterpret_cast< typelib_InterfaceTypeDescription * >( 297 pTXInterfaceDescr)->ppAllMembers[2]); 298 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr); 299 300 return release; 301 } 302 303 static uno::TypeDescription s_acquireMethod(getAcquireMethod()); 304 static uno::TypeDescription s_releaseMethod(getReleaseMethod()); 305 306 void Proxy::acquire(void) 307 { 308 if (m_probeFun) 309 m_probeFun(true, 310 this, 311 m_pProbeContext, 312 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), 313 NULL, 314 0, 315 s_acquireMethod.get(), 316 NULL, 317 NULL, 318 NULL); 319 320 if (osl_incrementInterlockedCount(&m_nRef) == 1) 321 { 322 // rebirth of proxy zombie 323 void * pThis = this; 324 m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv, 325 &pThis, 326 Proxy_free, 327 m_aOId.pData, 328 m_pTypeDescr); 329 OSL_ASSERT(pThis == this); 330 } 331 332 if (m_probeFun) 333 m_probeFun(false, 334 this, 335 m_pProbeContext, 336 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), 337 NULL, 338 0, 339 s_acquireMethod.get(), 340 NULL, 341 NULL, 342 NULL); 343 344 } 345 346 void Proxy::release(void) 347 { 348 cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun; 349 void * pProbeContext = m_pProbeContext; 350 351 if (m_probeFun) 352 m_probeFun(true, 353 this, 354 m_pProbeContext, 355 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), 356 NULL, 357 0, 358 s_releaseMethod.get(), 359 NULL, 360 NULL, 361 NULL); 362 363 if (osl_decrementInterlockedCount(&m_nRef) == 0) 364 m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this); 365 366 if (probeFun) 367 probeFun(false, 368 this, 369 pProbeContext, 370 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), 371 NULL, 372 0, 373 s_releaseMethod.get(), 374 NULL, 375 NULL, 376 NULL); 377 378 } 379 380 381 extern "C" { 382 static void s_type_destructData_v(va_list * pParam) 383 { 384 void * ret = va_arg(*pParam, void *); 385 typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *); 386 387 uno_type_destructData(ret, pReturnTypeRef, 0); 388 } 389 390 static void s_dispatcher_v(va_list * pParam) 391 { 392 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); 393 typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *); 394 void * pReturn = va_arg(*pParam, void *); 395 void ** pArgs = va_arg(*pParam, void **); 396 uno_Any ** ppException = va_arg(*pParam, uno_Any **); 397 398 pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException); 399 } 400 } 401 402 void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef, 403 typelib_MethodParameter * pParams, 404 sal_Int32 nParams, 405 typelib_TypeDescription const * pMemberType, 406 void * pReturn, 407 void * pArgs[], 408 uno_Any ** ppException) 409 { 410 if (m_probeFun) 411 m_probeFun(true, 412 this, 413 m_pProbeContext, 414 pReturnTypeRef, 415 pParams, 416 nParams, 417 pMemberType, 418 pReturn, 419 pArgs, 420 ppException); 421 422 void ** args = (void **) alloca( sizeof (void *) * nParams ); 423 424 typelib_TypeDescription * return_td = 0; 425 void * ret = pReturn; 426 if (pReturnTypeRef) 427 { 428 TYPELIB_DANGER_GET(&return_td, pReturnTypeRef); 429 430 if (relatesToInterface(return_td)) 431 ret = alloca(return_td->nSize); 432 433 TYPELIB_DANGER_RELEASE(return_td); 434 } 435 436 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos) 437 { 438 typelib_MethodParameter const & param = pParams[nPos]; 439 typelib_TypeDescription * td = 0; 440 TYPELIB_DANGER_GET( &td, param.pTypeRef ); 441 if (relatesToInterface(td)) 442 { 443 args[nPos] = alloca(td->nSize); 444 if (param.bIn) 445 { 446 uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get()); 447 } 448 } 449 else 450 { 451 args[nPos] = pArgs[nPos]; 452 } 453 TYPELIB_DANGER_RELEASE( td ); 454 } 455 456 uno_Any exc_data; 457 uno_Any * exc = &exc_data; 458 459 // do the UNO call... 460 uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc); 461 462 if (exc == 0) 463 { 464 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos) 465 { 466 if (args[nPos] != pArgs[nPos]) 467 { 468 typelib_MethodParameter const & param = pParams[nPos]; 469 if (param.bOut) 470 { 471 if (param.bIn) // is inout 472 { 473 uno_type_destructData(pArgs[nPos], param.pTypeRef, 0); 474 } 475 uno_type_copyAndConvertData(pArgs[ nPos ], 476 args[ nPos ], 477 param.pTypeRef, 478 m_to_from.get()); 479 } 480 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0); 481 } 482 } 483 if (ret != pReturn) 484 { 485 uno_type_copyAndConvertData(pReturn, 486 ret, 487 pReturnTypeRef, 488 m_to_from.get()); 489 490 uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0); 491 } 492 493 *ppException = 0; 494 } 495 else // exception occured 496 { 497 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos) 498 { 499 if (args[nPos] != pArgs[nPos]) 500 { 501 typelib_MethodParameter const & param = pParams[nPos]; 502 if (param.bIn) 503 { 504 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0); 505 } 506 } 507 } 508 509 uno_type_any_constructAndConvert(*ppException, 510 exc->pData, 511 exc->pType, 512 m_to_from.get()); 513 514 // FIXME: need to destruct in m_to 515 uno_any_destruct(exc, 0); 516 } 517 518 if (m_probeFun) 519 m_probeFun(false, 520 this, 521 m_pProbeContext, 522 pReturnTypeRef, 523 pParams, 524 nParams, 525 pMemberType, 526 pReturn, 527 pArgs, 528 ppException); 529 } 530 531