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