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 //--------------------------------------------------------------------------------------------------
get_type_XCurrentContext()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 //__________________________________________________________________________________________________
ThreadKey(oslThreadKeyCallbackFunction pCallback)130 inline ThreadKey::ThreadKey( oslThreadKeyCallbackFunction pCallback ) SAL_THROW( () )
131 : _bInit( sal_False )
132 , _pCallback( pCallback )
133 {
134 }
135 //__________________________________________________________________________________________________
~ThreadKey()136 inline ThreadKey::~ThreadKey() SAL_THROW( () )
137 {
138 if (_bInit)
139 {
140 ::osl_destroyThreadKey( _hThreadKey );
141 }
142 }
143 //__________________________________________________________________________________________________
getThreadKey()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 //==================================================================================================
delete_IdContainer(void * p)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 //==================================================================================================
getIdContainer()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 //##################################################################################################
uno_setCurrentContext(void * pCurrentContext,rtl_uString * pEnvTypeName,void * pEnvContext)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 //##################################################################################################
uno_getCurrentContext(void ** ppCurrentContext,rtl_uString * pEnvTypeName,void * pEnvContext)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