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 "rtl/uuid.h" 32 #include "osl/thread.h" 33 #include "osl/mutex.hxx" 34 35 #include "uno/environment.hxx" 36 #include "uno/mapping.hxx" 37 #include "uno/lbnames.h" 38 #include "typelib/typedescription.h" 39 40 #include "current.hxx" 41 42 43 using namespace ::osl; 44 using namespace ::rtl; 45 using namespace ::cppu; 46 using namespace ::com::sun::star::uno; 47 48 namespace cppu 49 { 50 51 //-------------------------------------------------------------------------------------------------- 52 class SAL_NO_VTABLE XInterface 53 { 54 public: 55 virtual void SAL_CALL slot_queryInterface() = 0; 56 virtual void SAL_CALL acquire() throw () = 0; 57 virtual void SAL_CALL release() throw () = 0; 58 }; 59 //-------------------------------------------------------------------------------------------------- 60 static typelib_InterfaceTypeDescription * get_type_XCurrentContext() 61 { 62 static typelib_InterfaceTypeDescription * s_type_XCurrentContext = 0; 63 if (0 == s_type_XCurrentContext) 64 { 65 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 66 if (0 == s_type_XCurrentContext) 67 { 68 OUString sTypeName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XCurrentContext") ); 69 typelib_InterfaceTypeDescription * pTD = 0; 70 typelib_TypeDescriptionReference * pMembers[1] = { 0 }; 71 OUString sMethodName0( 72 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XCurrentContext::getValueByName") ); 73 typelib_typedescriptionreference_new( 74 &pMembers[0], 75 typelib_TypeClass_INTERFACE_METHOD, 76 sMethodName0.pData ); 77 typelib_typedescription_newInterface( 78 &pTD, 79 sTypeName.pData, 0x00000000, 0x0000, 0x0000, 0x00000000, 0x00000000, 80 * typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE ), 81 1, 82 pMembers ); 83 84 typelib_typedescription_register( (typelib_TypeDescription**)&pTD ); 85 typelib_typedescriptionreference_release( pMembers[0] ); 86 87 typelib_InterfaceMethodTypeDescription * pMethod = 0; 88 typelib_Parameter_Init aParameters[1]; 89 OUString sParamName0( RTL_CONSTASCII_USTRINGPARAM("Name") ); 90 OUString sParamType0( RTL_CONSTASCII_USTRINGPARAM("string") ); 91 aParameters[0].pParamName = sParamName0.pData; 92 aParameters[0].eTypeClass = typelib_TypeClass_STRING; 93 aParameters[0].pTypeName = sParamType0.pData; 94 aParameters[0].bIn = sal_True; 95 aParameters[0].bOut = sal_False; 96 rtl_uString * pExceptions[1]; 97 OUString sExceptionName0( 98 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.RuntimeException") ); 99 pExceptions[0] = sExceptionName0.pData; 100 OUString sReturnType0( RTL_CONSTASCII_USTRINGPARAM("any") ); 101 typelib_typedescription_newInterfaceMethod( 102 &pMethod, 103 3, sal_False, 104 sMethodName0.pData, 105 typelib_TypeClass_ANY, sReturnType0.pData, 106 1, aParameters, 1, pExceptions ); 107 typelib_typedescription_register( (typelib_TypeDescription**)&pMethod ); 108 typelib_typedescription_release( (typelib_TypeDescription*)pMethod ); 109 // another static ref: 110 ++reinterpret_cast< typelib_TypeDescription * >( pTD )-> 111 nStaticRefCount; 112 s_type_XCurrentContext = pTD; 113 } 114 } 115 return s_type_XCurrentContext; 116 } 117 118 //################################################################################################## 119 120 //================================================================================================== 121 class ThreadKey 122 { 123 sal_Bool _bInit; 124 oslThreadKey _hThreadKey; 125 oslThreadKeyCallbackFunction _pCallback; 126 127 public: 128 inline oslThreadKey getThreadKey() SAL_THROW( () ); 129 130 inline ThreadKey( oslThreadKeyCallbackFunction pCallback ) SAL_THROW( () ); 131 inline ~ThreadKey() SAL_THROW( () ); 132 }; 133 //__________________________________________________________________________________________________ 134 inline ThreadKey::ThreadKey( oslThreadKeyCallbackFunction pCallback ) SAL_THROW( () ) 135 : _bInit( sal_False ) 136 , _pCallback( pCallback ) 137 { 138 } 139 //__________________________________________________________________________________________________ 140 inline ThreadKey::~ThreadKey() SAL_THROW( () ) 141 { 142 if (_bInit) 143 { 144 ::osl_destroyThreadKey( _hThreadKey ); 145 } 146 } 147 //__________________________________________________________________________________________________ 148 inline oslThreadKey ThreadKey::getThreadKey() SAL_THROW( () ) 149 { 150 if (! _bInit) 151 { 152 MutexGuard aGuard( Mutex::getGlobalMutex() ); 153 if (! _bInit) 154 { 155 _hThreadKey = ::osl_createThreadKey( _pCallback ); 156 _bInit = sal_True; 157 } 158 } 159 return _hThreadKey; 160 } 161 162 //================================================================================================== 163 extern "C" void SAL_CALL delete_IdContainer( void * p ) 164 { 165 if (p) 166 { 167 IdContainer * pId = reinterpret_cast< IdContainer * >( p ); 168 if (pId->pCurrentContext) 169 { 170 (*pId->pCurrentContextEnv->releaseInterface)( 171 pId->pCurrentContextEnv, pId->pCurrentContext ); 172 (*((uno_Environment *)pId->pCurrentContextEnv)->release)( 173 (uno_Environment *)pId->pCurrentContextEnv ); 174 } 175 if (pId->bInit) 176 { 177 ::rtl_byte_sequence_release( pId->pLocalThreadId ); 178 ::rtl_byte_sequence_release( pId->pCurrentId ); 179 } 180 delete pId; 181 } 182 } 183 //================================================================================================== 184 IdContainer * getIdContainer() SAL_THROW( () ) 185 { 186 static ThreadKey s_key( delete_IdContainer ); 187 oslThreadKey aKey = s_key.getThreadKey(); 188 189 IdContainer * pId = reinterpret_cast< IdContainer * >( ::osl_getThreadKeyData( aKey ) ); 190 if (! pId) 191 { 192 pId = new IdContainer(); 193 pId->pCurrentContext = 0; 194 pId->pCurrentContextEnv = 0; 195 pId->bInit = sal_False; 196 ::osl_setThreadKeyData( aKey, pId ); 197 } 198 return pId; 199 } 200 201 } 202 203 //################################################################################################## 204 extern "C" sal_Bool SAL_CALL uno_setCurrentContext( 205 void * pCurrentContext, 206 rtl_uString * pEnvTypeName, void * pEnvContext ) 207 SAL_THROW_EXTERN_C() 208 { 209 IdContainer * pId = getIdContainer(); 210 OSL_ASSERT( pId ); 211 212 // free old one 213 if (pId->pCurrentContext) 214 { 215 (*pId->pCurrentContextEnv->releaseInterface)( 216 pId->pCurrentContextEnv, pId->pCurrentContext ); 217 (*((uno_Environment *)pId->pCurrentContextEnv)->release)( 218 (uno_Environment *)pId->pCurrentContextEnv ); 219 pId->pCurrentContextEnv = 0; 220 221 pId->pCurrentContext = 0; 222 } 223 224 if (pCurrentContext) 225 { 226 uno_Environment * pEnv = 0; 227 ::uno_getEnvironment( &pEnv, pEnvTypeName, pEnvContext ); 228 OSL_ASSERT( pEnv && pEnv->pExtEnv ); 229 if (pEnv) 230 { 231 if (pEnv->pExtEnv) 232 { 233 pId->pCurrentContextEnv = pEnv->pExtEnv; 234 (*pId->pCurrentContextEnv->acquireInterface)( 235 pId->pCurrentContextEnv, pCurrentContext ); 236 pId->pCurrentContext = pCurrentContext; 237 } 238 else 239 { 240 (*pEnv->release)( pEnv ); 241 return sal_False; 242 } 243 } 244 else 245 { 246 return sal_False; 247 } 248 } 249 return sal_True; 250 } 251 //################################################################################################## 252 extern "C" sal_Bool SAL_CALL uno_getCurrentContext( 253 void ** ppCurrentContext, rtl_uString * pEnvTypeName, void * pEnvContext ) 254 SAL_THROW_EXTERN_C() 255 { 256 IdContainer * pId = getIdContainer(); 257 OSL_ASSERT( pId ); 258 259 Environment target_env; 260 261 // release inout parameter 262 if (*ppCurrentContext) 263 { 264 target_env = Environment(rtl::OUString(pEnvTypeName), pEnvContext); 265 OSL_ASSERT( target_env.is() ); 266 if (! target_env.is()) 267 return sal_False; 268 uno_ExtEnvironment * pEnv = target_env.get()->pExtEnv; 269 OSL_ASSERT( 0 != pEnv ); 270 if (0 == pEnv) 271 return sal_False; 272 (*pEnv->releaseInterface)( pEnv, *ppCurrentContext ); 273 274 *ppCurrentContext = 0; 275 } 276 277 // case: null-ref 278 if (0 == pId->pCurrentContext) 279 return sal_True; 280 281 if (! target_env.is()) 282 { 283 target_env = Environment(rtl::OUString(pEnvTypeName), pEnvContext); 284 OSL_ASSERT( target_env.is() ); 285 if (! target_env.is()) 286 return sal_False; 287 } 288 289 Mapping mapping((uno_Environment *) pId->pCurrentContextEnv, target_env.get()); 290 OSL_ASSERT( mapping.is() ); 291 if (! mapping.is()) 292 return sal_False; 293 294 mapping.mapInterface(ppCurrentContext, pId->pCurrentContext, ::cppu::get_type_XCurrentContext() ); 295 296 return sal_True; 297 } 298