1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 #include "uno/environment.hxx"
30 #include "cppu/EnvDcp.hxx"
31 #include "cppu/Enterable.hxx"
33 #include "osl/thread.h"
34 #include "osl/mutex.hxx"
39 using namespace com::sun::star
;
42 struct SAL_DLLPRIVATE oslThreadIdentifier_equal
44 bool operator()(oslThreadIdentifier s1
, oslThreadIdentifier s2
) const;
47 bool oslThreadIdentifier_equal::operator()(oslThreadIdentifier s1
, oslThreadIdentifier s2
) const
49 bool result
= s1
== s2
;
55 struct SAL_DLLPRIVATE oslThreadIdentifier_hash
57 size_t operator()(oslThreadIdentifier s1
) const;
60 size_t oslThreadIdentifier_hash::operator()(oslThreadIdentifier s1
) const
65 typedef ::std::hash_map
<oslThreadIdentifier
,
67 oslThreadIdentifier_hash
,
68 oslThreadIdentifier_equal
> ThreadMap
;
70 static osl::Mutex s_threadMap_mutex
;
71 static ThreadMap s_threadMap
;
74 static rtl::OUString
s_uno_envDcp(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO
));
76 static void s_setCurrent(uno_Environment
* pEnv
)
78 oslThreadIdentifier threadId
= osl_getThreadIdentifier(NULL
);
80 osl::MutexGuard
guard(s_threadMap_mutex
);
82 s_threadMap
[threadId
] = pEnv
;
86 ThreadMap::iterator iEnv
= s_threadMap
.find(threadId
);
87 s_threadMap
.erase(iEnv
);
91 static uno_Environment
* s_getCurrent(void)
93 uno_Environment
* pEnv
= NULL
;
95 oslThreadIdentifier threadId
= osl_getThreadIdentifier(NULL
);
97 osl::MutexGuard
guard(s_threadMap_mutex
);
98 ThreadMap::iterator iEnv
= s_threadMap
.find(threadId
);
99 if(iEnv
!= s_threadMap
.end())
106 extern "C" void SAL_CALL
uno_getCurrentEnvironment(uno_Environment
** ppEnv
, rtl_uString
* pTypeName
)
111 (*ppEnv
)->release(*ppEnv
);
115 rtl::OUString currPurpose
;
117 uno_Environment
* pCurrEnv
= s_getCurrent();
118 if (pCurrEnv
) // no environment means no purpose
119 currPurpose
= cppu::EnvDcp::getPurpose(pCurrEnv
->pTypeName
);
121 if (pTypeName
&& rtl_uString_getLength(pTypeName
))
123 rtl::OUString
envDcp(pTypeName
);
124 envDcp
+= currPurpose
;
126 uno_getEnvironment(ppEnv
, envDcp
.pData
, NULL
);
133 (*ppEnv
)->acquire(*ppEnv
);
136 uno_getEnvironment(ppEnv
, s_uno_envDcp
.pData
, NULL
);
141 static rtl::OUString
s_getPrefix(rtl::OUString
const & str1
, rtl::OUString
const & str2
)
143 sal_Int32 nIndex1
= 0;
144 sal_Int32 nIndex2
= 0;
147 rtl::OUString token1
;
148 rtl::OUString token2
;
152 token1
= str1
.getToken(0, ':', nIndex1
);
153 token2
= str2
.getToken(0, ':', nIndex2
);
155 if (token1
.equals(token2
))
156 sim
+= token1
.getLength() + 1;
158 while(nIndex1
== nIndex2
&& nIndex1
>= 0 && token1
.equals(token2
));
160 rtl::OUString result
;
163 result
= str1
.copy(0, sim
- 1);
168 static int s_getNextEnv(uno_Environment
** ppEnv
, uno_Environment
* pCurrEnv
, uno_Environment
* pTargetEnv
)
172 rtl::OUString nextPurpose
;
174 rtl::OUString currPurpose
;
176 currPurpose
= cppu::EnvDcp::getPurpose(pCurrEnv
->pTypeName
);
178 rtl::OUString targetPurpose
;
180 targetPurpose
= cppu::EnvDcp::getPurpose(pTargetEnv
->pTypeName
);
182 rtl::OUString
intermPurpose(s_getPrefix(currPurpose
, targetPurpose
));
183 if (currPurpose
.getLength() > intermPurpose
.getLength())
185 sal_Int32 idx
= currPurpose
.lastIndexOf(':');
186 nextPurpose
= currPurpose
.copy(0, idx
);
190 else if (intermPurpose
.getLength() < targetPurpose
.getLength())
192 sal_Int32 idx
= targetPurpose
.indexOf(':', intermPurpose
.getLength() + 1);
194 nextPurpose
= targetPurpose
;
197 nextPurpose
= targetPurpose
.copy(0, idx
);
202 if (nextPurpose
.getLength())
204 rtl::OUString
next_envDcp(s_uno_envDcp
);
205 next_envDcp
+= nextPurpose
;
207 uno_getEnvironment(ppEnv
, next_envDcp
.pData
, NULL
);
212 (*ppEnv
)->release(*ppEnv
);
220 extern "C" { static void s_pull(va_list * pParam
)
222 uno_EnvCallee
* pCallee
= va_arg(*pParam
, uno_EnvCallee
*);
223 va_list * pXparam
= va_arg(*pParam
, va_list *);
228 static void s_callInto_v(uno_Environment
* pEnv
, uno_EnvCallee
* pCallee
, va_list * pParam
)
230 cppu::Enterable
* pEnterable
= reinterpret_cast<cppu::Enterable
*>(pEnv
->pReserved
);
232 pEnterable
->callInto(s_pull
, pCallee
, pParam
);
238 static void s_callInto(uno_Environment
* pEnv
, uno_EnvCallee
* pCallee
, ...)
242 va_start(param
, pCallee
);
243 s_callInto_v(pEnv
, pCallee
, ¶m
);
247 static void s_callOut_v(uno_Environment
* pEnv
, uno_EnvCallee
* pCallee
, va_list * pParam
)
249 cppu::Enterable
* pEnterable
= reinterpret_cast<cppu::Enterable
*>(pEnv
->pReserved
);
251 pEnterable
->callOut_v(pCallee
, pParam
);
257 static void s_callOut(uno_Environment
* pEnv
, uno_EnvCallee
* pCallee
, ...)
261 va_start(param
, pCallee
);
262 s_callOut_v(pEnv
, pCallee
, ¶m
);
266 static void s_environment_invoke_v(uno_Environment
*, uno_Environment
*, uno_EnvCallee
*, va_list *);
268 extern "C" { static void s_environment_invoke_vv(va_list * pParam
)
270 uno_Environment
* pCurrEnv
= va_arg(*pParam
, uno_Environment
*);
271 uno_Environment
* pTargetEnv
= va_arg(*pParam
, uno_Environment
*);
272 uno_EnvCallee
* pCallee
= va_arg(*pParam
, uno_EnvCallee
*);
273 va_list * pXparam
= va_arg(*pParam
, va_list *);
275 s_environment_invoke_v(pCurrEnv
, pTargetEnv
, pCallee
, pXparam
);
278 static void s_environment_invoke_v(uno_Environment
* pCurrEnv
, uno_Environment
* pTargetEnv
, uno_EnvCallee
* pCallee
, va_list * pParam
)
280 uno_Environment
* pNextEnv
= NULL
;
281 switch(s_getNextEnv(&pNextEnv
, pCurrEnv
, pTargetEnv
))
284 s_setCurrent(pNextEnv
);
285 s_callOut(pCurrEnv
, s_environment_invoke_vv
, pNextEnv
, pTargetEnv
, pCallee
, pParam
);
286 s_setCurrent(pCurrEnv
);
290 uno_Environment
* hld
= s_getCurrent();
291 s_setCurrent(pCurrEnv
);
298 s_setCurrent(pNextEnv
);
299 s_callInto(pNextEnv
, s_environment_invoke_vv
, pNextEnv
, pTargetEnv
, pCallee
, pParam
);
300 s_setCurrent(pCurrEnv
);
305 pNextEnv
->release(pNextEnv
);
308 extern "C" void SAL_CALL
uno_Environment_invoke_v(uno_Environment
* pTargetEnv
, uno_EnvCallee
* pCallee
, va_list * pParam
)
311 s_environment_invoke_v(s_getCurrent(), pTargetEnv
, pCallee
, pParam
);
314 extern "C" void SAL_CALL
uno_Environment_invoke(uno_Environment
* pEnv
, uno_EnvCallee
* pCallee
, ...)
319 va_start(param
, pCallee
);
320 uno_Environment_invoke_v(pEnv
, pCallee
, ¶m
);
324 extern "C" void SAL_CALL
uno_Environment_enter(uno_Environment
* pTargetEnv
)
327 uno_Environment
* pNextEnv
= NULL
;
328 uno_Environment
* pCurrEnv
= s_getCurrent();
331 while ( (res
= s_getNextEnv(&pNextEnv
, pCurrEnv
, pTargetEnv
)) != 0)
333 cppu::Enterable
* pEnterable
;
338 pEnterable
= reinterpret_cast<cppu::Enterable
*>(pCurrEnv
->pReserved
);
341 pCurrEnv
->release(pCurrEnv
);
345 pNextEnv
->acquire(pNextEnv
);
346 pEnterable
= reinterpret_cast<cppu::Enterable
*>(pNextEnv
->pReserved
);
352 s_setCurrent(pNextEnv
);
357 int SAL_CALL
uno_Environment_isValid(uno_Environment
* pEnv
, rtl_uString
** pReason
)
362 rtl::OUString
typeName(cppu::EnvDcp::getTypeName(pEnv
->pTypeName
));
363 if (typeName
.equals(s_uno_envDcp
))
365 cppu::Enterable
* pEnterable
= reinterpret_cast<cppu::Enterable
*>(pEnv
->pReserved
);
367 result
= pEnterable
->isValid((rtl::OUString
*)pReason
);
371 rtl::OUString
envDcp(s_uno_envDcp
);
372 envDcp
+= cppu::EnvDcp::getPurpose(pEnv
->pTypeName
);
374 uno::Environment
env(envDcp
);
376 result
= env
.isValid((rtl::OUString
*)pReason
);