merged tag ooo/DEV300_m102
[LibreOffice.git] / cppu / source / uno / cascade_mapping.cxx
blobee870a52e286eaea9aad62af06ad19126f0bb743
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 <iostream>
30 #include "osl/interlck.h"
31 #include "rtl/ustring.hxx"
32 #include "uno/environment.hxx"
33 #include "uno/mapping.hxx"
34 #include "uno/dispatcher.h"
36 //#include "cascade_mappping.hxx"
37 #include "cppu/EnvDcp.hxx"
40 //#define LOG_CALLING_named_purpose_getMapping
42 //#define LOG_LIFECYLE_MediatorMapping
43 #ifdef LOG_LIFECYLE_MediatorMapping
44 # define LOG_LIFECYLE_MediatorMapping_emit(x) x
46 #else
47 # define LOG_LIFECYLE_MediatorMapping_emit(x)
49 #endif
52 using namespace com::sun::star;
54 class MediatorMapping : public uno_Mapping
56 oslInterlockedCount m_refCount;
58 uno::Mapping m_from2uno;
59 uno::Mapping m_uno2to;
61 uno::Environment m_from;
62 uno::Environment m_interm;
63 uno::Environment m_to;
65 public:
66 void acquire(void);
67 void release(void);
69 void mapInterface(void ** ppOut,
70 void * pInterface,
71 typelib_InterfaceTypeDescription * pInterfaceTypeDescr);
72 MediatorMapping(uno_Environment * pFrom,
73 uno_Environment * pInterm,
74 uno_Environment * pTo);
75 ~MediatorMapping();
78 extern "C" {
79 static void SAL_CALL s_acquire(uno_Mapping * mapping)
81 MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
82 pMediatorMapping->acquire();
85 static void SAL_CALL s_release(uno_Mapping * mapping)
87 MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
88 pMediatorMapping->release();
91 static void SAL_CALL s_mapInterface(
92 uno_Mapping * mapping,
93 void ** ppOut,
94 void * pInterface,
95 typelib_InterfaceTypeDescription * pInterfaceTypeDescr)
97 MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
98 pMediatorMapping->mapInterface(ppOut, pInterface, pInterfaceTypeDescr);
102 MediatorMapping::MediatorMapping(uno_Environment * pFrom,
103 uno_Environment * pInterm,
104 uno_Environment * pTo)
105 : m_refCount(0),
106 m_from2uno(pFrom, pInterm),
107 m_uno2to (pInterm, pTo),
108 m_from (pFrom),
109 m_interm (pInterm),
110 m_to (pTo)
112 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
114 if (!m_from2uno.get() || !m_uno2to.get())
115 abort();
117 uno_Mapping::acquire = s_acquire;
118 uno_Mapping::release = s_release;
119 uno_Mapping::mapInterface = s_mapInterface;
122 MediatorMapping::~MediatorMapping()
124 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
127 void MediatorMapping::acquire(void)
129 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
131 osl_incrementInterlockedCount(&m_refCount);
134 void MediatorMapping::release(void)
136 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
138 if (osl_decrementInterlockedCount(&m_refCount) == 0)
140 ::uno_revokeMapping(this);
144 extern "C" { static void s_mapInterface_v(va_list * pParam)
146 void ** ppOut = va_arg(*pParam, void **);
147 void * pInterface = va_arg(*pParam, void *);
148 typelib_InterfaceTypeDescription * pInterfaceTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
149 uno_Mapping * pMapping = va_arg(*pParam, uno_Mapping *);
151 pMapping->mapInterface(pMapping, ppOut, pInterface, pInterfaceTypeDescr);
154 void MediatorMapping::mapInterface(
155 void ** ppOut,
156 void * pInterface,
157 typelib_InterfaceTypeDescription * pInterfaceTypeDescr)
159 if (*ppOut != 0)
161 uno_ExtEnvironment * env = m_to.get()->pExtEnv;
162 OSL_ASSERT( env != 0 );
163 env->releaseInterface( env, *ppOut );
164 *ppOut = NULL;
167 void * ret = 0;
168 uno_Interface * pUnoI = 0;
170 m_from.invoke(s_mapInterface_v, &pUnoI, pInterface, pInterfaceTypeDescr, m_from2uno.get());
172 m_uno2to.mapInterface(&ret, pUnoI, pInterfaceTypeDescr);
174 if (pUnoI)
175 m_interm.get()->pExtEnv->releaseInterface(m_interm.get()->pExtEnv, pUnoI);
177 *ppOut = ret;
180 extern "C" { static void SAL_CALL s_MediatorMapping_free(uno_Mapping * pMapping)
181 SAL_THROW_EXTERN_C()
183 delete static_cast<MediatorMapping *>(pMapping);
188 static rtl::OUString getPrefix(rtl::OUString const & str1, rtl::OUString const & str2)
190 sal_Int32 nIndex1 = 0;
191 sal_Int32 nIndex2 = 0;
192 sal_Int32 sim = 0;
194 rtl::OUString token1;
195 rtl::OUString token2;
199 token1 = str1.getToken(0, ':', nIndex1);
200 token2 = str2.getToken(0, ':', nIndex2);
202 if (token1.equals(token2))
203 sim += token1.getLength() + 1;
205 while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2));
207 rtl::OUString result;
209 if (sim)
210 result = str1.copy(0, sim - 1);
212 return result;
215 // rtl::OUString str1(RTL_CONSTASCII_USTRINGPARAM("abc:def:ghi"));
216 // rtl::OUString str2(RTL_CONSTASCII_USTRINGPARAM("abc:def"));
217 // rtl::OUString str3(RTL_CONSTASCII_USTRINGPARAM("abc"));
218 // rtl::OUString str4(RTL_CONSTASCII_USTRINGPARAM(""));
220 // rtl::OUString pref;
222 // pref = getPrefix(str1, str1);
223 // pref = getPrefix(str1, str2);
224 // pref = getPrefix(str1, str3);
225 // pref = getPrefix(str1, str4);
227 // pref = getPrefix(str2, str1);
228 // pref = getPrefix(str3, str1);
229 // pref = getPrefix(str4, str1);
232 void getCascadeMapping(uno_Mapping ** ppMapping,
233 uno_Environment * pFrom,
234 uno_Environment * pTo,
235 rtl_uString * pAddPurpose)
237 if (pAddPurpose && pAddPurpose->length)
238 return;
240 rtl::OUString uno_envType(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO));
242 rtl::OUString from_envType = cppu::EnvDcp::getTypeName(pFrom->pTypeName);
243 rtl::OUString to_envType = cppu::EnvDcp::getTypeName(pTo->pTypeName);
244 rtl::OUString from_envPurpose = cppu::EnvDcp::getPurpose(pFrom->pTypeName);
245 rtl::OUString to_envPurpose = cppu::EnvDcp::getPurpose(pTo->pTypeName);
247 #ifdef LOG_CALLING_named_purpose_getMapping
248 rtl::OString s_from_name = rtl::OUStringToOString(pFrom->pTypeName, RTL_TEXTENCODING_ASCII_US);
249 rtl::OString s_to_name = rtl::OUStringToOString(pTo->pTypeName, RTL_TEXTENCODING_ASCII_US);
251 std::cerr << __FUNCTION__ << " - creating mediation ";
252 std::cerr << "pFrom: " << s_from_name.getStr();
253 std::cerr <<" pTo: " << s_to_name.getStr() << std::endl;
254 #endif
256 if (from_envPurpose == to_envPurpose) // gcc:bla => uno:bla
257 return;
259 // reaching this point means, we need a mediated mapping!!!
260 // we generall mediate via uno[:free]
261 uno_Environment * pInterm = NULL;
263 // chained uno -> uno
264 if (from_envType == uno_envType && to_envType == uno_envType)
266 rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose);
268 rtl::OUString uno_envDcp = uno_envType;
269 uno_envDcp += purpose;
271 // direct mapping possible?
272 // uno:bla-->uno:bla:blubb
273 if (from_envPurpose.equals(purpose))
275 rtl::OUString rest = to_envPurpose.copy(purpose.getLength());
277 sal_Int32 index = rest.indexOf(':', 1);
278 if (index == -1)
280 uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData);
281 return;
284 uno_envDcp += rest.copy(0, index);
286 else if (to_envPurpose.equals(purpose))
288 rtl::OUString rest = from_envPurpose.copy(purpose.getLength());
290 sal_Int32 index = rest.indexOf(':', 1);
291 if (index == -1)
293 uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData);
294 return;
297 uno_envDcp += rest.copy(0, index);
300 uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL);
302 else if (from_envType != uno_envType && to_envType == uno_envType) // <ANY> -> UNO ?
303 // mediate via uno:purpose(fromEnv)
305 rtl::OUString envDcp = uno_envType;
307 envDcp += from_envPurpose;
308 uno_getEnvironment(&pInterm, envDcp.pData, NULL);
310 else if (from_envType == uno_envType && to_envType != uno_envType) // UNO -> <ANY>?
311 // mediate via uno(context)
313 rtl::OUString envDcp = uno_envType;
315 envDcp += to_envPurpose;
316 uno_getEnvironment(&pInterm, envDcp.pData, NULL);
318 else // everything else
319 // mediate via uno:purpose
321 rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose);
323 rtl::OUString uno_envDcp = uno_envType;
324 uno_envDcp += purpose;
326 uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL);
329 uno_Mapping * pMapping = new MediatorMapping(pFrom, pInterm, pTo);
330 pInterm->release(pInterm);
333 pMapping->acquire(pMapping);
335 ::uno_registerMapping(&pMapping, s_MediatorMapping_free, pFrom, pTo, pAddPurpose);
337 if (*ppMapping)
338 (*ppMapping)->release(*ppMapping);
340 *ppMapping = pMapping;