Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include "uno/environment.hxx"
21 : :
22 : : #include "cppu/EnvDcp.hxx"
23 : : #include "cppu/Enterable.hxx"
24 : :
25 : : #include "rtl/instance.hxx"
26 : :
27 : : #include "osl/thread.h"
28 : : #include "osl/mutex.hxx"
29 : :
30 : : #include <boost/unordered_map.hpp>
31 : :
32 : :
33 : : using namespace com::sun::star;
34 : :
35 : :
36 : : struct SAL_DLLPRIVATE oslThreadIdentifier_equal
37 : : {
38 : : bool operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const;
39 : : };
40 : :
41 : 0 : bool oslThreadIdentifier_equal::operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const
42 : : {
43 : 0 : bool result = s1 == s2;
44 : :
45 : 0 : return result;
46 : : }
47 : :
48 : :
49 : : struct SAL_DLLPRIVATE oslThreadIdentifier_hash
50 : : {
51 : : size_t operator()(oslThreadIdentifier s1) const;
52 : : };
53 : :
54 : 0 : size_t oslThreadIdentifier_hash::operator()(oslThreadIdentifier s1) const
55 : : {
56 : 0 : return s1;
57 : : }
58 : :
59 : : typedef ::boost::unordered_map<oslThreadIdentifier,
60 : : uno_Environment *,
61 : : oslThreadIdentifier_hash,
62 : : oslThreadIdentifier_equal> ThreadMap;
63 : :
64 : : namespace
65 : : {
66 : : struct s_threadMap_mutex : public rtl::Static< osl::Mutex, s_threadMap_mutex > {};
67 : : struct s_threadMap : public rtl::Static< ThreadMap, s_threadMap > {};
68 : : }
69 : :
70 : 2411 : static rtl::OUString s_uno_envDcp(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO));
71 : :
72 : 2015721 : static void s_setCurrent(uno_Environment * pEnv)
73 : : {
74 [ + - ]: 2015721 : oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL);
75 : :
76 [ + - ][ + - ]: 2015722 : osl::MutexGuard guard(s_threadMap_mutex::get());
77 [ + - ]: 2015722 : ThreadMap &rThreadMap = s_threadMap::get();
78 [ - + ]: 2015722 : if (pEnv)
79 [ # # ]: 0 : rThreadMap[threadId] = pEnv;
80 : :
81 : : else
82 [ + - ][ + - ]: 2015722 : rThreadMap.erase(threadId);
83 : 2015722 : }
84 : :
85 : 2070878 : static uno_Environment * s_getCurrent(void)
86 : : {
87 : 2070878 : uno_Environment * pEnv = NULL;
88 : :
89 [ + - ]: 2070878 : oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL);
90 : :
91 [ + - ][ + - ]: 2070882 : osl::MutexGuard guard(s_threadMap_mutex::get());
92 [ + - ]: 2070882 : ThreadMap &rThreadMap = s_threadMap::get();
93 [ + - ]: 2070882 : ThreadMap::iterator iEnv = rThreadMap.find(threadId);
94 [ + - ][ - + ]: 2070882 : if(iEnv != rThreadMap.end())
95 [ # # ]: 0 : pEnv = iEnv->second;
96 : :
97 [ + - ]: 2070882 : return pEnv;
98 : : }
99 : :
100 : :
101 : 55160 : extern "C" CPPU_DLLPUBLIC void SAL_CALL uno_getCurrentEnvironment(uno_Environment ** ppEnv, rtl_uString * pTypeName)
102 : : SAL_THROW_EXTERN_C()
103 : : {
104 [ - + ]: 55160 : if (*ppEnv)
105 : : {
106 [ # # ]: 0 : (*ppEnv)->release(*ppEnv);
107 : 0 : *ppEnv = NULL;
108 : : }
109 : :
110 : 55160 : rtl::OUString currPurpose;
111 : :
112 [ + - ]: 55160 : uno_Environment * pCurrEnv = s_getCurrent();
113 [ - + ]: 55160 : if (pCurrEnv) // no environment means no purpose
114 [ # # ]: 0 : currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);
115 : :
116 [ + - ][ + - ]: 55160 : if (pTypeName && rtl_uString_getLength(pTypeName))
[ + - ]
117 : : {
118 : 55160 : rtl::OUString envDcp(pTypeName);
119 : 55160 : envDcp += currPurpose;
120 : :
121 : 55160 : uno_getEnvironment(ppEnv, envDcp.pData, NULL);
122 : : }
123 : : else
124 : : {
125 [ # # ]: 0 : if (pCurrEnv)
126 : : {
127 : 0 : *ppEnv = pCurrEnv;
128 [ # # ]: 0 : (*ppEnv)->acquire(*ppEnv);
129 : : }
130 : : else
131 : 0 : uno_getEnvironment(ppEnv, s_uno_envDcp.pData, NULL);
132 : :
133 : 55160 : }
134 : 55160 : }
135 : :
136 : 1007861 : static rtl::OUString s_getPrefix(rtl::OUString const & str1, rtl::OUString const & str2)
137 : : {
138 : 1007861 : sal_Int32 nIndex1 = 0;
139 : 1007861 : sal_Int32 nIndex2 = 0;
140 : 1007861 : sal_Int32 sim = 0;
141 : :
142 : 1007861 : rtl::OUString token1;
143 : 1007861 : rtl::OUString token2;
144 : :
145 [ + - ]: 1007861 : do
[ - + # # ]
[ - + ]
146 : : {
147 : 1007861 : token1 = str1.getToken(0, ':', nIndex1);
148 : 1007861 : token2 = str2.getToken(0, ':', nIndex2);
149 : :
150 [ + - ]: 1007861 : if (token1.equals(token2))
151 : 1007861 : sim += token1.getLength() + 1;
152 : : }
153 : 0 : while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2));
154 : :
155 : 1007861 : rtl::OUString result;
156 : :
157 [ + - ]: 1007861 : if (sim)
158 : 1007861 : result = str1.copy(0, sim - 1);
159 : :
160 : 1007861 : return result;
161 : : }
162 : :
163 : 1007861 : static int s_getNextEnv(uno_Environment ** ppEnv, uno_Environment * pCurrEnv, uno_Environment * pTargetEnv)
164 : : {
165 : 1007861 : int res = 0;
166 : :
167 : 1007861 : rtl::OUString nextPurpose;
168 : :
169 : 1007861 : rtl::OUString currPurpose;
170 [ - + ]: 1007861 : if (pCurrEnv)
171 [ # # ]: 0 : currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);
172 : :
173 : 1007861 : rtl::OUString targetPurpose;
174 [ + - ]: 1007861 : if (pTargetEnv)
175 [ + - ]: 1007861 : targetPurpose = cppu::EnvDcp::getPurpose(pTargetEnv->pTypeName);
176 : :
177 : 1007861 : rtl::OUString intermPurpose(s_getPrefix(currPurpose, targetPurpose));
178 [ - + ]: 1007861 : if (currPurpose.getLength() > intermPurpose.getLength())
179 : : {
180 : 0 : sal_Int32 idx = currPurpose.lastIndexOf(':');
181 : 0 : nextPurpose = currPurpose.copy(0, idx);
182 : :
183 : 0 : res = -1;
184 : : }
185 [ - + ]: 1007861 : else if (intermPurpose.getLength() < targetPurpose.getLength())
186 : : {
187 : 0 : sal_Int32 idx = targetPurpose.indexOf(':', intermPurpose.getLength() + 1);
188 [ # # ]: 0 : if (idx == -1)
189 : 0 : nextPurpose = targetPurpose;
190 : :
191 : : else
192 : 0 : nextPurpose = targetPurpose.copy(0, idx);
193 : :
194 : 0 : res = 1;
195 : : }
196 : :
197 [ - + ]: 1007861 : if (!nextPurpose.isEmpty())
198 : : {
199 : 0 : rtl::OUString next_envDcp(s_uno_envDcp);
200 : 0 : next_envDcp += nextPurpose;
201 : :
202 : 0 : uno_getEnvironment(ppEnv, next_envDcp.pData, NULL);
203 : : }
204 : : else
205 : : {
206 [ - + ]: 1007861 : if (*ppEnv)
207 [ # # ]: 0 : (*ppEnv)->release(*ppEnv);
208 : :
209 : 1007861 : *ppEnv = NULL;
210 : : }
211 : :
212 : 1007861 : return res;
213 : : }
214 : :
215 : 0 : extern "C" { static void s_pull(va_list * pParam)
216 : : {
217 : 0 : uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
218 : 0 : va_list * pXparam = va_arg(*pParam, va_list *);
219 : :
220 : 0 : pCallee(pXparam);
221 : 0 : }}
222 : :
223 : 0 : static void s_callInto_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
224 : : {
225 : 0 : cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved);
226 [ # # ]: 0 : if (pEnterable)
227 : 0 : pEnterable->callInto(s_pull, pCallee, pParam);
228 : :
229 : : else
230 : 0 : pCallee(pParam);
231 : 0 : }
232 : :
233 : 0 : static void s_callInto(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
234 : : {
235 : : va_list param;
236 : :
237 : 0 : va_start(param, pCallee);
238 [ # # ]: 0 : s_callInto_v(pEnv, pCallee, ¶m);
239 : 0 : va_end(param);
240 : 0 : }
241 : :
242 : 0 : static void s_callOut_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
243 : : {
244 : 0 : cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved);
245 [ # # ]: 0 : if (pEnterable)
246 : 0 : pEnterable->callOut_v(pCallee, pParam);
247 : :
248 : : else
249 : 0 : pCallee(pParam);
250 : 0 : }
251 : :
252 : 0 : static void s_callOut(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
253 : : {
254 : : va_list param;
255 : :
256 : 0 : va_start(param, pCallee);
257 [ # # ]: 0 : s_callOut_v(pEnv, pCallee, ¶m);
258 : 0 : va_end(param);
259 : 0 : }
260 : :
261 : : static void s_environment_invoke_v(uno_Environment *, uno_Environment *, uno_EnvCallee *, va_list *);
262 : :
263 : 0 : extern "C" { static void s_environment_invoke_vv(va_list * pParam)
264 : : {
265 : 0 : uno_Environment * pCurrEnv = va_arg(*pParam, uno_Environment *);
266 : 0 : uno_Environment * pTargetEnv = va_arg(*pParam, uno_Environment *);
267 : 0 : uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
268 : 0 : va_list * pXparam = va_arg(*pParam, va_list *);
269 : :
270 : 0 : s_environment_invoke_v(pCurrEnv, pTargetEnv, pCallee, pXparam);
271 : 0 : }}
272 : :
273 : 1007861 : static void s_environment_invoke_v(uno_Environment * pCurrEnv, uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
274 : : {
275 : 1007861 : uno_Environment * pNextEnv = NULL;
276 [ + - ]: 1007861 : switch(s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv))
[ - + - - ]
277 : : {
278 : : case -1:
279 [ # # ]: 0 : s_setCurrent(pNextEnv);
280 [ # # ]: 0 : s_callOut(pCurrEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
281 [ # # ]: 0 : s_setCurrent(pCurrEnv);
282 : 0 : break;
283 : :
284 : : case 0: {
285 [ + - ]: 1007861 : uno_Environment * hld = s_getCurrent();
286 [ + - ]: 1007860 : s_setCurrent(pCurrEnv);
287 [ + - ]: 1007861 : pCallee(pParam);
288 [ + - ]: 1007861 : s_setCurrent(hld);
289 : : }
290 : 1007861 : break;
291 : :
292 : : case 1:
293 [ # # ]: 0 : s_setCurrent(pNextEnv);
294 [ # # ]: 0 : s_callInto(pNextEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
295 [ # # ]: 0 : s_setCurrent(pCurrEnv);
296 : 0 : break;
297 : : }
298 : :
299 [ - + ]: 1007861 : if (pNextEnv)
300 [ # # ]: 0 : pNextEnv->release(pNextEnv);
301 : 1007861 : }
302 : :
303 : 1007861 : extern "C" CPPU_DLLPUBLIC void SAL_CALL uno_Environment_invoke_v(uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
304 : : SAL_THROW_EXTERN_C()
305 : : {
306 : 1007861 : s_environment_invoke_v(s_getCurrent(), pTargetEnv, pCallee, pParam);
307 : 1007861 : }
308 : :
309 : 977204 : extern "C" CPPU_DLLPUBLIC void SAL_CALL uno_Environment_invoke(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
310 : : SAL_THROW_EXTERN_C()
311 : : {
312 : : va_list param;
313 : :
314 : 977204 : va_start(param, pCallee);
315 : 977204 : uno_Environment_invoke_v(pEnv, pCallee, ¶m);
316 : 977204 : va_end(param);
317 : 977204 : }
318 : :
319 : 0 : extern "C" CPPU_DLLPUBLIC void SAL_CALL uno_Environment_enter(uno_Environment * pTargetEnv)
320 : : SAL_THROW_EXTERN_C()
321 : : {
322 : 0 : uno_Environment * pNextEnv = NULL;
323 [ # # ]: 0 : uno_Environment * pCurrEnv = s_getCurrent();
324 : :
325 : : int res;
326 [ # # ][ # # ]: 0 : while ( (res = s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) != 0)
327 : : {
328 : : cppu::Enterable * pEnterable;
329 : :
330 [ # # # ]: 0 : switch(res)
331 : : {
332 : : case -1:
333 : 0 : pEnterable = reinterpret_cast<cppu::Enterable *>(pCurrEnv->pReserved);
334 [ # # ]: 0 : if (pEnterable)
335 [ # # ]: 0 : pEnterable->leave();
336 [ # # ]: 0 : pCurrEnv->release(pCurrEnv);
337 : 0 : break;
338 : :
339 : : case 1:
340 [ # # ]: 0 : pNextEnv->acquire(pNextEnv);
341 : 0 : pEnterable = reinterpret_cast<cppu::Enterable *>(pNextEnv->pReserved);
342 [ # # ]: 0 : if (pEnterable)
343 [ # # ]: 0 : pEnterable->enter();
344 : 0 : break;
345 : : }
346 : :
347 [ # # ]: 0 : s_setCurrent(pNextEnv);
348 : 0 : pCurrEnv = pNextEnv;
349 : : }
350 : 0 : }
351 : :
352 : 0 : CPPU_DLLPUBLIC int SAL_CALL uno_Environment_isValid(uno_Environment * pEnv, rtl_uString ** pReason)
353 : : SAL_THROW_EXTERN_C()
354 : : {
355 : 0 : int result = 1;
356 : :
357 [ # # ]: 0 : rtl::OUString typeName(cppu::EnvDcp::getTypeName(pEnv->pTypeName));
358 [ # # ]: 0 : if (typeName.equals(s_uno_envDcp))
359 : : {
360 : 0 : cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved);
361 [ # # ]: 0 : if (pEnterable)
362 [ # # ]: 0 : result = pEnterable->isValid((rtl::OUString *)pReason);
363 : : }
364 : : else
365 : : {
366 : 0 : rtl::OUString envDcp(s_uno_envDcp);
367 [ # # ]: 0 : envDcp += cppu::EnvDcp::getPurpose(pEnv->pTypeName);
368 : :
369 : 0 : uno::Environment env(envDcp);
370 : :
371 [ # # ]: 0 : result = env.isValid((rtl::OUString *)pReason);
372 : : }
373 : :
374 : 0 : return result;
375 [ + - ][ + - ]: 7233 : }
376 : :
377 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|