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