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 10cdf0e10cSrcweir * 11*129fa3d1SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 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. 19cdf0e10cSrcweir * 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" { 75cdf0e10cSrcweir static void SAL_CALL s_acquire(uno_Mapping * mapping) 76cdf0e10cSrcweir { 77cdf0e10cSrcweir MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); 78cdf0e10cSrcweir pMediatorMapping->acquire(); 79cdf0e10cSrcweir } 80cdf0e10cSrcweir 81cdf0e10cSrcweir static void SAL_CALL s_release(uno_Mapping * mapping) 82cdf0e10cSrcweir { 83cdf0e10cSrcweir MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); 84cdf0e10cSrcweir pMediatorMapping->release(); 85cdf0e10cSrcweir } 86cdf0e10cSrcweir 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 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 118cdf0e10cSrcweir MediatorMapping::~MediatorMapping() 119cdf0e10cSrcweir { 120cdf0e10cSrcweir LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); 121cdf0e10cSrcweir } 122cdf0e10cSrcweir 123cdf0e10cSrcweir void MediatorMapping::acquire(void) 124cdf0e10cSrcweir { 125cdf0e10cSrcweir LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); 126cdf0e10cSrcweir 127cdf0e10cSrcweir osl_incrementInterlockedCount(&m_refCount); 128cdf0e10cSrcweir } 129cdf0e10cSrcweir 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 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 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 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 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 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