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 : #include <uno/lbnames.h>
22 :
23 : #include "cppu/EnvDcp.hxx"
24 : #include "cppu/Enterable.hxx"
25 :
26 : #include "rtl/instance.hxx"
27 :
28 : #include "osl/thread.h"
29 : #include "osl/thread.hxx"
30 : #include "osl/mutex.hxx"
31 :
32 : #include <unordered_map>
33 :
34 : using namespace com::sun::star;
35 :
36 :
37 : struct oslThreadIdentifier_equal
38 : {
39 : bool operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const;
40 : };
41 :
42 6203701 : bool oslThreadIdentifier_equal::operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const
43 : {
44 6203701 : bool result = s1 == s2;
45 :
46 6203701 : return result;
47 : }
48 :
49 :
50 : struct oslThreadIdentifier_hash
51 : {
52 : size_t operator()(oslThreadIdentifier s1) const;
53 : };
54 :
55 13415409 : size_t oslThreadIdentifier_hash::operator()(oslThreadIdentifier s1) const
56 : {
57 13415409 : return s1;
58 : }
59 :
60 : typedef std::unordered_map<oslThreadIdentifier,
61 : uno_Environment *,
62 : oslThreadIdentifier_hash,
63 : oslThreadIdentifier_equal> ThreadMap;
64 :
65 : namespace
66 : {
67 : struct s_threadMap_mutex : public rtl::Static< osl::Mutex, s_threadMap_mutex > {};
68 : struct s_threadMap : public rtl::Static< ThreadMap, s_threadMap > {};
69 : }
70 :
71 7442485 : static void s_setCurrent(uno_Environment * pEnv)
72 : {
73 7442485 : oslThreadIdentifier threadId = osl::Thread::getCurrentIdentifier();
74 :
75 7442492 : osl::MutexGuard guard(s_threadMap_mutex::get());
76 7442492 : ThreadMap &rThreadMap = s_threadMap::get();
77 7442492 : if (pEnv)
78 : {
79 3816368 : rThreadMap[threadId] = pEnv;
80 : }
81 : else
82 : {
83 3626124 : ThreadMap::iterator iEnv = rThreadMap.find(threadId);
84 3626124 : if( iEnv != rThreadMap.end())
85 1518066 : rThreadMap.erase(iEnv);
86 7442492 : }
87 7442492 : }
88 :
89 5972913 : static uno_Environment * s_getCurrent()
90 : {
91 5972913 : uno_Environment * pEnv = NULL;
92 :
93 5972913 : oslThreadIdentifier threadId = osl::Thread::getCurrentIdentifier();
94 :
95 5972916 : osl::MutexGuard guard(s_threadMap_mutex::get());
96 5972917 : ThreadMap &rThreadMap = s_threadMap::get();
97 5972917 : ThreadMap::iterator iEnv = rThreadMap.find(threadId);
98 5972917 : if(iEnv != rThreadMap.end())
99 2387333 : pEnv = iEnv->second;
100 :
101 5972917 : return pEnv;
102 : }
103 :
104 :
105 48491 : extern "C" void SAL_CALL uno_getCurrentEnvironment(uno_Environment ** ppEnv, rtl_uString * pTypeName)
106 : SAL_THROW_EXTERN_C()
107 : {
108 48491 : if (*ppEnv)
109 : {
110 0 : (*ppEnv)->release(*ppEnv);
111 0 : *ppEnv = NULL;
112 : }
113 :
114 48491 : rtl::OUString currPurpose;
115 :
116 48491 : uno_Environment * pCurrEnv = s_getCurrent();
117 48491 : if (pCurrEnv) // no environment means no purpose
118 1 : currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);
119 :
120 48491 : if (pTypeName && rtl_uString_getLength(pTypeName))
121 : {
122 48491 : rtl::OUString envDcp(pTypeName);
123 48491 : envDcp += currPurpose;
124 :
125 48491 : uno_getEnvironment(ppEnv, envDcp.pData, NULL);
126 : }
127 : else
128 : {
129 0 : if (pCurrEnv)
130 : {
131 0 : *ppEnv = pCurrEnv;
132 0 : (*ppEnv)->acquire(*ppEnv);
133 : }
134 : else
135 : {
136 0 : rtl::OUString uno_envDcp(UNO_LB_UNO);
137 0 : uno_getEnvironment(ppEnv, uno_envDcp.pData, NULL);
138 : }
139 48491 : }
140 48491 : }
141 :
142 3721243 : static rtl::OUString s_getPrefix(rtl::OUString const & str1, rtl::OUString const & str2)
143 : {
144 3721243 : sal_Int32 nIndex1 = 0;
145 3721243 : sal_Int32 nIndex2 = 0;
146 3721243 : sal_Int32 sim = 0;
147 :
148 3721243 : rtl::OUString token1;
149 7442486 : rtl::OUString token2;
150 :
151 5584914 : do
152 : {
153 5584912 : token1 = str1.getToken(0, ':', nIndex1);
154 5584912 : token2 = str2.getToken(0, ':', nIndex2);
155 :
156 5584912 : if (token1.equals(token2))
157 5584912 : sim += token1.getLength() + 1;
158 : }
159 5584914 : while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2));
160 :
161 3721245 : rtl::OUString result;
162 :
163 3721245 : if (sim)
164 3721245 : result = str1.copy(0, sim - 1);
165 :
166 7442487 : return result;
167 : }
168 :
169 3721244 : static int s_getNextEnv(uno_Environment ** ppEnv, uno_Environment * pCurrEnv, uno_Environment * pTargetEnv)
170 : {
171 3721244 : int res = 0;
172 :
173 3721244 : rtl::OUString nextPurpose;
174 :
175 7442490 : rtl::OUString currPurpose;
176 3721246 : if (pCurrEnv)
177 1908184 : currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);
178 :
179 7442486 : rtl::OUString targetPurpose;
180 3721242 : if (pTargetEnv)
181 3721242 : targetPurpose = cppu::EnvDcp::getPurpose(pTargetEnv->pTypeName);
182 :
183 7442485 : rtl::OUString intermPurpose(s_getPrefix(currPurpose, targetPurpose));
184 3721242 : if (currPurpose.getLength() > intermPurpose.getLength())
185 : {
186 44515 : sal_Int32 idx = currPurpose.lastIndexOf(':');
187 44515 : nextPurpose = currPurpose.copy(0, idx);
188 :
189 44515 : res = -1;
190 : }
191 3676727 : else if (intermPurpose.getLength() < targetPurpose.getLength())
192 : {
193 714518 : sal_Int32 idx = targetPurpose.indexOf(':', intermPurpose.getLength() + 1);
194 714518 : if (idx == -1)
195 714518 : nextPurpose = targetPurpose;
196 :
197 : else
198 0 : nextPurpose = targetPurpose.copy(0, idx);
199 :
200 714518 : res = 1;
201 : }
202 :
203 3721242 : if (!nextPurpose.isEmpty())
204 : {
205 714518 : rtl::OUString next_envDcp(UNO_LB_UNO);
206 714518 : next_envDcp += nextPurpose;
207 :
208 714518 : uno_getEnvironment(ppEnv, next_envDcp.pData, NULL);
209 : }
210 : else
211 : {
212 3006724 : if (*ppEnv)
213 0 : (*ppEnv)->release(*ppEnv);
214 :
215 3006724 : *ppEnv = NULL;
216 : }
217 :
218 7442488 : return res;
219 : }
220 :
221 714518 : extern "C" { static void s_pull(va_list * pParam)
222 : {
223 714518 : uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
224 714518 : va_list * pXparam = va_arg(*pParam, va_list *);
225 :
226 714518 : pCallee(pXparam);
227 714518 : }}
228 :
229 714518 : static void s_callInto_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
230 : {
231 714518 : cppu::Enterable * pEnterable = static_cast<cppu::Enterable *>(pEnv->pReserved);
232 714518 : if (pEnterable)
233 714518 : pEnterable->callInto(s_pull, pCallee, pParam);
234 :
235 : else
236 0 : pCallee(pParam);
237 714518 : }
238 :
239 714518 : static void s_callInto(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
240 : {
241 : va_list param;
242 :
243 714518 : va_start(param, pCallee);
244 714518 : s_callInto_v(pEnv, pCallee, ¶m);
245 714518 : va_end(param);
246 714518 : }
247 :
248 44515 : static void s_callOut_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
249 : {
250 44515 : cppu::Enterable * pEnterable = static_cast<cppu::Enterable *>(pEnv->pReserved);
251 44515 : if (pEnterable)
252 44515 : pEnterable->callOut_v(pCallee, pParam);
253 :
254 : else
255 0 : pCallee(pParam);
256 44515 : }
257 :
258 44515 : static void s_callOut(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
259 : {
260 : va_list param;
261 :
262 44515 : va_start(param, pCallee);
263 44515 : s_callOut_v(pEnv, pCallee, ¶m);
264 44515 : va_end(param);
265 44515 : }
266 :
267 : static void s_environment_invoke_v(uno_Environment *, uno_Environment *, uno_EnvCallee *, va_list *);
268 :
269 759033 : extern "C" { static void s_environment_invoke_vv(va_list * pParam)
270 : {
271 759033 : uno_Environment * pCurrEnv = va_arg(*pParam, uno_Environment *);
272 759033 : uno_Environment * pTargetEnv = va_arg(*pParam, uno_Environment *);
273 759033 : uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
274 759033 : va_list * pXparam = va_arg(*pParam, va_list *);
275 :
276 759033 : s_environment_invoke_v(pCurrEnv, pTargetEnv, pCallee, pXparam);
277 759033 : }}
278 :
279 3721246 : static void s_environment_invoke_v(uno_Environment * pCurrEnv, uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
280 : {
281 3721246 : uno_Environment * pNextEnv = NULL;
282 3721246 : switch(s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv))
283 : {
284 : case -1:
285 44515 : s_setCurrent(pNextEnv);
286 44515 : s_callOut(pCurrEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
287 44515 : s_setCurrent(pCurrEnv);
288 44515 : break;
289 :
290 : case 0: {
291 2962212 : uno_Environment * hld = s_getCurrent();
292 2962213 : s_setCurrent(pCurrEnv);
293 2962213 : pCallee(pParam);
294 2962213 : s_setCurrent(hld);
295 : }
296 2962213 : break;
297 :
298 : case 1:
299 714518 : s_setCurrent(pNextEnv);
300 714518 : s_callInto(pNextEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
301 714518 : s_setCurrent(pCurrEnv);
302 714518 : break;
303 : }
304 :
305 3721244 : if (pNextEnv)
306 714518 : pNextEnv->release(pNextEnv);
307 3721244 : }
308 :
309 2962211 : extern "C" void SAL_CALL uno_Environment_invoke_v(uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
310 : SAL_THROW_EXTERN_C()
311 : {
312 2962211 : s_environment_invoke_v(s_getCurrent(), pTargetEnv, pCallee, pParam);
313 2962213 : }
314 :
315 2961627 : extern "C" void SAL_CALL uno_Environment_invoke(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
316 : SAL_THROW_EXTERN_C()
317 : {
318 : va_list param;
319 :
320 2961627 : va_start(param, pCallee);
321 2961627 : uno_Environment_invoke_v(pEnv, pCallee, ¶m);
322 2961629 : va_end(param);
323 2961629 : }
324 :
325 0 : extern "C" void SAL_CALL uno_Environment_enter(uno_Environment * pTargetEnv)
326 : SAL_THROW_EXTERN_C()
327 : {
328 0 : uno_Environment * pNextEnv = NULL;
329 0 : uno_Environment * pCurrEnv = s_getCurrent();
330 :
331 : int res;
332 0 : while ( (res = s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) != 0)
333 : {
334 : cppu::Enterable * pEnterable;
335 :
336 0 : switch(res)
337 : {
338 : case -1:
339 0 : pEnterable = static_cast<cppu::Enterable *>(pCurrEnv->pReserved);
340 0 : if (pEnterable)
341 0 : pEnterable->leave();
342 0 : pCurrEnv->release(pCurrEnv);
343 0 : break;
344 :
345 : case 1:
346 0 : pNextEnv->acquire(pNextEnv);
347 0 : pEnterable = static_cast<cppu::Enterable *>(pNextEnv->pReserved);
348 0 : if (pEnterable)
349 0 : pEnterable->enter();
350 0 : break;
351 : }
352 :
353 0 : s_setCurrent(pNextEnv);
354 0 : pCurrEnv = pNextEnv;
355 : }
356 0 : }
357 :
358 0 : int SAL_CALL uno_Environment_isValid(uno_Environment * pEnv, rtl_uString ** pReason)
359 : SAL_THROW_EXTERN_C()
360 : {
361 0 : int result = 1;
362 :
363 0 : rtl::OUString typeName(cppu::EnvDcp::getTypeName(pEnv->pTypeName));
364 0 : if (typeName == UNO_LB_UNO)
365 : {
366 0 : cppu::Enterable * pEnterable = static_cast<cppu::Enterable *>(pEnv->pReserved);
367 0 : if (pEnterable)
368 0 : result = pEnterable->isValid(reinterpret_cast<rtl::OUString *>(pReason));
369 : }
370 : else
371 : {
372 0 : rtl::OUString envDcp(UNO_LB_UNO);
373 0 : envDcp += cppu::EnvDcp::getPurpose(pEnv->pTypeName);
374 :
375 0 : uno::Environment env(envDcp);
376 :
377 0 : result = env.isValid(reinterpret_cast<rtl::OUString *>(pReason));
378 : }
379 :
380 0 : return result;
381 : }
382 :
383 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|