merge the formfield patch from ooo-build
[ooovba.git] / cppu / source / uno / cascade_mapping.cxx
blob4331cb2c1a1ceb4c73a603980607108ed6f495f0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cascade_mapping.cxx,v $
10 * $Revision: 1.4 $
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 ************************************************************************/
31 #include <iostream>
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
49 #else
50 # define LOG_LIFECYLE_MediatorMapping_emit(x)
52 #endif
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;
68 public:
69 void acquire(void);
70 void release(void);
72 void mapInterface(void ** ppOut,
73 void * pInterface,
74 typelib_InterfaceTypeDescription * pInterfaceTypeDescr);
75 MediatorMapping(uno_Environment * pFrom,
76 uno_Environment * pInterm,
77 uno_Environment * pTo);
78 ~MediatorMapping();
81 extern "C" {
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,
96 void ** ppOut,
97 void * pInterface,
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)
108 : m_refCount(0),
109 m_from2uno(pFrom, pInterm),
110 m_uno2to (pInterm, pTo),
111 m_from (pFrom),
112 m_interm (pInterm),
113 m_to (pTo)
115 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
117 if (!m_from2uno.get() || !m_uno2to.get())
118 abort();
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(
158 void ** ppOut,
159 void * pInterface,
160 typelib_InterfaceTypeDescription * pInterfaceTypeDescr)
162 if (*ppOut != 0)
164 uno_ExtEnvironment * env = m_to.get()->pExtEnv;
165 OSL_ASSERT( env != 0 );
166 env->releaseInterface( env, *ppOut );
167 *ppOut = NULL;
170 void * ret = 0;
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);
177 if (pUnoI)
178 m_interm.get()->pExtEnv->releaseInterface(m_interm.get()->pExtEnv, pUnoI);
180 *ppOut = ret;
183 extern "C" { static void SAL_CALL s_MediatorMapping_free(uno_Mapping * pMapping)
184 SAL_THROW_EXTERN_C()
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;
195 sal_Int32 sim = 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;
212 if (sim)
213 result = str1.copy(0, sim - 1);
215 return result;
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)
241 return;
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;
257 #endif
259 if (from_envPurpose == to_envPurpose) // gcc:bla => uno:bla
260 return;
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);
281 if (index == -1)
283 uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData);
284 return;
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);
294 if (index == -1)
296 uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData);
297 return;
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);
340 if (*ppMapping)
341 (*ppMapping)->release(*ppMapping);
343 *ppMapping = pMapping;