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