1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <osl/interlck.h>
21 #include <rtl/ustring.hxx>
22 #include <uno/environment.hxx>
23 #include <uno/lbnames.h>
24 #include <uno/mapping.hxx>
25 #include <uno/dispatcher.h>
26 #include <o3tl/string_view.hxx>
28 #include <cppu/EnvDcp.hxx>
30 #include "cascade_mapping.hxx"
32 using namespace com::sun::star
;
36 class MediatorMapping
: public uno_Mapping
38 oslInterlockedCount m_refCount
;
40 uno::Mapping m_from2uno
;
41 uno::Mapping m_uno2to
;
43 uno::Environment m_from
;
44 uno::Environment m_interm
;
45 uno::Environment m_to
;
51 void mapInterface(void ** ppOut
,
53 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
);
54 MediatorMapping(uno_Environment
* pFrom
,
55 uno_Environment
* pInterm
,
56 uno_Environment
* pTo
);
62 static void s_acquire(uno_Mapping
* mapping
)
64 MediatorMapping
* pMediatorMapping
= static_cast<MediatorMapping
*>(mapping
);
65 pMediatorMapping
->acquire();
68 static void s_release(uno_Mapping
* mapping
)
70 MediatorMapping
* pMediatorMapping
= static_cast<MediatorMapping
*>(mapping
);
71 pMediatorMapping
->release();
74 static void s_mapInterface(
75 uno_Mapping
* mapping
,
78 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
)
80 MediatorMapping
* pMediatorMapping
= static_cast<MediatorMapping
*>(mapping
);
81 pMediatorMapping
->mapInterface(ppOut
, pInterface
, pInterfaceTypeDescr
);
85 MediatorMapping::MediatorMapping(uno_Environment
* pFrom
,
86 uno_Environment
* pInterm
,
87 uno_Environment
* pTo
)
89 m_from2uno(pFrom
, pInterm
),
90 m_uno2to (pInterm
, pTo
),
95 if (!m_from2uno
.get() || !m_uno2to
.get())
98 uno_Mapping::acquire
= s_acquire
;
99 uno_Mapping::release
= s_release
;
100 uno_Mapping::mapInterface
= s_mapInterface
;
103 void MediatorMapping::acquire()
105 osl_atomic_increment(&m_refCount
);
108 void MediatorMapping::release()
110 if (osl_atomic_decrement(&m_refCount
) == 0)
112 ::uno_revokeMapping(this);
116 extern "C" { static void s_mapInterface_v(va_list * pParam
)
118 void ** ppOut
= va_arg(*pParam
, void **);
119 void * pInterface
= va_arg(*pParam
, void *);
120 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
= va_arg(*pParam
, typelib_InterfaceTypeDescription
*);
121 uno_Mapping
* pMapping
= va_arg(*pParam
, uno_Mapping
*);
123 pMapping
->mapInterface(pMapping
, ppOut
, pInterface
, pInterfaceTypeDescr
);
126 void MediatorMapping::mapInterface(
129 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
)
131 if (*ppOut
!= nullptr)
133 uno_ExtEnvironment
* env
= m_to
.get()->pExtEnv
;
134 assert(env
!= nullptr);
135 env
->releaseInterface( env
, *ppOut
);
139 void * ret
= nullptr;
140 uno_Interface
* pUnoI
= nullptr;
142 m_from
.invoke(s_mapInterface_v
, &pUnoI
, pInterface
, pInterfaceTypeDescr
, m_from2uno
.get());
144 m_uno2to
.mapInterface(&ret
, pUnoI
, pInterfaceTypeDescr
);
147 m_interm
.get()->pExtEnv
->releaseInterface(m_interm
.get()->pExtEnv
, pUnoI
);
152 extern "C" { static void s_MediatorMapping_free(uno_Mapping
* pMapping
) noexcept
154 delete static_cast<MediatorMapping
*>(pMapping
);
158 static OUString
getPrefix(std::u16string_view str1
, std::u16string_view str2
)
160 sal_Int32 nIndex1
= 0;
161 sal_Int32 nIndex2
= 0;
164 std::u16string_view token1
;
165 std::u16string_view token2
;
169 token1
= o3tl::getToken(str1
, 0, ':', nIndex1
);
170 token2
= o3tl::getToken(str2
, 0, ':', nIndex2
);
172 if (token1
== token2
)
173 sim
+= token1
.size() + 1;
175 while(nIndex1
== nIndex2
&& nIndex1
>= 0 && token1
== token2
);
180 result
= str1
.substr(0, sim
- 1);
185 // OUString str1("abc:def:ghi");
186 // OUString str2("abc:def");
187 // OUString str3("abc");
188 // OUString str4("");
192 // pref = getPrefix(str1, str1);
193 // pref = getPrefix(str1, str2);
194 // pref = getPrefix(str1, str3);
195 // pref = getPrefix(str1, str4);
197 // pref = getPrefix(str2, str1);
198 // pref = getPrefix(str3, str1);
199 // pref = getPrefix(str4, str1);
202 void getCascadeMapping(uno_Mapping
** ppMapping
,
203 uno_Environment
* pFrom
,
204 uno_Environment
* pTo
,
205 rtl_uString
* pAddPurpose
)
207 if (pAddPurpose
&& pAddPurpose
->length
)
210 OUString
uno_envType(u
"" UNO_LB_UNO
""_ustr
);
212 OUString from_envType
= cppu::EnvDcp::getTypeName(pFrom
->pTypeName
);
213 OUString to_envType
= cppu::EnvDcp::getTypeName(pTo
->pTypeName
);
214 OUString from_envPurpose
= cppu::EnvDcp::getPurpose(pFrom
->pTypeName
);
215 OUString to_envPurpose
= cppu::EnvDcp::getPurpose(pTo
->pTypeName
);
217 #ifdef LOG_CALLING_named_purpose_getMapping
218 OString s_from_name
= OUStringToOString(pFrom
->pTypeName
, RTL_TEXTENCODING_ASCII_US
);
219 OString s_to_name
= OUStringToOString(pTo
->pTypeName
, RTL_TEXTENCODING_ASCII_US
);
221 std::cerr
<< __FUNCTION__
<< " - creating mediation ";
222 std::cerr
<< "pFrom: " << s_from_name
.getStr();
223 std::cerr
<<" pTo: " << s_to_name
.getStr() << std::endl
;
226 if (from_envPurpose
== to_envPurpose
) // gcc:bla => uno:bla
229 // reaching this point means, we need a mediated mapping!!!
230 // we generally mediate via uno[:free]
231 uno_Environment
* pInterm
= nullptr;
233 // chained uno -> uno
234 if (from_envType
== uno_envType
&& to_envType
== uno_envType
)
236 OUString purpose
= getPrefix(from_envPurpose
, to_envPurpose
);
238 OUString uno_envDcp
= uno_envType
+ purpose
;
240 // direct mapping possible?
241 // uno:bla-->uno:bla:blubb
242 if (from_envPurpose
== purpose
)
244 OUString rest
= to_envPurpose
.copy(purpose
.getLength());
246 sal_Int32 index
= rest
.indexOf(':', 1);
249 uno_getMapping(ppMapping
, pFrom
, pTo
, rest
.copy(1).pData
);
253 uno_envDcp
+= rest
.subView(0, index
);
255 else if (to_envPurpose
== purpose
)
257 OUString rest
= from_envPurpose
.copy(purpose
.getLength());
259 sal_Int32 index
= rest
.indexOf(':', 1);
262 uno_getMapping(ppMapping
, pFrom
, pTo
, rest
.copy(1).pData
);
266 uno_envDcp
+= rest
.subView(0, index
);
269 uno_getEnvironment(&pInterm
, uno_envDcp
.pData
, nullptr);
271 else if (from_envType
!= uno_envType
&& to_envType
== uno_envType
) // <ANY> -> UNO ?
272 // mediate via uno:purpose(fromEnv)
274 OUString envDcp
= uno_envType
+ from_envPurpose
;
275 uno_getEnvironment(&pInterm
, envDcp
.pData
, nullptr);
277 else if (from_envType
== uno_envType
&& to_envType
!= uno_envType
) // UNO -> <ANY>?
278 // mediate via uno(context)
280 OUString envDcp
= uno_envType
+ to_envPurpose
;
281 uno_getEnvironment(&pInterm
, envDcp
.pData
, nullptr);
283 else // everything else
284 // mediate via uno:purpose
286 OUString purpose
= getPrefix(from_envPurpose
, to_envPurpose
);
288 OUString uno_envDcp
= uno_envType
+ purpose
;
290 uno_getEnvironment(&pInterm
, uno_envDcp
.pData
, nullptr);
293 uno_Mapping
* pMapping
= new MediatorMapping(pFrom
, pInterm
, pTo
);
294 pInterm
->release(pInterm
);
297 pMapping
->acquire(pMapping
);
299 ::uno_registerMapping(&pMapping
, s_MediatorMapping_free
, pFrom
, pTo
, pAddPurpose
);
302 (*ppMapping
)->release(*ppMapping
);
304 *ppMapping
= pMapping
;
307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */