1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 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. 14 * 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). 20 * 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. 25 * 26 ************************************************************************/ 27 28 #include <iostream> 29 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" 35 36 //#include "cascade_mappping.hxx" 37 #include "cppu/EnvDcp.hxx" 38 39 40 //#define LOG_CALLING_named_purpose_getMapping 41 42 //#define LOG_LIFECYLE_MediatorMapping 43 #ifdef LOG_LIFECYLE_MediatorMapping 44 # define LOG_LIFECYLE_MediatorMapping_emit(x) x 45 46 #else 47 # define LOG_LIFECYLE_MediatorMapping_emit(x) 48 49 #endif 50 51 52 using namespace com::sun::star; 53 54 class MediatorMapping : public uno_Mapping 55 { 56 oslInterlockedCount m_refCount; 57 58 uno::Mapping m_from2uno; 59 uno::Mapping m_uno2to; 60 61 uno::Environment m_from; 62 uno::Environment m_interm; 63 uno::Environment m_to; 64 65 public: 66 void acquire(void); 67 void release(void); 68 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(); 76 }; 77 78 extern "C" { 79 static void SAL_CALL s_acquire(uno_Mapping * mapping) 80 { 81 MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); 82 pMediatorMapping->acquire(); 83 } 84 85 static void SAL_CALL s_release(uno_Mapping * mapping) 86 { 87 MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); 88 pMediatorMapping->release(); 89 } 90 91 static void SAL_CALL s_mapInterface( 92 uno_Mapping * mapping, 93 void ** ppOut, 94 void * pInterface, 95 typelib_InterfaceTypeDescription * pInterfaceTypeDescr) 96 { 97 MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); 98 pMediatorMapping->mapInterface(ppOut, pInterface, pInterfaceTypeDescr); 99 } 100 } 101 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) 111 { 112 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); 113 114 if (!m_from2uno.get() || !m_uno2to.get()) 115 abort(); 116 117 uno_Mapping::acquire = s_acquire; 118 uno_Mapping::release = s_release; 119 uno_Mapping::mapInterface = s_mapInterface; 120 } 121 122 MediatorMapping::~MediatorMapping() 123 { 124 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); 125 } 126 127 void MediatorMapping::acquire(void) 128 { 129 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); 130 131 osl_incrementInterlockedCount(&m_refCount); 132 } 133 134 void MediatorMapping::release(void) 135 { 136 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); 137 138 if (osl_decrementInterlockedCount(&m_refCount) == 0) 139 { 140 ::uno_revokeMapping(this); 141 } 142 } 143 144 extern "C" { static void s_mapInterface_v(va_list * pParam) 145 { 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 *); 150 151 pMapping->mapInterface(pMapping, ppOut, pInterface, pInterfaceTypeDescr); 152 }} 153 154 void MediatorMapping::mapInterface( 155 void ** ppOut, 156 void * pInterface, 157 typelib_InterfaceTypeDescription * pInterfaceTypeDescr) 158 { 159 if (*ppOut != 0) 160 { 161 uno_ExtEnvironment * env = m_to.get()->pExtEnv; 162 OSL_ASSERT( env != 0 ); 163 env->releaseInterface( env, *ppOut ); 164 *ppOut = NULL; 165 } 166 167 void * ret = 0; 168 uno_Interface * pUnoI = 0; 169 170 m_from.invoke(s_mapInterface_v, &pUnoI, pInterface, pInterfaceTypeDescr, m_from2uno.get()); 171 172 m_uno2to.mapInterface(&ret, pUnoI, pInterfaceTypeDescr); 173 174 if (pUnoI) 175 m_interm.get()->pExtEnv->releaseInterface(m_interm.get()->pExtEnv, pUnoI); 176 177 *ppOut = ret; 178 } 179 180 extern "C" { static void SAL_CALL s_MediatorMapping_free(uno_Mapping * pMapping) 181 SAL_THROW_EXTERN_C() 182 { 183 delete static_cast<MediatorMapping *>(pMapping); 184 }} 185 186 187 188 static rtl::OUString getPrefix(rtl::OUString const & str1, rtl::OUString const & str2) 189 { 190 sal_Int32 nIndex1 = 0; 191 sal_Int32 nIndex2 = 0; 192 sal_Int32 sim = 0; 193 194 rtl::OUString token1; 195 rtl::OUString token2; 196 197 do 198 { 199 token1 = str1.getToken(0, ':', nIndex1); 200 token2 = str2.getToken(0, ':', nIndex2); 201 202 if (token1.equals(token2)) 203 sim += token1.getLength() + 1; 204 } 205 while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2)); 206 207 rtl::OUString result; 208 209 if (sim) 210 result = str1.copy(0, sim - 1); 211 212 return result; 213 } 214 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("")); 219 220 // rtl::OUString pref; 221 222 // pref = getPrefix(str1, str1); 223 // pref = getPrefix(str1, str2); 224 // pref = getPrefix(str1, str3); 225 // pref = getPrefix(str1, str4); 226 227 // pref = getPrefix(str2, str1); 228 // pref = getPrefix(str3, str1); 229 // pref = getPrefix(str4, str1); 230 231 232 void getCascadeMapping(uno_Mapping ** ppMapping, 233 uno_Environment * pFrom, 234 uno_Environment * pTo, 235 rtl_uString * pAddPurpose) 236 { 237 if (pAddPurpose && pAddPurpose->length) 238 return; 239 240 rtl::OUString uno_envType(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)); 241 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); 246 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); 250 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 255 256 if (from_envPurpose == to_envPurpose) // gcc:bla => uno:bla 257 return; 258 259 // reaching this point means, we need a mediated mapping!!! 260 // we generall mediate via uno[:free] 261 uno_Environment * pInterm = NULL; 262 263 // chained uno -> uno 264 if (from_envType == uno_envType && to_envType == uno_envType) 265 { 266 rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose); 267 268 rtl::OUString uno_envDcp = uno_envType; 269 uno_envDcp += purpose; 270 271 // direct mapping possible? 272 // uno:bla-->uno:bla:blubb 273 if (from_envPurpose.equals(purpose)) 274 { 275 rtl::OUString rest = to_envPurpose.copy(purpose.getLength()); 276 277 sal_Int32 index = rest.indexOf(':', 1); 278 if (index == -1) 279 { 280 uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData); 281 return; 282 } 283 284 uno_envDcp += rest.copy(0, index); 285 } 286 else if (to_envPurpose.equals(purpose)) 287 { 288 rtl::OUString rest = from_envPurpose.copy(purpose.getLength()); 289 290 sal_Int32 index = rest.indexOf(':', 1); 291 if (index == -1) 292 { 293 uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData); 294 return; 295 } 296 297 uno_envDcp += rest.copy(0, index); 298 } 299 300 uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL); 301 } 302 else if (from_envType != uno_envType && to_envType == uno_envType) // <ANY> -> UNO ? 303 // mediate via uno:purpose(fromEnv) 304 { 305 rtl::OUString envDcp = uno_envType; 306 307 envDcp += from_envPurpose; 308 uno_getEnvironment(&pInterm, envDcp.pData, NULL); 309 } 310 else if (from_envType == uno_envType && to_envType != uno_envType) // UNO -> <ANY>? 311 // mediate via uno(context) 312 { 313 rtl::OUString envDcp = uno_envType; 314 315 envDcp += to_envPurpose; 316 uno_getEnvironment(&pInterm, envDcp.pData, NULL); 317 } 318 else // everything else 319 // mediate via uno:purpose 320 { 321 rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose); 322 323 rtl::OUString uno_envDcp = uno_envType; 324 uno_envDcp += purpose; 325 326 uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL); 327 } 328 329 uno_Mapping * pMapping = new MediatorMapping(pFrom, pInterm, pTo); 330 pInterm->release(pInterm); 331 332 333 pMapping->acquire(pMapping); 334 335 ::uno_registerMapping(&pMapping, s_MediatorMapping_free, pFrom, pTo, pAddPurpose); 336 337 if (*ppMapping) 338 (*ppMapping)->release(*ppMapping); 339 340 *ppMapping = pMapping; 341 } 342