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/mapping.hxx"
24 #include "uno/dispatcher.h"
26 #include "cppu/EnvDcp.hxx"
29 #ifdef LOG_LIFECYLE_MediatorMapping
31 # define LOG_LIFECYLE_MediatorMapping_emit(x) x
34 # define LOG_LIFECYLE_MediatorMapping_emit(x)
39 using namespace com::sun::star
;
41 class MediatorMapping
: public uno_Mapping
43 oslInterlockedCount m_refCount
;
45 uno::Mapping m_from2uno
;
46 uno::Mapping m_uno2to
;
48 uno::Environment m_from
;
49 uno::Environment m_interm
;
50 uno::Environment m_to
;
56 void mapInterface(void ** ppOut
,
58 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
);
59 MediatorMapping(uno_Environment
* pFrom
,
60 uno_Environment
* pInterm
,
61 uno_Environment
* pTo
);
66 static void SAL_CALL
s_acquire(uno_Mapping
* mapping
)
68 MediatorMapping
* pMediatorMapping
= static_cast<MediatorMapping
*>(mapping
);
69 pMediatorMapping
->acquire();
72 static void SAL_CALL
s_release(uno_Mapping
* mapping
)
74 MediatorMapping
* pMediatorMapping
= static_cast<MediatorMapping
*>(mapping
);
75 pMediatorMapping
->release();
78 static void SAL_CALL
s_mapInterface(
79 uno_Mapping
* mapping
,
82 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
)
84 MediatorMapping
* pMediatorMapping
= static_cast<MediatorMapping
*>(mapping
);
85 pMediatorMapping
->mapInterface(ppOut
, pInterface
, pInterfaceTypeDescr
);
89 MediatorMapping::MediatorMapping(uno_Environment
* pFrom
,
90 uno_Environment
* pInterm
,
91 uno_Environment
* pTo
)
93 m_from2uno(pFrom
, pInterm
),
94 m_uno2to (pInterm
, pTo
),
99 LOG_LIFECYLE_MediatorMapping_emit(std::cerr
<< __FUNCTION__
<< std::endl
);
101 if (!m_from2uno
.get() || !m_uno2to
.get())
104 uno_Mapping::acquire
= s_acquire
;
105 uno_Mapping::release
= s_release
;
106 uno_Mapping::mapInterface
= s_mapInterface
;
109 MediatorMapping::~MediatorMapping()
111 LOG_LIFECYLE_MediatorMapping_emit(std::cerr
<< __FUNCTION__
<< std::endl
);
114 void MediatorMapping::acquire(void)
116 LOG_LIFECYLE_MediatorMapping_emit(std::cerr
<< __FUNCTION__
<< std::endl
);
118 osl_atomic_increment(&m_refCount
);
121 void MediatorMapping::release(void)
123 LOG_LIFECYLE_MediatorMapping_emit(std::cerr
<< __FUNCTION__
<< std::endl
);
125 if (osl_atomic_decrement(&m_refCount
) == 0)
127 ::uno_revokeMapping(this);
131 extern "C" { static void s_mapInterface_v(va_list * pParam
)
133 void ** ppOut
= va_arg(*pParam
, void **);
134 void * pInterface
= va_arg(*pParam
, void *);
135 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
= va_arg(*pParam
, typelib_InterfaceTypeDescription
*);
136 uno_Mapping
* pMapping
= va_arg(*pParam
, uno_Mapping
*);
138 pMapping
->mapInterface(pMapping
, ppOut
, pInterface
, pInterfaceTypeDescr
);
141 void MediatorMapping::mapInterface(
144 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
)
148 uno_ExtEnvironment
* env
= m_to
.get()->pExtEnv
;
149 OSL_ASSERT( env
!= 0 );
150 env
->releaseInterface( env
, *ppOut
);
155 uno_Interface
* pUnoI
= 0;
157 m_from
.invoke(s_mapInterface_v
, &pUnoI
, pInterface
, pInterfaceTypeDescr
, m_from2uno
.get());
159 m_uno2to
.mapInterface(&ret
, pUnoI
, pInterfaceTypeDescr
);
162 m_interm
.get()->pExtEnv
->releaseInterface(m_interm
.get()->pExtEnv
, pUnoI
);
167 extern "C" { static void SAL_CALL
s_MediatorMapping_free(uno_Mapping
* pMapping
)
170 delete static_cast<MediatorMapping
*>(pMapping
);
175 static rtl::OUString
getPrefix(rtl::OUString
const & str1
, rtl::OUString
const & str2
)
177 sal_Int32 nIndex1
= 0;
178 sal_Int32 nIndex2
= 0;
181 rtl::OUString token1
;
182 rtl::OUString token2
;
186 token1
= str1
.getToken(0, ':', nIndex1
);
187 token2
= str2
.getToken(0, ':', nIndex2
);
189 if (token1
.equals(token2
))
190 sim
+= token1
.getLength() + 1;
192 while(nIndex1
== nIndex2
&& nIndex1
>= 0 && token1
.equals(token2
));
194 rtl::OUString result
;
197 result
= str1
.copy(0, sim
- 1);
202 // rtl::OUString str1(RTL_CONSTASCII_USTRINGPARAM("abc:def:ghi"));
203 // rtl::OUString str2(RTL_CONSTASCII_USTRINGPARAM("abc:def"));
204 // rtl::OUString str3(RTL_CONSTASCII_USTRINGPARAM("abc"));
205 // rtl::OUString str4(RTL_CONSTASCII_USTRINGPARAM(""));
207 // rtl::OUString pref;
209 // pref = getPrefix(str1, str1);
210 // pref = getPrefix(str1, str2);
211 // pref = getPrefix(str1, str3);
212 // pref = getPrefix(str1, str4);
214 // pref = getPrefix(str2, str1);
215 // pref = getPrefix(str3, str1);
216 // pref = getPrefix(str4, str1);
219 void getCascadeMapping(uno_Mapping
** ppMapping
,
220 uno_Environment
* pFrom
,
221 uno_Environment
* pTo
,
222 rtl_uString
* pAddPurpose
)
224 if (pAddPurpose
&& pAddPurpose
->length
)
227 rtl::OUString
uno_envType(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO
));
229 rtl::OUString from_envType
= cppu::EnvDcp::getTypeName(pFrom
->pTypeName
);
230 rtl::OUString to_envType
= cppu::EnvDcp::getTypeName(pTo
->pTypeName
);
231 rtl::OUString from_envPurpose
= cppu::EnvDcp::getPurpose(pFrom
->pTypeName
);
232 rtl::OUString to_envPurpose
= cppu::EnvDcp::getPurpose(pTo
->pTypeName
);
234 #ifdef LOG_CALLING_named_purpose_getMapping
235 rtl::OString s_from_name
= rtl::OUStringToOString(pFrom
->pTypeName
, RTL_TEXTENCODING_ASCII_US
);
236 rtl::OString s_to_name
= rtl::OUStringToOString(pTo
->pTypeName
, RTL_TEXTENCODING_ASCII_US
);
238 std::cerr
<< __FUNCTION__
<< " - creating mediation ";
239 std::cerr
<< "pFrom: " << s_from_name
.getStr();
240 std::cerr
<<" pTo: " << s_to_name
.getStr() << std::endl
;
243 if (from_envPurpose
== to_envPurpose
) // gcc:bla => uno:bla
246 // reaching this point means, we need a mediated mapping!!!
247 // we generall mediate via uno[:free]
248 uno_Environment
* pInterm
= NULL
;
250 // chained uno -> uno
251 if (from_envType
== uno_envType
&& to_envType
== uno_envType
)
253 rtl::OUString purpose
= getPrefix(from_envPurpose
, to_envPurpose
);
255 rtl::OUString uno_envDcp
= uno_envType
;
256 uno_envDcp
+= purpose
;
258 // direct mapping possible?
259 // uno:bla-->uno:bla:blubb
260 if (from_envPurpose
.equals(purpose
))
262 rtl::OUString rest
= to_envPurpose
.copy(purpose
.getLength());
264 sal_Int32 index
= rest
.indexOf(':', 1);
267 uno_getMapping(ppMapping
, pFrom
, pTo
, rest
.copy(1).pData
);
271 uno_envDcp
+= rest
.copy(0, index
);
273 else if (to_envPurpose
.equals(purpose
))
275 rtl::OUString rest
= from_envPurpose
.copy(purpose
.getLength());
277 sal_Int32 index
= rest
.indexOf(':', 1);
280 uno_getMapping(ppMapping
, pFrom
, pTo
, rest
.copy(1).pData
);
284 uno_envDcp
+= rest
.copy(0, index
);
287 uno_getEnvironment(&pInterm
, uno_envDcp
.pData
, NULL
);
289 else if (from_envType
!= uno_envType
&& to_envType
== uno_envType
) // <ANY> -> UNO ?
290 // mediate via uno:purpose(fromEnv)
292 rtl::OUString envDcp
= uno_envType
;
294 envDcp
+= from_envPurpose
;
295 uno_getEnvironment(&pInterm
, envDcp
.pData
, NULL
);
297 else if (from_envType
== uno_envType
&& to_envType
!= uno_envType
) // UNO -> <ANY>?
298 // mediate via uno(context)
300 rtl::OUString envDcp
= uno_envType
;
302 envDcp
+= to_envPurpose
;
303 uno_getEnvironment(&pInterm
, envDcp
.pData
, NULL
);
305 else // everything else
306 // mediate via uno:purpose
308 rtl::OUString purpose
= getPrefix(from_envPurpose
, to_envPurpose
);
310 rtl::OUString uno_envDcp
= uno_envType
;
311 uno_envDcp
+= purpose
;
313 uno_getEnvironment(&pInterm
, uno_envDcp
.pData
, NULL
);
316 uno_Mapping
* pMapping
= new MediatorMapping(pFrom
, pInterm
, pTo
);
317 pInterm
->release(pInterm
);
320 pMapping
->acquire(pMapping
);
322 ::uno_registerMapping(&pMapping
, s_MediatorMapping_free
, pFrom
, pTo
, pAddPurpose
);
325 (*ppMapping
)->release(*ppMapping
);
327 *ppMapping
= pMapping
;
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */