1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
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__attribute__ ((visibility("hidden"))) oslThreadIdentifier_equal |
37 | { |
38 | bool operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const; |
39 | }; |
40 | |
41 | bool oslThreadIdentifier_equal::operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const |
42 | { |
43 | bool result = s1 == s2; |
44 | |
45 | return result; |
46 | } |
47 | |
48 | |
49 | struct SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) oslThreadIdentifier_hash |
50 | { |
51 | size_t operator()(oslThreadIdentifier s1) const; |
52 | }; |
53 | |
54 | size_t oslThreadIdentifier_hash::operator()(oslThreadIdentifier s1) const |
55 | { |
56 | 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 | static rtl::OUString s_uno_envDcp(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)(&("uno")[0]), ((sal_Int32)((sizeof ("uno") / sizeof (("uno" )[0]))-1)), (((rtl_TextEncoding) 11))); |
71 | |
72 | static void s_setCurrent(uno_Environment * pEnv) |
73 | { |
74 | oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL__null); |
75 | |
76 | osl::MutexGuard guard(s_threadMap_mutex::get()); |
77 | ThreadMap &rThreadMap = s_threadMap::get(); |
78 | if (pEnv) |
79 | rThreadMap[threadId] = pEnv; |
80 | |
81 | else |
82 | rThreadMap.erase(threadId); |
83 | } |
84 | |
85 | static uno_Environment * s_getCurrent(void) |
86 | { |
87 | uno_Environment * pEnv = NULL__null; |
88 | |
89 | oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL__null); |
90 | |
91 | osl::MutexGuard guard(s_threadMap_mutex::get()); |
92 | ThreadMap &rThreadMap = s_threadMap::get(); |
93 | ThreadMap::iterator iEnv = rThreadMap.find(threadId); |
94 | if(iEnv != rThreadMap.end()) |
95 | pEnv = iEnv->second; |
96 | |
97 | return pEnv; |
98 | } |
99 | |
100 | |
101 | extern "C" CPPU_DLLPUBLIC__attribute__ ((visibility("default"))) void SAL_CALL uno_getCurrentEnvironment(uno_Environment ** ppEnv, rtl_uString * pTypeName) |
102 | SAL_THROW_EXTERN_C()throw () |
103 | { |
104 | if (*ppEnv) |
105 | { |
106 | (*ppEnv)->release(*ppEnv); |
107 | *ppEnv = NULL__null; |
108 | } |
109 | |
110 | rtl::OUString currPurpose; |
111 | |
112 | uno_Environment * pCurrEnv = s_getCurrent(); |
113 | if (pCurrEnv) |
114 | currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName); |
115 | |
116 | if (pTypeName && rtl_uString_getLength(pTypeName)) |
117 | { |
118 | rtl::OUString envDcp(pTypeName); |
119 | envDcp += currPurpose; |
120 | |
121 | uno_getEnvironment(ppEnv, envDcp.pData, NULL__null); |
122 | } |
123 | else |
124 | { |
125 | if (pCurrEnv) |
126 | { |
127 | *ppEnv = pCurrEnv; |
128 | (*ppEnv)->acquire(*ppEnv); |
129 | } |
130 | else |
131 | uno_getEnvironment(ppEnv, s_uno_envDcp.pData, NULL__null); |
132 | |
133 | } |
134 | } |
135 | |
136 | static rtl::OUString s_getPrefix(rtl::OUString const & str1, rtl::OUString const & str2) |
137 | { |
138 | sal_Int32 nIndex1 = 0; |
139 | sal_Int32 nIndex2 = 0; |
140 | sal_Int32 sim = 0; |
141 | |
142 | rtl::OUString token1; |
143 | rtl::OUString token2; |
144 | |
145 | do |
146 | { |
147 | token1 = str1.getToken(0, ':', nIndex1); |
148 | token2 = str2.getToken(0, ':', nIndex2); |
149 | |
150 | if (token1.equals(token2)) |
151 | sim += token1.getLength() + 1; |
152 | } |
153 | while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2)); |
154 | |
155 | rtl::OUString result; |
156 | |
157 | if (sim) |
158 | result = str1.copy(0, sim - 1); |
159 | |
160 | return result; |
161 | } |
162 | |
163 | static int s_getNextEnv(uno_Environment ** ppEnv, uno_Environment * pCurrEnv, uno_Environment * pTargetEnv) |
164 | { |
165 | int res = 0; |
166 | |
167 | rtl::OUString nextPurpose; |
168 | |
169 | rtl::OUString currPurpose; |
170 | if (pCurrEnv) |
171 | currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName); |
172 | |
173 | rtl::OUString targetPurpose; |
174 | if (pTargetEnv) |
175 | targetPurpose = cppu::EnvDcp::getPurpose(pTargetEnv->pTypeName); |
176 | |
177 | rtl::OUString intermPurpose(s_getPrefix(currPurpose, targetPurpose)); |
178 | if (currPurpose.getLength() > intermPurpose.getLength()) |
179 | { |
180 | sal_Int32 idx = currPurpose.lastIndexOf(':'); |
181 | nextPurpose = currPurpose.copy(0, idx); |
182 | |
183 | res = -1; |
184 | } |
185 | else if (intermPurpose.getLength() < targetPurpose.getLength()) |
186 | { |
187 | sal_Int32 idx = targetPurpose.indexOf(':', intermPurpose.getLength() + 1); |
188 | if (idx == -1) |
189 | nextPurpose = targetPurpose; |
190 | |
191 | else |
192 | nextPurpose = targetPurpose.copy(0, idx); |
193 | |
194 | res = 1; |
195 | } |
196 | |
197 | if (!nextPurpose.isEmpty()) |
198 | { |
199 | rtl::OUString next_envDcp(s_uno_envDcp); |
200 | next_envDcp += nextPurpose; |
201 | |
202 | uno_getEnvironment(ppEnv, next_envDcp.pData, NULL__null); |
203 | } |
204 | else |
205 | { |
206 | if (*ppEnv) |
207 | (*ppEnv)->release(*ppEnv); |
208 | |
209 | *ppEnv = NULL__null; |
210 | } |
211 | |
212 | return res; |
213 | } |
214 | |
215 | extern "C" { static void s_pull(va_list * pParam) |
216 | { |
217 | uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *)__builtin_va_arg(*pParam, uno_EnvCallee *); |
218 | va_list * pXparam = va_arg(*pParam, va_list *)__builtin_va_arg(*pParam, va_list *); |
219 | |
220 | pCallee(pXparam); |
221 | }} |
222 | |
223 | static void s_callInto_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam) |
224 | { |
225 | cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved); |
226 | if (pEnterable) |
227 | pEnterable->callInto(s_pull, pCallee, pParam); |
228 | |
229 | else |
230 | pCallee(pParam); |
231 | } |
232 | |
233 | static void s_callInto(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...) |
234 | { |
235 | va_list param; |
236 | |
237 | va_start(param, pCallee)__builtin_va_start(param, pCallee); |
238 | s_callInto_v(pEnv, pCallee, ¶m); |
239 | va_end(param)__builtin_va_end(param); |
240 | } |
241 | |
242 | static void s_callOut_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam) |
243 | { |
244 | cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved); |
245 | if (pEnterable) |
246 | pEnterable->callOut_v(pCallee, pParam); |
247 | |
248 | else |
249 | pCallee(pParam); |
250 | } |
251 | |
252 | static void s_callOut(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...) |
253 | { |
254 | va_list param; |
255 | |
256 | va_start(param, pCallee)__builtin_va_start(param, pCallee); |
257 | s_callOut_v(pEnv, pCallee, ¶m); |
258 | va_end(param)__builtin_va_end(param); |
259 | } |
260 | |
261 | static void s_environment_invoke_v(uno_Environment *, uno_Environment *, uno_EnvCallee *, va_list *); |
262 | |
263 | extern "C" { static void s_environment_invoke_vv(va_list * pParam) |
264 | { |
265 | uno_Environment * pCurrEnv = va_arg(*pParam, uno_Environment *)__builtin_va_arg(*pParam, uno_Environment *); |
266 | uno_Environment * pTargetEnv = va_arg(*pParam, uno_Environment *)__builtin_va_arg(*pParam, uno_Environment *); |
267 | uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *)__builtin_va_arg(*pParam, uno_EnvCallee *); |
268 | va_list * pXparam = va_arg(*pParam, va_list *)__builtin_va_arg(*pParam, va_list *); |
269 | |
270 | s_environment_invoke_v(pCurrEnv, pTargetEnv, pCallee, pXparam); |
271 | }} |
272 | |
273 | static void s_environment_invoke_v(uno_Environment * pCurrEnv, uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam) |
274 | { |
275 | uno_Environment * pNextEnv = NULL__null; |
276 | switch(s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) |
277 | { |
278 | case -1: |
279 | s_setCurrent(pNextEnv); |
280 | s_callOut(pCurrEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam); |
281 | s_setCurrent(pCurrEnv); |
282 | break; |
283 | |
284 | case 0: { |
285 | uno_Environment * hld = s_getCurrent(); |
286 | s_setCurrent(pCurrEnv); |
287 | pCallee(pParam); |
288 | s_setCurrent(hld); |
289 | } |
290 | break; |
291 | |
292 | case 1: |
293 | s_setCurrent(pNextEnv); |
294 | s_callInto(pNextEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam); |
295 | s_setCurrent(pCurrEnv); |
296 | break; |
297 | } |
298 | |
299 | if (pNextEnv) |
300 | pNextEnv->release(pNextEnv); |
301 | } |
302 | |
303 | extern "C" CPPU_DLLPUBLIC__attribute__ ((visibility("default"))) void SAL_CALL uno_Environment_invoke_v(uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam) |
304 | SAL_THROW_EXTERN_C()throw () |
305 | { |
306 | s_environment_invoke_v(s_getCurrent(), pTargetEnv, pCallee, pParam); |
307 | } |
308 | |
309 | extern "C" CPPU_DLLPUBLIC__attribute__ ((visibility("default"))) void SAL_CALL uno_Environment_invoke(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...) |
310 | SAL_THROW_EXTERN_C()throw () |
311 | { |
312 | va_list param; |
313 | |
314 | va_start(param, pCallee)__builtin_va_start(param, pCallee); |
315 | uno_Environment_invoke_v(pEnv, pCallee, ¶m); |
316 | va_end(param)__builtin_va_end(param); |
317 | } |
318 | |
319 | extern "C" CPPU_DLLPUBLIC__attribute__ ((visibility("default"))) void SAL_CALL uno_Environment_enter(uno_Environment * pTargetEnv) |
320 | SAL_THROW_EXTERN_C()throw () |
321 | { |
322 | uno_Environment * pNextEnv = NULL__null; |
323 | uno_Environment * pCurrEnv = s_getCurrent(); |
324 | |
325 | int res; |
326 | while ( (res = s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) != 0) |
| 1 | Loop condition is true. Entering loop body | |
|
| 5 | | Loop condition is true. Entering loop body | |
|
| 9 | | Loop condition is true. Entering loop body | |
|
| 13 | | Loop condition is true. Entering loop body | |
|
327 | { |
328 | cppu::Enterable * pEnterable; |
329 | |
330 | switch(res) |
| 2 | | Control jumps to 'case 1:' at line 339 | |
|
| 6 | | Control jumps to 'case 1:' at line 339 | |
|
| 10 | | Control jumps to 'case 1:' at line 339 | |
|
| 14 | | Control jumps to 'case 1:' at line 339 | |
|
331 | { |
332 | case -1: |
333 | pEnterable = reinterpret_cast<cppu::Enterable *>(pCurrEnv->pReserved); |
334 | if (pEnterable) |
335 | pEnterable->leave(); |
336 | pCurrEnv->release(pCurrEnv); |
337 | break; |
338 | |
339 | case 1: |
340 | pNextEnv->acquire(pNextEnv); |
| 15 | | Access to field 'acquire' results in a dereference of a null pointer (loaded from variable 'pNextEnv') |
|
341 | pEnterable = reinterpret_cast<cppu::Enterable *>(pNextEnv->pReserved); |
342 | if (pEnterable) |
| |
| |
| |
343 | pEnterable->enter(); |
344 | break; |
| 4 | | Execution continues on line 347 | |
|
| 8 | | Execution continues on line 347 | |
|
| 12 | | Execution continues on line 347 | |
|
345 | } |
346 | |
347 | s_setCurrent(pNextEnv); |
348 | pCurrEnv = pNextEnv; |
349 | } |
350 | } |
351 | |
352 | CPPU_DLLPUBLIC__attribute__ ((visibility("default"))) int SAL_CALL uno_Environment_isValid(uno_Environment * pEnv, rtl_uString ** pReason) |
353 | SAL_THROW_EXTERN_C()throw () |
354 | { |
355 | int result = 1; |
356 | |
357 | rtl::OUString typeName(cppu::EnvDcp::getTypeName(pEnv->pTypeName)); |
358 | if (typeName.equals(s_uno_envDcp)) |
359 | { |
360 | cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved); |
361 | if (pEnterable) |
362 | result = pEnterable->isValid((rtl::OUString *)pReason); |
363 | } |
364 | else |
365 | { |
366 | rtl::OUString envDcp(s_uno_envDcp); |
367 | envDcp += cppu::EnvDcp::getPurpose(pEnv->pTypeName); |
368 | |
369 | uno::Environment env(envDcp); |
370 | |
371 | result = env.isValid((rtl::OUString *)pReason); |
372 | } |
373 | |
374 | return result; |
375 | } |
376 | |
377 | |