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