1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cascade_mapping.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
33 #include "osl/interlck.h"
34 #include "rtl/ustring.hxx"
35 #include "uno/environment.hxx"
36 #include "uno/mapping.hxx"
37 #include "uno/dispatcher.h"
39 //#include "cascade_mappping.hxx"
40 #include "cppu/EnvDcp.hxx"
43 //#define LOG_CALLING_named_purpose_getMapping
45 //#define LOG_LIFECYLE_MediatorMapping
46 #ifdef LOG_LIFECYLE_MediatorMapping
47 # define LOG_LIFECYLE_MediatorMapping_emit(x) x
50 # define LOG_LIFECYLE_MediatorMapping_emit(x)
55 using namespace com::sun::star
;
57 class MediatorMapping
: public uno_Mapping
59 oslInterlockedCount m_refCount
;
61 uno::Mapping m_from2uno
;
62 uno::Mapping m_uno2to
;
64 uno::Environment m_from
;
65 uno::Environment m_interm
;
66 uno::Environment m_to
;
72 void mapInterface(void ** ppOut
,
74 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
);
75 MediatorMapping(uno_Environment
* pFrom
,
76 uno_Environment
* pInterm
,
77 uno_Environment
* pTo
);
82 static void SAL_CALL
s_acquire(uno_Mapping
* mapping
)
84 MediatorMapping
* pMediatorMapping
= static_cast<MediatorMapping
*>(mapping
);
85 pMediatorMapping
->acquire();
88 static void SAL_CALL
s_release(uno_Mapping
* mapping
)
90 MediatorMapping
* pMediatorMapping
= static_cast<MediatorMapping
*>(mapping
);
91 pMediatorMapping
->release();
94 static void SAL_CALL
s_mapInterface(
95 uno_Mapping
* mapping
,
98 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
)
100 MediatorMapping
* pMediatorMapping
= static_cast<MediatorMapping
*>(mapping
);
101 pMediatorMapping
->mapInterface(ppOut
, pInterface
, pInterfaceTypeDescr
);
105 MediatorMapping::MediatorMapping(uno_Environment
* pFrom
,
106 uno_Environment
* pInterm
,
107 uno_Environment
* pTo
)
109 m_from2uno(pFrom
, pInterm
),
110 m_uno2to (pInterm
, pTo
),
115 LOG_LIFECYLE_MediatorMapping_emit(std::cerr
<< __FUNCTION__
<< std::endl
);
117 if (!m_from2uno
.get() || !m_uno2to
.get())
120 uno_Mapping::acquire
= s_acquire
;
121 uno_Mapping::release
= s_release
;
122 uno_Mapping::mapInterface
= s_mapInterface
;
125 MediatorMapping::~MediatorMapping()
127 LOG_LIFECYLE_MediatorMapping_emit(std::cerr
<< __FUNCTION__
<< std::endl
);
130 void MediatorMapping::acquire(void)
132 LOG_LIFECYLE_MediatorMapping_emit(std::cerr
<< __FUNCTION__
<< std::endl
);
134 osl_incrementInterlockedCount(&m_refCount
);
137 void MediatorMapping::release(void)
139 LOG_LIFECYLE_MediatorMapping_emit(std::cerr
<< __FUNCTION__
<< std::endl
);
141 if (osl_decrementInterlockedCount(&m_refCount
) == 0)
143 ::uno_revokeMapping(this);
147 extern "C" { static void s_mapInterface_v(va_list * pParam
)
149 void ** ppOut
= va_arg(*pParam
, void **);
150 void * pInterface
= va_arg(*pParam
, void *);
151 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
= va_arg(*pParam
, typelib_InterfaceTypeDescription
*);
152 uno_Mapping
* pMapping
= va_arg(*pParam
, uno_Mapping
*);
154 pMapping
->mapInterface(pMapping
, ppOut
, pInterface
, pInterfaceTypeDescr
);
157 void MediatorMapping::mapInterface(
160 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
)
164 uno_ExtEnvironment
* env
= m_to
.get()->pExtEnv
;
165 OSL_ASSERT( env
!= 0 );
166 env
->releaseInterface( env
, *ppOut
);
171 uno_Interface
* pUnoI
= 0;
173 m_from
.invoke(s_mapInterface_v
, &pUnoI
, pInterface
, pInterfaceTypeDescr
, m_from2uno
.get());
175 m_uno2to
.mapInterface(&ret
, pUnoI
, pInterfaceTypeDescr
);
178 m_interm
.get()->pExtEnv
->releaseInterface(m_interm
.get()->pExtEnv
, pUnoI
);
183 extern "C" { static void SAL_CALL
s_MediatorMapping_free(uno_Mapping
* pMapping
)
186 delete static_cast<MediatorMapping
*>(pMapping
);
191 static rtl::OUString
getPrefix(rtl::OUString
const & str1
, rtl::OUString
const & str2
)
193 sal_Int32 nIndex1
= 0;
194 sal_Int32 nIndex2
= 0;
197 rtl::OUString token1
;
198 rtl::OUString token2
;
202 token1
= str1
.getToken(0, ':', nIndex1
);
203 token2
= str2
.getToken(0, ':', nIndex2
);
205 if (token1
.equals(token2
))
206 sim
+= token1
.getLength() + 1;
208 while(nIndex1
== nIndex2
&& nIndex1
>= 0 && token1
.equals(token2
));
210 rtl::OUString result
;
213 result
= str1
.copy(0, sim
- 1);
218 // rtl::OUString str1(RTL_CONSTASCII_USTRINGPARAM("abc:def:ghi"));
219 // rtl::OUString str2(RTL_CONSTASCII_USTRINGPARAM("abc:def"));
220 // rtl::OUString str3(RTL_CONSTASCII_USTRINGPARAM("abc"));
221 // rtl::OUString str4(RTL_CONSTASCII_USTRINGPARAM(""));
223 // rtl::OUString pref;
225 // pref = getPrefix(str1, str1);
226 // pref = getPrefix(str1, str2);
227 // pref = getPrefix(str1, str3);
228 // pref = getPrefix(str1, str4);
230 // pref = getPrefix(str2, str1);
231 // pref = getPrefix(str3, str1);
232 // pref = getPrefix(str4, str1);
235 void getCascadeMapping(uno_Mapping
** ppMapping
,
236 uno_Environment
* pFrom
,
237 uno_Environment
* pTo
,
238 rtl_uString
* pAddPurpose
)
240 if (pAddPurpose
&& pAddPurpose
->length
)
243 rtl::OUString
uno_envType(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO
));
245 rtl::OUString from_envType
= cppu::EnvDcp::getTypeName(pFrom
->pTypeName
);
246 rtl::OUString to_envType
= cppu::EnvDcp::getTypeName(pTo
->pTypeName
);
247 rtl::OUString from_envPurpose
= cppu::EnvDcp::getPurpose(pFrom
->pTypeName
);
248 rtl::OUString to_envPurpose
= cppu::EnvDcp::getPurpose(pTo
->pTypeName
);
250 #ifdef LOG_CALLING_named_purpose_getMapping
251 rtl::OString s_from_name
= rtl::OUStringToOString(pFrom
->pTypeName
, RTL_TEXTENCODING_ASCII_US
);
252 rtl::OString s_to_name
= rtl::OUStringToOString(pTo
->pTypeName
, RTL_TEXTENCODING_ASCII_US
);
254 std::cerr
<< __FUNCTION__
<< " - creating mediation ";
255 std::cerr
<< "pFrom: " << s_from_name
.getStr();
256 std::cerr
<<" pTo: " << s_to_name
.getStr() << std::endl
;
259 if (from_envPurpose
== to_envPurpose
) // gcc:bla => uno:bla
262 // reaching this point means, we need a mediated mapping!!!
263 // we generall mediate via uno[:free]
264 uno_Environment
* pInterm
= NULL
;
266 // chained uno -> uno
267 if (from_envType
== uno_envType
&& to_envType
== uno_envType
)
269 rtl::OUString purpose
= getPrefix(from_envPurpose
, to_envPurpose
);
271 rtl::OUString uno_envDcp
= uno_envType
;
272 uno_envDcp
+= purpose
;
274 // direct mapping possible?
275 // uno:bla-->uno:bla:blubb
276 if (from_envPurpose
.equals(purpose
))
278 rtl::OUString rest
= to_envPurpose
.copy(purpose
.getLength());
280 sal_Int32 index
= rest
.indexOf(':', 1);
283 uno_getMapping(ppMapping
, pFrom
, pTo
, rest
.copy(1).pData
);
287 uno_envDcp
+= rest
.copy(0, index
);
289 else if (to_envPurpose
.equals(purpose
))
291 rtl::OUString rest
= from_envPurpose
.copy(purpose
.getLength());
293 sal_Int32 index
= rest
.indexOf(':', 1);
296 uno_getMapping(ppMapping
, pFrom
, pTo
, rest
.copy(1).pData
);
300 uno_envDcp
+= rest
.copy(0, index
);
303 uno_getEnvironment(&pInterm
, uno_envDcp
.pData
, NULL
);
305 else if (from_envType
!= uno_envType
&& to_envType
== uno_envType
) // <ANY> -> UNO ?
306 // mediate via uno:purpose(fromEnv)
308 rtl::OUString envDcp
= uno_envType
;
310 envDcp
+= from_envPurpose
;
311 uno_getEnvironment(&pInterm
, envDcp
.pData
, NULL
);
313 else if (from_envType
== uno_envType
&& to_envType
!= uno_envType
) // UNO -> <ANY>?
314 // mediate via uno(context)
316 rtl::OUString envDcp
= uno_envType
;
318 envDcp
+= to_envPurpose
;
319 uno_getEnvironment(&pInterm
, envDcp
.pData
, NULL
);
321 else // everything else
322 // mediate via uno:purpose
324 rtl::OUString purpose
= getPrefix(from_envPurpose
, to_envPurpose
);
326 rtl::OUString uno_envDcp
= uno_envType
;
327 uno_envDcp
+= purpose
;
329 uno_getEnvironment(&pInterm
, uno_envDcp
.pData
, NULL
);
332 uno_Mapping
* pMapping
= new MediatorMapping(pFrom
, pInterm
, pTo
);
333 pInterm
->release(pInterm
);
336 pMapping
->acquire(pMapping
);
338 ::uno_registerMapping(&pMapping
, s_MediatorMapping_free
, pFrom
, pTo
, pAddPurpose
);
341 (*ppMapping
)->release(*ppMapping
);
343 *ppMapping
= pMapping
;