1*129fa3d1SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*129fa3d1SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*129fa3d1SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*129fa3d1SAndrew Rist  * distributed with this work for additional information
6*129fa3d1SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*129fa3d1SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*129fa3d1SAndrew Rist  * "License"); you may not use this file except in compliance
9*129fa3d1SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*129fa3d1SAndrew Rist  *
11*129fa3d1SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*129fa3d1SAndrew Rist  *
13*129fa3d1SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*129fa3d1SAndrew Rist  * software distributed under the License is distributed on an
15*129fa3d1SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*129fa3d1SAndrew Rist  * KIND, either express or implied.  See the License for the
17*129fa3d1SAndrew Rist  * specific language governing permissions and limitations
18*129fa3d1SAndrew Rist  * under the License.
19*129fa3d1SAndrew Rist  *
20*129fa3d1SAndrew Rist  *************************************************************/
21*129fa3d1SAndrew Rist 
22*129fa3d1SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include <iostream>
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include "osl/interlck.h"
27cdf0e10cSrcweir #include "rtl/ustring.hxx"
28cdf0e10cSrcweir #include "uno/environment.hxx"
29cdf0e10cSrcweir #include "uno/mapping.hxx"
30cdf0e10cSrcweir #include "uno/dispatcher.h"
31cdf0e10cSrcweir 
32cdf0e10cSrcweir //#include "cascade_mappping.hxx"
33cdf0e10cSrcweir #include "cppu/EnvDcp.hxx"
34cdf0e10cSrcweir 
35cdf0e10cSrcweir 
36cdf0e10cSrcweir //#define LOG_CALLING_named_purpose_getMapping
37cdf0e10cSrcweir 
38cdf0e10cSrcweir //#define LOG_LIFECYLE_MediatorMapping
39cdf0e10cSrcweir #ifdef LOG_LIFECYLE_MediatorMapping
40cdf0e10cSrcweir #  define LOG_LIFECYLE_MediatorMapping_emit(x) x
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #else
43cdf0e10cSrcweir #  define LOG_LIFECYLE_MediatorMapping_emit(x)
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #endif
46cdf0e10cSrcweir 
47cdf0e10cSrcweir 
48cdf0e10cSrcweir using namespace com::sun::star;
49cdf0e10cSrcweir 
50cdf0e10cSrcweir class MediatorMapping : public uno_Mapping
51cdf0e10cSrcweir {
52cdf0e10cSrcweir 	oslInterlockedCount m_refCount;
53cdf0e10cSrcweir 
54cdf0e10cSrcweir 	uno::Mapping        m_from2uno;
55cdf0e10cSrcweir 	uno::Mapping        m_uno2to;
56cdf0e10cSrcweir 
57cdf0e10cSrcweir 	uno::Environment    m_from;
58cdf0e10cSrcweir 	uno::Environment    m_interm;
59cdf0e10cSrcweir 	uno::Environment    m_to;
60cdf0e10cSrcweir 
61cdf0e10cSrcweir public:
62cdf0e10cSrcweir 	void acquire(void);
63cdf0e10cSrcweir 	void release(void);
64cdf0e10cSrcweir 
65cdf0e10cSrcweir 	void mapInterface(void                            ** ppOut,
66cdf0e10cSrcweir 					  void                             * pInterface,
67cdf0e10cSrcweir 					  typelib_InterfaceTypeDescription * pInterfaceTypeDescr);
68cdf0e10cSrcweir 	MediatorMapping(uno_Environment * pFrom,
69cdf0e10cSrcweir 					uno_Environment * pInterm,
70cdf0e10cSrcweir 					uno_Environment * pTo);
71cdf0e10cSrcweir 	~MediatorMapping();
72cdf0e10cSrcweir };
73cdf0e10cSrcweir 
74cdf0e10cSrcweir extern "C" {
s_acquire(uno_Mapping * mapping)75cdf0e10cSrcweir static void SAL_CALL s_acquire(uno_Mapping * mapping)
76cdf0e10cSrcweir {
77cdf0e10cSrcweir 	MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
78cdf0e10cSrcweir 	pMediatorMapping->acquire();
79cdf0e10cSrcweir }
80cdf0e10cSrcweir 
s_release(uno_Mapping * mapping)81cdf0e10cSrcweir static void SAL_CALL s_release(uno_Mapping * mapping)
82cdf0e10cSrcweir {
83cdf0e10cSrcweir 	MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
84cdf0e10cSrcweir 	pMediatorMapping->release();
85cdf0e10cSrcweir }
86cdf0e10cSrcweir 
s_mapInterface(uno_Mapping * mapping,void ** ppOut,void * pInterface,typelib_InterfaceTypeDescription * pInterfaceTypeDescr)87cdf0e10cSrcweir static void SAL_CALL s_mapInterface(
88cdf0e10cSrcweir 	uno_Mapping                      * mapping,
89cdf0e10cSrcweir 	void                            ** ppOut,
90cdf0e10cSrcweir 	void                             * pInterface,
91cdf0e10cSrcweir 	typelib_InterfaceTypeDescription * pInterfaceTypeDescr)
92cdf0e10cSrcweir {
93cdf0e10cSrcweir 	MediatorMapping   * pMediatorMapping  = static_cast<MediatorMapping *>(mapping);
94cdf0e10cSrcweir 	pMediatorMapping->mapInterface(ppOut, pInterface, pInterfaceTypeDescr);
95cdf0e10cSrcweir }
96cdf0e10cSrcweir }
97cdf0e10cSrcweir 
MediatorMapping(uno_Environment * pFrom,uno_Environment * pInterm,uno_Environment * pTo)98cdf0e10cSrcweir MediatorMapping::MediatorMapping(uno_Environment * pFrom,
99cdf0e10cSrcweir 								 uno_Environment * pInterm,
100cdf0e10cSrcweir 								 uno_Environment * pTo)
101cdf0e10cSrcweir     : m_refCount(0),
102cdf0e10cSrcweir 	  m_from2uno(pFrom, pInterm),
103cdf0e10cSrcweir 	  m_uno2to  (pInterm, pTo),
104cdf0e10cSrcweir 	  m_from    (pFrom),
105cdf0e10cSrcweir 	  m_interm  (pInterm),
106cdf0e10cSrcweir 	  m_to      (pTo)
107cdf0e10cSrcweir {
108cdf0e10cSrcweir 	LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
109cdf0e10cSrcweir 
110cdf0e10cSrcweir 	if (!m_from2uno.get() || !m_uno2to.get())
111cdf0e10cSrcweir 		abort();
112cdf0e10cSrcweir 
113cdf0e10cSrcweir 	uno_Mapping::acquire      = s_acquire;
114cdf0e10cSrcweir 	uno_Mapping::release      = s_release;
115cdf0e10cSrcweir 	uno_Mapping::mapInterface = s_mapInterface;
116cdf0e10cSrcweir }
117cdf0e10cSrcweir 
~MediatorMapping()118cdf0e10cSrcweir MediatorMapping::~MediatorMapping()
119cdf0e10cSrcweir {
120cdf0e10cSrcweir 	LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
121cdf0e10cSrcweir }
122cdf0e10cSrcweir 
acquire(void)123cdf0e10cSrcweir void MediatorMapping::acquire(void)
124cdf0e10cSrcweir {
125cdf0e10cSrcweir 	LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
126cdf0e10cSrcweir 
127cdf0e10cSrcweir 	osl_incrementInterlockedCount(&m_refCount);
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
release(void)130cdf0e10cSrcweir void MediatorMapping::release(void)
131cdf0e10cSrcweir {
132cdf0e10cSrcweir 	LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 	if (osl_decrementInterlockedCount(&m_refCount) == 0)
135cdf0e10cSrcweir 	{
136cdf0e10cSrcweir         ::uno_revokeMapping(this);
137cdf0e10cSrcweir 	}
138cdf0e10cSrcweir }
139cdf0e10cSrcweir 
s_mapInterface_v(va_list * pParam)140cdf0e10cSrcweir extern "C" { static void s_mapInterface_v(va_list * pParam)
141cdf0e10cSrcweir {
142cdf0e10cSrcweir 	void                            ** ppOut               = va_arg(*pParam, void **);
143cdf0e10cSrcweir 	void                             * pInterface          = va_arg(*pParam, void *);
144cdf0e10cSrcweir 	typelib_InterfaceTypeDescription * pInterfaceTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
145cdf0e10cSrcweir 	uno_Mapping                      * pMapping            = va_arg(*pParam, uno_Mapping *);
146cdf0e10cSrcweir 
147cdf0e10cSrcweir 	pMapping->mapInterface(pMapping, ppOut, pInterface, pInterfaceTypeDescr);
148cdf0e10cSrcweir }}
149cdf0e10cSrcweir 
mapInterface(void ** ppOut,void * pInterface,typelib_InterfaceTypeDescription * pInterfaceTypeDescr)150cdf0e10cSrcweir void MediatorMapping::mapInterface(
151cdf0e10cSrcweir 	void                            ** ppOut,
152cdf0e10cSrcweir 	void                             * pInterface,
153cdf0e10cSrcweir 	typelib_InterfaceTypeDescription * pInterfaceTypeDescr)
154cdf0e10cSrcweir {
155cdf0e10cSrcweir 	if (*ppOut != 0)
156cdf0e10cSrcweir 	{
157cdf0e10cSrcweir 		uno_ExtEnvironment * env = m_to.get()->pExtEnv;
158cdf0e10cSrcweir 		OSL_ASSERT( env != 0 );
159cdf0e10cSrcweir 		env->releaseInterface( env, *ppOut );
160cdf0e10cSrcweir 		*ppOut = NULL;
161cdf0e10cSrcweir 	}
162cdf0e10cSrcweir 
163cdf0e10cSrcweir 	void * ret = 0;
164cdf0e10cSrcweir 	uno_Interface * pUnoI = 0;
165cdf0e10cSrcweir 
166cdf0e10cSrcweir 	m_from.invoke(s_mapInterface_v, &pUnoI, pInterface, pInterfaceTypeDescr, m_from2uno.get());
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 	m_uno2to.mapInterface(&ret, pUnoI, pInterfaceTypeDescr);
169cdf0e10cSrcweir 
170cdf0e10cSrcweir 	if (pUnoI)
171cdf0e10cSrcweir 		m_interm.get()->pExtEnv->releaseInterface(m_interm.get()->pExtEnv, pUnoI);
172cdf0e10cSrcweir 
173cdf0e10cSrcweir 	*ppOut = ret;
174cdf0e10cSrcweir }
175cdf0e10cSrcweir 
s_MediatorMapping_free(uno_Mapping * pMapping)176cdf0e10cSrcweir extern "C" { static void SAL_CALL s_MediatorMapping_free(uno_Mapping * pMapping)
177cdf0e10cSrcweir     SAL_THROW_EXTERN_C()
178cdf0e10cSrcweir {
179cdf0e10cSrcweir     delete static_cast<MediatorMapping *>(pMapping);
180cdf0e10cSrcweir }}
181cdf0e10cSrcweir 
182cdf0e10cSrcweir 
183cdf0e10cSrcweir 
getPrefix(rtl::OUString const & str1,rtl::OUString const & str2)184cdf0e10cSrcweir static rtl::OUString getPrefix(rtl::OUString const & str1, rtl::OUString const & str2)
185cdf0e10cSrcweir {
186cdf0e10cSrcweir 	sal_Int32 nIndex1 = 0;
187cdf0e10cSrcweir 	sal_Int32 nIndex2 = 0;
188cdf0e10cSrcweir 	sal_Int32 sim = 0;
189cdf0e10cSrcweir 
190cdf0e10cSrcweir 	rtl::OUString token1;
191cdf0e10cSrcweir 	rtl::OUString token2;
192cdf0e10cSrcweir 
193cdf0e10cSrcweir 	do
194cdf0e10cSrcweir 	{
195cdf0e10cSrcweir 		token1 = str1.getToken(0, ':', nIndex1);
196cdf0e10cSrcweir 		token2 = str2.getToken(0, ':', nIndex2);
197cdf0e10cSrcweir 
198cdf0e10cSrcweir 		if (token1.equals(token2))
199cdf0e10cSrcweir 			sim += token1.getLength() + 1;
200cdf0e10cSrcweir 	}
201cdf0e10cSrcweir 	while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2));
202cdf0e10cSrcweir 
203cdf0e10cSrcweir 	rtl::OUString result;
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 	if (sim)
206cdf0e10cSrcweir 		result = str1.copy(0, sim - 1);
207cdf0e10cSrcweir 
208cdf0e10cSrcweir 	return result;
209cdf0e10cSrcweir }
210cdf0e10cSrcweir 
211cdf0e10cSrcweir // 	rtl::OUString str1(RTL_CONSTASCII_USTRINGPARAM("abc:def:ghi"));
212cdf0e10cSrcweir // 	rtl::OUString str2(RTL_CONSTASCII_USTRINGPARAM("abc:def"));
213cdf0e10cSrcweir // 	rtl::OUString str3(RTL_CONSTASCII_USTRINGPARAM("abc"));
214cdf0e10cSrcweir // 	rtl::OUString str4(RTL_CONSTASCII_USTRINGPARAM(""));
215cdf0e10cSrcweir 
216cdf0e10cSrcweir // 	rtl::OUString pref;
217cdf0e10cSrcweir 
218cdf0e10cSrcweir // 	pref = getPrefix(str1, str1);
219cdf0e10cSrcweir // 	pref = getPrefix(str1, str2);
220cdf0e10cSrcweir // 	pref = getPrefix(str1, str3);
221cdf0e10cSrcweir // 	pref = getPrefix(str1, str4);
222cdf0e10cSrcweir 
223cdf0e10cSrcweir // 	pref = getPrefix(str2, str1);
224cdf0e10cSrcweir // 	pref = getPrefix(str3, str1);
225cdf0e10cSrcweir // 	pref = getPrefix(str4, str1);
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 
getCascadeMapping(uno_Mapping ** ppMapping,uno_Environment * pFrom,uno_Environment * pTo,rtl_uString * pAddPurpose)228cdf0e10cSrcweir void getCascadeMapping(uno_Mapping     ** ppMapping,
229cdf0e10cSrcweir 					   uno_Environment  * pFrom,
230cdf0e10cSrcweir 					   uno_Environment  * pTo,
231cdf0e10cSrcweir 					   rtl_uString      * pAddPurpose)
232cdf0e10cSrcweir {
233cdf0e10cSrcweir 	if (pAddPurpose && pAddPurpose->length)
234cdf0e10cSrcweir 		return;
235cdf0e10cSrcweir 
236cdf0e10cSrcweir 	rtl::OUString uno_envType(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO));
237cdf0e10cSrcweir 
238cdf0e10cSrcweir 	rtl::OUString from_envType    = cppu::EnvDcp::getTypeName(pFrom->pTypeName);
239cdf0e10cSrcweir 	rtl::OUString to_envType      = cppu::EnvDcp::getTypeName(pTo->pTypeName);
240cdf0e10cSrcweir 	rtl::OUString from_envPurpose = cppu::EnvDcp::getPurpose(pFrom->pTypeName);
241cdf0e10cSrcweir 	rtl::OUString to_envPurpose   = cppu::EnvDcp::getPurpose(pTo->pTypeName);
242cdf0e10cSrcweir 
243cdf0e10cSrcweir #ifdef LOG_CALLING_named_purpose_getMapping
244cdf0e10cSrcweir 	rtl::OString s_from_name = rtl::OUStringToOString(pFrom->pTypeName, RTL_TEXTENCODING_ASCII_US);
245cdf0e10cSrcweir 	rtl::OString s_to_name   = rtl::OUStringToOString(pTo->pTypeName,   RTL_TEXTENCODING_ASCII_US);
246cdf0e10cSrcweir 
247cdf0e10cSrcweir 	std::cerr << __FUNCTION__ << " - creating mediation ";
248cdf0e10cSrcweir 	std::cerr << "pFrom: " << s_from_name.getStr();
249cdf0e10cSrcweir 	std::cerr <<" pTo: "   << s_to_name.getStr() << std::endl;
250cdf0e10cSrcweir #endif
251cdf0e10cSrcweir 
252cdf0e10cSrcweir 	if (from_envPurpose == to_envPurpose) // gcc:bla => uno:bla
253cdf0e10cSrcweir 		return;
254cdf0e10cSrcweir 
255cdf0e10cSrcweir 	// reaching this point means, we need a mediated mapping!!!
256cdf0e10cSrcweir 	// we generall mediate via uno[:free]
257cdf0e10cSrcweir 	uno_Environment * pInterm = NULL;
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 	// chained uno -> uno
260cdf0e10cSrcweir 	if (from_envType == uno_envType && to_envType == uno_envType)
261cdf0e10cSrcweir 	{
262cdf0e10cSrcweir 		rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose);
263cdf0e10cSrcweir 
264cdf0e10cSrcweir 		rtl::OUString uno_envDcp = uno_envType;
265cdf0e10cSrcweir 		uno_envDcp += purpose;
266cdf0e10cSrcweir 
267cdf0e10cSrcweir 		// direct mapping possible?
268cdf0e10cSrcweir 		// uno:bla-->uno:bla:blubb
269cdf0e10cSrcweir 		if (from_envPurpose.equals(purpose))
270cdf0e10cSrcweir 		{
271cdf0e10cSrcweir 			rtl::OUString rest = to_envPurpose.copy(purpose.getLength());
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 			sal_Int32 index = rest.indexOf(':', 1);
274cdf0e10cSrcweir 			if (index == -1)
275cdf0e10cSrcweir 			{
276cdf0e10cSrcweir 				uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData);
277cdf0e10cSrcweir 				return;
278cdf0e10cSrcweir 			}
279cdf0e10cSrcweir 
280cdf0e10cSrcweir 			uno_envDcp += rest.copy(0, index);
281cdf0e10cSrcweir 		}
282cdf0e10cSrcweir 		else if (to_envPurpose.equals(purpose))
283cdf0e10cSrcweir 		{
284cdf0e10cSrcweir 			rtl::OUString rest = from_envPurpose.copy(purpose.getLength());
285cdf0e10cSrcweir 
286cdf0e10cSrcweir 			sal_Int32 index = rest.indexOf(':', 1);
287cdf0e10cSrcweir 			if (index == -1)
288cdf0e10cSrcweir 			{
289cdf0e10cSrcweir 				uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData);
290cdf0e10cSrcweir 				return;
291cdf0e10cSrcweir 			}
292cdf0e10cSrcweir 
293cdf0e10cSrcweir 			uno_envDcp += rest.copy(0, index);
294cdf0e10cSrcweir 		}
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 		uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL);
297cdf0e10cSrcweir 	}
298cdf0e10cSrcweir 	else if (from_envType != uno_envType && to_envType == uno_envType) // <ANY> -> UNO ?
299cdf0e10cSrcweir 		// mediate via uno:purpose(fromEnv)
300cdf0e10cSrcweir 	{
301cdf0e10cSrcweir 		rtl::OUString     envDcp = uno_envType;
302cdf0e10cSrcweir 
303cdf0e10cSrcweir 		envDcp += from_envPurpose;
304cdf0e10cSrcweir  		uno_getEnvironment(&pInterm, envDcp.pData, NULL);
305cdf0e10cSrcweir 	}
306cdf0e10cSrcweir 	else if (from_envType == uno_envType && to_envType != uno_envType) // UNO -> <ANY>?
307cdf0e10cSrcweir 		// mediate via uno(context)
308cdf0e10cSrcweir 	{
309cdf0e10cSrcweir 		rtl::OUString     envDcp = uno_envType;
310cdf0e10cSrcweir 
311cdf0e10cSrcweir  		envDcp += to_envPurpose;
312cdf0e10cSrcweir 		uno_getEnvironment(&pInterm, envDcp.pData, NULL);
313cdf0e10cSrcweir 	}
314cdf0e10cSrcweir 	else // everything else
315cdf0e10cSrcweir 		// mediate via uno:purpose
316cdf0e10cSrcweir 	{
317cdf0e10cSrcweir 		rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose);
318cdf0e10cSrcweir 
319cdf0e10cSrcweir 		rtl::OUString uno_envDcp = uno_envType;
320cdf0e10cSrcweir 		uno_envDcp += purpose;
321cdf0e10cSrcweir 
322cdf0e10cSrcweir 		uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL);
323cdf0e10cSrcweir 	}
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 	uno_Mapping * pMapping = new MediatorMapping(pFrom, pInterm, pTo);
326cdf0e10cSrcweir 	pInterm->release(pInterm);
327cdf0e10cSrcweir 
328cdf0e10cSrcweir 
329cdf0e10cSrcweir 	pMapping->acquire(pMapping);
330cdf0e10cSrcweir 
331cdf0e10cSrcweir 	::uno_registerMapping(&pMapping, s_MediatorMapping_free, pFrom, pTo, pAddPurpose);
332cdf0e10cSrcweir 
333cdf0e10cSrcweir 	if (*ppMapping)
334cdf0e10cSrcweir 		(*ppMapping)->release(*ppMapping);
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 	*ppMapping = pMapping;
337cdf0e10cSrcweir }
338