1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_bridges.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <stdio.h> 32*cdf0e10cSrcweir #include <string.h> 33*cdf0e10cSrcweir #include <cxxabi.h> 34*cdf0e10cSrcweir #include <hash_map> 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir #include <rtl/strbuf.hxx> 37*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 38*cdf0e10cSrcweir #include <osl/diagnose.h> 39*cdf0e10cSrcweir #include <osl/mutex.hxx> 40*cdf0e10cSrcweir 41*cdf0e10cSrcweir #include <com/sun/star/uno/genfunc.hxx> 42*cdf0e10cSrcweir #include "com/sun/star/uno/RuntimeException.hpp" 43*cdf0e10cSrcweir #include <typelib/typedescription.hxx> 44*cdf0e10cSrcweir #include <uno/any2.h> 45*cdf0e10cSrcweir 46*cdf0e10cSrcweir #include "share.hxx" 47*cdf0e10cSrcweir 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir using namespace ::std; 50*cdf0e10cSrcweir using namespace ::osl; 51*cdf0e10cSrcweir using namespace ::rtl; 52*cdf0e10cSrcweir using namespace ::com::sun::star::uno; 53*cdf0e10cSrcweir using namespace ::__cxxabiv1; 54*cdf0e10cSrcweir 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir namespace CPPU_CURRENT_NAMESPACE 57*cdf0e10cSrcweir { 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir void dummy_can_throw_anything( char const * ) 60*cdf0e10cSrcweir { 61*cdf0e10cSrcweir } 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir //================================================================================================== 64*cdf0e10cSrcweir static OUString toUNOname( char const * p ) SAL_THROW( () ) 65*cdf0e10cSrcweir { 66*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 67*cdf0e10cSrcweir char const * start = p; 68*cdf0e10cSrcweir #endif 69*cdf0e10cSrcweir 70*cdf0e10cSrcweir // example: N3com3sun4star4lang24IllegalArgumentExceptionE 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir OUStringBuffer buf( 64 ); 73*cdf0e10cSrcweir OSL_ASSERT( 'N' == *p ); 74*cdf0e10cSrcweir ++p; // skip N 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir while ('E' != *p) 77*cdf0e10cSrcweir { 78*cdf0e10cSrcweir // read chars count 79*cdf0e10cSrcweir long n = (*p++ - '0'); 80*cdf0e10cSrcweir while ('0' <= *p && '9' >= *p) 81*cdf0e10cSrcweir { 82*cdf0e10cSrcweir n *= 10; 83*cdf0e10cSrcweir n += (*p++ - '0'); 84*cdf0e10cSrcweir } 85*cdf0e10cSrcweir buf.appendAscii( p, n ); 86*cdf0e10cSrcweir p += n; 87*cdf0e10cSrcweir if ('E' != *p) 88*cdf0e10cSrcweir buf.append( (sal_Unicode)'.' ); 89*cdf0e10cSrcweir } 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 92*cdf0e10cSrcweir OUString ret( buf.makeStringAndClear() ); 93*cdf0e10cSrcweir OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); 94*cdf0e10cSrcweir fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); 95*cdf0e10cSrcweir return ret; 96*cdf0e10cSrcweir #else 97*cdf0e10cSrcweir return buf.makeStringAndClear(); 98*cdf0e10cSrcweir #endif 99*cdf0e10cSrcweir } 100*cdf0e10cSrcweir 101*cdf0e10cSrcweir //================================================================================================== 102*cdf0e10cSrcweir class RTTI 103*cdf0e10cSrcweir { 104*cdf0e10cSrcweir typedef hash_map< OUString, type_info *, OUStringHash > t_rtti_map; 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir Mutex m_mutex; 107*cdf0e10cSrcweir t_rtti_map m_rttis; 108*cdf0e10cSrcweir t_rtti_map m_generatedRttis; 109*cdf0e10cSrcweir 110*cdf0e10cSrcweir public: 111*cdf0e10cSrcweir RTTI() SAL_THROW( () ); 112*cdf0e10cSrcweir ~RTTI() SAL_THROW( () ); 113*cdf0e10cSrcweir 114*cdf0e10cSrcweir type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); 115*cdf0e10cSrcweir }; 116*cdf0e10cSrcweir //__________________________________________________________________________________________________ 117*cdf0e10cSrcweir RTTI::RTTI() SAL_THROW( () ) 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir } 120*cdf0e10cSrcweir //__________________________________________________________________________________________________ 121*cdf0e10cSrcweir RTTI::~RTTI() SAL_THROW( () ) 122*cdf0e10cSrcweir { 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir //__________________________________________________________________________________________________ 126*cdf0e10cSrcweir type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) 127*cdf0e10cSrcweir { 128*cdf0e10cSrcweir type_info * rtti; 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir MutexGuard guard( m_mutex ); 133*cdf0e10cSrcweir t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) ); 134*cdf0e10cSrcweir if (iRttiFind == m_rttis.end()) 135*cdf0e10cSrcweir { 136*cdf0e10cSrcweir // RTTI symbol 137*cdf0e10cSrcweir OStringBuffer buf( 64 ); 138*cdf0e10cSrcweir buf.append( RTL_CONSTASCII_STRINGPARAM("__ZTIN") ); 139*cdf0e10cSrcweir sal_Int32 index = 0; 140*cdf0e10cSrcweir do 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir OUString token( unoName.getToken( 0, '.', index ) ); 143*cdf0e10cSrcweir buf.append( token.getLength() ); 144*cdf0e10cSrcweir OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); 145*cdf0e10cSrcweir buf.append( c_token ); 146*cdf0e10cSrcweir } 147*cdf0e10cSrcweir while (index >= 0); 148*cdf0e10cSrcweir buf.append( 'E' ); 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir OString symName( buf.makeStringAndClear() ); 151*cdf0e10cSrcweir // try to lookup the symbol in the generated rtti map 152*cdf0e10cSrcweir t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); 153*cdf0e10cSrcweir if (iFind == m_generatedRttis.end()) 154*cdf0e10cSrcweir { 155*cdf0e10cSrcweir // we must generate it ! 156*cdf0e10cSrcweir // symbol and rtti-name is nearly identical, 157*cdf0e10cSrcweir // the symbol is prefixed with __ZTI 158*cdf0e10cSrcweir char const * rttiName = symName.getStr() +5; 159*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 160*cdf0e10cSrcweir fprintf( stderr,"generated rtti for %s\n", rttiName ); 161*cdf0e10cSrcweir #endif 162*cdf0e10cSrcweir if (pTypeDescr->pBaseTypeDescription) 163*cdf0e10cSrcweir { 164*cdf0e10cSrcweir // ensure availability of base 165*cdf0e10cSrcweir type_info * base_rtti = getRTTI( 166*cdf0e10cSrcweir (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); 167*cdf0e10cSrcweir rtti = new __si_class_type_info( 168*cdf0e10cSrcweir strdup( rttiName ), (__class_type_info *)base_rtti ); 169*cdf0e10cSrcweir } 170*cdf0e10cSrcweir else 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir // this class has no base class 173*cdf0e10cSrcweir rtti = new __class_type_info( strdup( rttiName ) ); 174*cdf0e10cSrcweir } 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir pair< t_rtti_map::iterator, bool > insertion( 177*cdf0e10cSrcweir m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); 178*cdf0e10cSrcweir OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir else // taking already generated rtti 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir rtti = iFind->second; 183*cdf0e10cSrcweir } 184*cdf0e10cSrcweir } 185*cdf0e10cSrcweir else 186*cdf0e10cSrcweir { 187*cdf0e10cSrcweir rtti = iRttiFind->second; 188*cdf0e10cSrcweir } 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir return rtti; 191*cdf0e10cSrcweir } 192*cdf0e10cSrcweir 193*cdf0e10cSrcweir //-------------------------------------------------------------------------------------------------- 194*cdf0e10cSrcweir static void deleteException( void * pExc ) 195*cdf0e10cSrcweir { 196*cdf0e10cSrcweir __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); 197*cdf0e10cSrcweir typelib_TypeDescription * pTD = 0; 198*cdf0e10cSrcweir OUString unoName( toUNOname( header->exceptionType->name() ) ); 199*cdf0e10cSrcweir ::typelib_typedescription_getByName( &pTD, unoName.pData ); 200*cdf0e10cSrcweir OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); 201*cdf0e10cSrcweir if (pTD) 202*cdf0e10cSrcweir { 203*cdf0e10cSrcweir ::uno_destructData( pExc, pTD, cpp_release ); 204*cdf0e10cSrcweir ::typelib_typedescription_release( pTD ); 205*cdf0e10cSrcweir } 206*cdf0e10cSrcweir } 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir //================================================================================================== 209*cdf0e10cSrcweir void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) 210*cdf0e10cSrcweir { 211*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 212*cdf0e10cSrcweir OString cstr( 213*cdf0e10cSrcweir OUStringToOString( 214*cdf0e10cSrcweir *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), 215*cdf0e10cSrcweir RTL_TEXTENCODING_ASCII_US ) ); 216*cdf0e10cSrcweir fprintf( stderr, "> uno exception occured: %s\n", cstr.getStr() ); 217*cdf0e10cSrcweir #endif 218*cdf0e10cSrcweir void * pCppExc; 219*cdf0e10cSrcweir type_info * rtti; 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir { 222*cdf0e10cSrcweir // construct cpp exception object 223*cdf0e10cSrcweir typelib_TypeDescription * pTypeDescr = 0; 224*cdf0e10cSrcweir TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); 225*cdf0e10cSrcweir OSL_ASSERT( pTypeDescr ); 226*cdf0e10cSrcweir if (! pTypeDescr) 227*cdf0e10cSrcweir { 228*cdf0e10cSrcweir throw RuntimeException( 229*cdf0e10cSrcweir OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + 230*cdf0e10cSrcweir *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), 231*cdf0e10cSrcweir Reference< XInterface >() ); 232*cdf0e10cSrcweir } 233*cdf0e10cSrcweir 234*cdf0e10cSrcweir pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); 235*cdf0e10cSrcweir ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); 236*cdf0e10cSrcweir 237*cdf0e10cSrcweir // destruct uno exception 238*cdf0e10cSrcweir ::uno_any_destruct( pUnoExc, 0 ); 239*cdf0e10cSrcweir // avoiding locked counts 240*cdf0e10cSrcweir static RTTI * s_rtti = 0; 241*cdf0e10cSrcweir if (! s_rtti) 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir MutexGuard guard( Mutex::getGlobalMutex() ); 244*cdf0e10cSrcweir if (! s_rtti) 245*cdf0e10cSrcweir { 246*cdf0e10cSrcweir #ifdef LEAK_STATIC_DATA 247*cdf0e10cSrcweir s_rtti = new RTTI(); 248*cdf0e10cSrcweir #else 249*cdf0e10cSrcweir static RTTI rtti_data; 250*cdf0e10cSrcweir s_rtti = &rtti_data; 251*cdf0e10cSrcweir #endif 252*cdf0e10cSrcweir } 253*cdf0e10cSrcweir } 254*cdf0e10cSrcweir rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); 255*cdf0e10cSrcweir TYPELIB_DANGER_RELEASE( pTypeDescr ); 256*cdf0e10cSrcweir OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); 257*cdf0e10cSrcweir if (! rtti) 258*cdf0e10cSrcweir { 259*cdf0e10cSrcweir throw RuntimeException( 260*cdf0e10cSrcweir OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + 261*cdf0e10cSrcweir *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), 262*cdf0e10cSrcweir Reference< XInterface >() ); 263*cdf0e10cSrcweir } 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir __cxa_throw( pCppExc, rtti, deleteException ); 267*cdf0e10cSrcweir } 268*cdf0e10cSrcweir 269*cdf0e10cSrcweir //================================================================================================== 270*cdf0e10cSrcweir void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) 271*cdf0e10cSrcweir { 272*cdf0e10cSrcweir if (! header) 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir RuntimeException aRE( 275*cdf0e10cSrcweir OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), 276*cdf0e10cSrcweir Reference< XInterface >() ); 277*cdf0e10cSrcweir Type const & rType = ::getCppuType( &aRE ); 278*cdf0e10cSrcweir uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); 279*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 280*cdf0e10cSrcweir OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); 281*cdf0e10cSrcweir OSL_ENSURE( 0, cstr.getStr() ); 282*cdf0e10cSrcweir #endif 283*cdf0e10cSrcweir return; 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir typelib_TypeDescription * pExcTypeDescr = 0; 287*cdf0e10cSrcweir OUString unoName( toUNOname( header->exceptionType->name() ) ); 288*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 289*cdf0e10cSrcweir OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) ); 290*cdf0e10cSrcweir fprintf( stderr, "> c++ exception occured: %s\n", cstr_unoName.getStr() ); 291*cdf0e10cSrcweir #endif 292*cdf0e10cSrcweir typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData ); 293*cdf0e10cSrcweir if (0 == pExcTypeDescr) 294*cdf0e10cSrcweir { 295*cdf0e10cSrcweir RuntimeException aRE( 296*cdf0e10cSrcweir OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName, 297*cdf0e10cSrcweir Reference< XInterface >() ); 298*cdf0e10cSrcweir Type const & rType = ::getCppuType( &aRE ); 299*cdf0e10cSrcweir uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); 300*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 301*cdf0e10cSrcweir OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); 302*cdf0e10cSrcweir OSL_ENSURE( 0, cstr.getStr() ); 303*cdf0e10cSrcweir #endif 304*cdf0e10cSrcweir } 305*cdf0e10cSrcweir else 306*cdf0e10cSrcweir { 307*cdf0e10cSrcweir // construct uno exception any 308*cdf0e10cSrcweir uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); 309*cdf0e10cSrcweir typelib_typedescription_release( pExcTypeDescr ); 310*cdf0e10cSrcweir } 311*cdf0e10cSrcweir } 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir } 314*cdf0e10cSrcweir 315