| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include <iostream> |
| |
| #include "osl/interlck.h" |
| #include "rtl/ustring.hxx" |
| #include "uno/environment.hxx" |
| #include "uno/mapping.hxx" |
| #include "uno/dispatcher.h" |
| |
| //#include "cascade_mappping.hxx" |
| #include "cppu/EnvDcp.hxx" |
| |
| |
| //#define LOG_CALLING_named_purpose_getMapping |
| |
| //#define LOG_LIFECYLE_MediatorMapping |
| #ifdef LOG_LIFECYLE_MediatorMapping |
| # define LOG_LIFECYLE_MediatorMapping_emit(x) x |
| |
| #else |
| # define LOG_LIFECYLE_MediatorMapping_emit(x) |
| |
| #endif |
| |
| |
| using namespace com::sun::star; |
| |
| class MediatorMapping : public uno_Mapping |
| { |
| oslInterlockedCount m_refCount; |
| |
| uno::Mapping m_from2uno; |
| uno::Mapping m_uno2to; |
| |
| uno::Environment m_from; |
| uno::Environment m_interm; |
| uno::Environment m_to; |
| |
| public: |
| void acquire(void); |
| void release(void); |
| |
| void mapInterface(void ** ppOut, |
| void * pInterface, |
| typelib_InterfaceTypeDescription * pInterfaceTypeDescr); |
| MediatorMapping(uno_Environment * pFrom, |
| uno_Environment * pInterm, |
| uno_Environment * pTo); |
| ~MediatorMapping(); |
| }; |
| |
| extern "C" { |
| static void SAL_CALL s_acquire(uno_Mapping * mapping) |
| { |
| MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); |
| pMediatorMapping->acquire(); |
| } |
| |
| static void SAL_CALL s_release(uno_Mapping * mapping) |
| { |
| MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); |
| pMediatorMapping->release(); |
| } |
| |
| static void SAL_CALL s_mapInterface( |
| uno_Mapping * mapping, |
| void ** ppOut, |
| void * pInterface, |
| typelib_InterfaceTypeDescription * pInterfaceTypeDescr) |
| { |
| MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); |
| pMediatorMapping->mapInterface(ppOut, pInterface, pInterfaceTypeDescr); |
| } |
| } |
| |
| MediatorMapping::MediatorMapping(uno_Environment * pFrom, |
| uno_Environment * pInterm, |
| uno_Environment * pTo) |
| : m_refCount(0), |
| m_from2uno(pFrom, pInterm), |
| m_uno2to (pInterm, pTo), |
| m_from (pFrom), |
| m_interm (pInterm), |
| m_to (pTo) |
| { |
| LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); |
| |
| if (!m_from2uno.get() || !m_uno2to.get()) |
| abort(); |
| |
| uno_Mapping::acquire = s_acquire; |
| uno_Mapping::release = s_release; |
| uno_Mapping::mapInterface = s_mapInterface; |
| } |
| |
| MediatorMapping::~MediatorMapping() |
| { |
| LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); |
| } |
| |
| void MediatorMapping::acquire(void) |
| { |
| LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); |
| |
| osl_incrementInterlockedCount(&m_refCount); |
| } |
| |
| void MediatorMapping::release(void) |
| { |
| LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); |
| |
| if (osl_decrementInterlockedCount(&m_refCount) == 0) |
| { |
| ::uno_revokeMapping(this); |
| } |
| } |
| |
| extern "C" { static void s_mapInterface_v(va_list * pParam) |
| { |
| void ** ppOut = va_arg(*pParam, void **); |
| void * pInterface = va_arg(*pParam, void *); |
| typelib_InterfaceTypeDescription * pInterfaceTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *); |
| uno_Mapping * pMapping = va_arg(*pParam, uno_Mapping *); |
| |
| pMapping->mapInterface(pMapping, ppOut, pInterface, pInterfaceTypeDescr); |
| }} |
| |
| void MediatorMapping::mapInterface( |
| void ** ppOut, |
| void * pInterface, |
| typelib_InterfaceTypeDescription * pInterfaceTypeDescr) |
| { |
| if (*ppOut != 0) |
| { |
| uno_ExtEnvironment * env = m_to.get()->pExtEnv; |
| OSL_ASSERT( env != 0 ); |
| env->releaseInterface( env, *ppOut ); |
| *ppOut = NULL; |
| } |
| |
| void * ret = 0; |
| uno_Interface * pUnoI = 0; |
| |
| m_from.invoke(s_mapInterface_v, &pUnoI, pInterface, pInterfaceTypeDescr, m_from2uno.get()); |
| |
| m_uno2to.mapInterface(&ret, pUnoI, pInterfaceTypeDescr); |
| |
| if (pUnoI) |
| m_interm.get()->pExtEnv->releaseInterface(m_interm.get()->pExtEnv, pUnoI); |
| |
| *ppOut = ret; |
| } |
| |
| extern "C" { static void SAL_CALL s_MediatorMapping_free(uno_Mapping * pMapping) |
| SAL_THROW_EXTERN_C() |
| { |
| delete static_cast<MediatorMapping *>(pMapping); |
| }} |
| |
| |
| |
| static rtl::OUString getPrefix(rtl::OUString const & str1, rtl::OUString const & str2) |
| { |
| sal_Int32 nIndex1 = 0; |
| sal_Int32 nIndex2 = 0; |
| sal_Int32 sim = 0; |
| |
| rtl::OUString token1; |
| rtl::OUString token2; |
| |
| do |
| { |
| token1 = str1.getToken(0, ':', nIndex1); |
| token2 = str2.getToken(0, ':', nIndex2); |
| |
| if (token1.equals(token2)) |
| sim += token1.getLength() + 1; |
| } |
| while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2)); |
| |
| rtl::OUString result; |
| |
| if (sim) |
| result = str1.copy(0, sim - 1); |
| |
| return result; |
| } |
| |
| // rtl::OUString str1(RTL_CONSTASCII_USTRINGPARAM("abc:def:ghi")); |
| // rtl::OUString str2(RTL_CONSTASCII_USTRINGPARAM("abc:def")); |
| // rtl::OUString str3(RTL_CONSTASCII_USTRINGPARAM("abc")); |
| // rtl::OUString str4(RTL_CONSTASCII_USTRINGPARAM("")); |
| |
| // rtl::OUString pref; |
| |
| // pref = getPrefix(str1, str1); |
| // pref = getPrefix(str1, str2); |
| // pref = getPrefix(str1, str3); |
| // pref = getPrefix(str1, str4); |
| |
| // pref = getPrefix(str2, str1); |
| // pref = getPrefix(str3, str1); |
| // pref = getPrefix(str4, str1); |
| |
| |
| void getCascadeMapping(uno_Mapping ** ppMapping, |
| uno_Environment * pFrom, |
| uno_Environment * pTo, |
| rtl_uString * pAddPurpose) |
| { |
| if (pAddPurpose && pAddPurpose->length) |
| return; |
| |
| rtl::OUString uno_envType(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)); |
| |
| rtl::OUString from_envType = cppu::EnvDcp::getTypeName(pFrom->pTypeName); |
| rtl::OUString to_envType = cppu::EnvDcp::getTypeName(pTo->pTypeName); |
| rtl::OUString from_envPurpose = cppu::EnvDcp::getPurpose(pFrom->pTypeName); |
| rtl::OUString to_envPurpose = cppu::EnvDcp::getPurpose(pTo->pTypeName); |
| |
| #ifdef LOG_CALLING_named_purpose_getMapping |
| rtl::OString s_from_name = rtl::OUStringToOString(pFrom->pTypeName, RTL_TEXTENCODING_ASCII_US); |
| rtl::OString s_to_name = rtl::OUStringToOString(pTo->pTypeName, RTL_TEXTENCODING_ASCII_US); |
| |
| std::cerr << __FUNCTION__ << " - creating mediation "; |
| std::cerr << "pFrom: " << s_from_name.getStr(); |
| std::cerr <<" pTo: " << s_to_name.getStr() << std::endl; |
| #endif |
| |
| if (from_envPurpose == to_envPurpose) // gcc:bla => uno:bla |
| return; |
| |
| // reaching this point means, we need a mediated mapping!!! |
| // we generall mediate via uno[:free] |
| uno_Environment * pInterm = NULL; |
| |
| // chained uno -> uno |
| if (from_envType == uno_envType && to_envType == uno_envType) |
| { |
| rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose); |
| |
| rtl::OUString uno_envDcp = uno_envType; |
| uno_envDcp += purpose; |
| |
| // direct mapping possible? |
| // uno:bla-->uno:bla:blubb |
| if (from_envPurpose.equals(purpose)) |
| { |
| rtl::OUString rest = to_envPurpose.copy(purpose.getLength()); |
| |
| sal_Int32 index = rest.indexOf(':', 1); |
| if (index == -1) |
| { |
| uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData); |
| return; |
| } |
| |
| uno_envDcp += rest.copy(0, index); |
| } |
| else if (to_envPurpose.equals(purpose)) |
| { |
| rtl::OUString rest = from_envPurpose.copy(purpose.getLength()); |
| |
| sal_Int32 index = rest.indexOf(':', 1); |
| if (index == -1) |
| { |
| uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData); |
| return; |
| } |
| |
| uno_envDcp += rest.copy(0, index); |
| } |
| |
| uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL); |
| } |
| else if (from_envType != uno_envType && to_envType == uno_envType) // <ANY> -> UNO ? |
| // mediate via uno:purpose(fromEnv) |
| { |
| rtl::OUString envDcp = uno_envType; |
| |
| envDcp += from_envPurpose; |
| uno_getEnvironment(&pInterm, envDcp.pData, NULL); |
| } |
| else if (from_envType == uno_envType && to_envType != uno_envType) // UNO -> <ANY>? |
| // mediate via uno(context) |
| { |
| rtl::OUString envDcp = uno_envType; |
| |
| envDcp += to_envPurpose; |
| uno_getEnvironment(&pInterm, envDcp.pData, NULL); |
| } |
| else // everything else |
| // mediate via uno:purpose |
| { |
| rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose); |
| |
| rtl::OUString uno_envDcp = uno_envType; |
| uno_envDcp += purpose; |
| |
| uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL); |
| } |
| |
| uno_Mapping * pMapping = new MediatorMapping(pFrom, pInterm, pTo); |
| pInterm->release(pInterm); |
| |
| |
| pMapping->acquire(pMapping); |
| |
| ::uno_registerMapping(&pMapping, s_MediatorMapping_free, pFrom, pTo, pAddPurpose); |
| |
| if (*ppMapping) |
| (*ppMapping)->release(*ppMapping); |
| |
| *ppMapping = pMapping; |
| } |