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