Update ooo320-m1
[ooovba.git] / bridges / source / cpp_uno / gcc3_os2_intel / except.cxx
bloba48bf9e9d56f6709c1d618df7a383a3eb733297b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: except.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include <stdio.h>
32 #include <dlfcn.h>
33 #include <cxxabi.h>
34 #include <hash_map>
36 #include <rtl/strbuf.hxx>
37 #include <rtl/ustrbuf.hxx>
38 #include <osl/diagnose.h>
39 #include <osl/mutex.hxx>
41 #include <com/sun/star/uno/genfunc.hxx>
42 #include "com/sun/star/uno/RuntimeException.hpp"
43 #include <typelib/typedescription.hxx>
44 #include <uno/any2.h>
46 #include "share.hxx"
48 #ifdef TEST
49 #include "test/TestBridgeException.hpp"
50 #endif
52 using namespace ::std;
53 using namespace ::osl;
54 using namespace ::rtl;
55 using namespace ::com::sun::star::uno;
56 using namespace ::__cxxabiv1;
58 //==================================================================================================
59 //YD static handle to this dll, to allow rtti symbol lookup
60 static void* hmod;
62 //==================================================================================================
63 //YD required to run test programs, because exe cannot export symbols!
64 #ifdef TEST
65 using namespace ::test;
67 void dymmy_TestBridgeException() throw( ::test::TestBridgeException)
69 throw TestBridgeException();
71 #endif
73 //==================================================================================================
74 namespace CPPU_CURRENT_NAMESPACE
77 void dummy_can_throw_anything( char const * )
81 //==================================================================================================
82 static OUString toUNOname( char const * p ) SAL_THROW( () )
84 #if OSL_DEBUG_LEVEL > 1
85 char const * start = p;
86 #endif
88 // example: N3com3sun4star4lang24IllegalArgumentExceptionE
90 OUStringBuffer buf( 64 );
91 OSL_ASSERT( 'N' == *p );
92 ++p; // skip N
94 while ('E' != *p)
96 // read chars count
97 long n = (*p++ - '0');
98 while ('0' <= *p && '9' >= *p)
100 n *= 10;
101 n += (*p++ - '0');
103 buf.appendAscii( p, n );
104 p += n;
105 if ('E' != *p)
106 buf.append( (sal_Unicode)'.' );
109 #if OSL_DEBUG_LEVEL > 1
110 OUString ret( buf.makeStringAndClear() );
111 OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) );
112 fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() );
113 return ret;
114 #else
115 return buf.makeStringAndClear();
116 #endif
119 //==================================================================================================
120 class RTTI
122 typedef hash_map< OUString, type_info *, OUStringHash > t_rtti_map;
124 Mutex m_mutex;
125 t_rtti_map m_rttis;
126 t_rtti_map m_generatedRttis;
128 //void * m_hApp;
130 public:
131 RTTI() SAL_THROW( () );
132 ~RTTI() SAL_THROW( () );
134 type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () );
136 //__________________________________________________________________________________________________
137 RTTI::RTTI() SAL_THROW( () )
138 // : m_hApp( dlopen( 0, RTLD_LAZY ) )
141 //__________________________________________________________________________________________________
142 RTTI::~RTTI() SAL_THROW( () )
144 // dlclose( m_hApp );
147 //__________________________________________________________________________________________________
148 type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () )
150 type_info * rtti;
152 OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName;
154 MutexGuard guard( m_mutex );
155 t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
156 if (iFind == m_rttis.end())
158 // RTTI symbol
159 OStringBuffer buf( 64 );
160 buf.append( RTL_CONSTASCII_STRINGPARAM("__ZTIN") );
161 sal_Int32 index = 0;
164 OUString token( unoName.getToken( 0, '.', index ) );
165 buf.append( token.getLength() );
166 OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
167 buf.append( c_token );
169 while (index >= 0);
170 buf.append( 'E' );
172 OString symName( buf.makeStringAndClear() );
173 //rtti = (type_info *)dlsym( m_hApp, symName.getStr() );
174 if (hmod == NULL)
175 hmod = dlopen( "gcc3_uno.dll", 0);
177 if (hmod)
178 rtti = (type_info *)dlsym( hmod, symName.getStr() );
180 if (rtti)
182 pair< t_rtti_map::iterator, bool > insertion(
183 m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
184 OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" );
186 else
188 // try to lookup the symbol in the generated rtti map
189 t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) );
190 if (iFind == m_generatedRttis.end())
192 // we must generate it !
193 // symbol and rtti-name is nearly identical,
194 // the symbol is prefixed with __ZTI
195 char const * rttiName = symName.getStr() +5;
196 #if OSL_DEBUG_LEVEL > 1
197 fprintf( stderr,"generated rtti for %s\n", rttiName );
198 #endif
199 if (pTypeDescr->pBaseTypeDescription)
201 // ensure availability of base
202 type_info * base_rtti = getRTTI(
203 (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription );
204 rtti = new __si_class_type_info(
205 strdup( rttiName ), (__class_type_info *)base_rtti );
207 else
209 // this class has no base class
210 rtti = new __class_type_info( strdup( rttiName ) );
213 pair< t_rtti_map::iterator, bool > insertion(
214 m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
215 OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" );
217 else // taking already generated rtti
219 rtti = iFind->second;
223 else
225 rtti = iFind->second;
228 return rtti;
231 //--------------------------------------------------------------------------------------------------
232 static void deleteException( void * pExc )
234 __cxa_exception const * header = ((__cxa_exception const *)pExc - 1);
235 typelib_TypeDescription * pTD = 0;
236 OUString unoName( toUNOname( header->exceptionType->name() ) );
237 ::typelib_typedescription_getByName( &pTD, unoName.pData );
238 OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" );
239 if (pTD)
241 ::uno_destructData( pExc, pTD, cpp_release );
242 ::typelib_typedescription_release( pTD );
246 //==================================================================================================
247 void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
249 #if OSL_DEBUG_LEVEL > 1
250 OString cstr(
251 OUStringToOString(
252 *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
253 RTL_TEXTENCODING_ASCII_US ) );
254 fprintf( stderr, "> uno exception occured: %s\n", cstr.getStr() );
255 #endif
256 void * pCppExc;
257 type_info * rtti;
260 // construct cpp exception object
261 typelib_TypeDescription * pTypeDescr = 0;
262 TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
263 OSL_ASSERT( pTypeDescr );
264 if (! pTypeDescr)
266 throw RuntimeException(
267 OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) +
268 *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
269 Reference< XInterface >() );
272 pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
273 ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
275 // destruct uno exception
276 ::uno_any_destruct( pUnoExc, 0 );
277 // avoiding locked counts
278 static RTTI * s_rtti = 0;
279 if (! s_rtti)
281 MutexGuard guard( Mutex::getGlobalMutex() );
282 if (! s_rtti)
284 #ifdef LEAK_STATIC_DATA
285 s_rtti = new RTTI();
286 #else
287 static RTTI rtti_data;
288 s_rtti = &rtti_data;
289 #endif
292 rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr );
293 TYPELIB_DANGER_RELEASE( pTypeDescr );
294 OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
295 if (! rtti)
297 throw RuntimeException(
298 OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) +
299 *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
300 Reference< XInterface >() );
304 __cxa_throw( pCppExc, rtti, deleteException );
307 //==================================================================================================
308 void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
310 if (! header)
312 RuntimeException aRE(
313 OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ),
314 Reference< XInterface >() );
315 Type const & rType = ::getCppuType( &aRE );
316 uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
317 #if OSL_DEBUG_LEVEL > 0
318 OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
319 OSL_ENSURE( 0, cstr.getStr() );
320 #endif
321 return;
324 typelib_TypeDescription * pExcTypeDescr = 0;
325 OUString unoName( toUNOname( header->exceptionType->name() ) );
326 #if OSL_DEBUG_LEVEL > 1
327 OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) );
328 fprintf( stderr, "> c++ exception occured: %s\n", cstr_unoName.getStr() );
329 #endif
330 typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
331 if (0 == pExcTypeDescr)
333 RuntimeException aRE(
334 OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName,
335 Reference< XInterface >() );
336 Type const & rType = ::getCppuType( &aRE );
337 uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
338 #if OSL_DEBUG_LEVEL > 0
339 OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
340 OSL_ENSURE( 0, cstr.getStr() );
341 #endif
343 else
345 // construct uno exception any
346 uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
347 typelib_typedescription_release( pExcTypeDescr );