1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_cppuhelper.hxx" 30 31 #include "osl/diagnose.h" 32 #include "osl/doublecheckedlocking.h" 33 #include "osl/mutex.hxx" 34 #include "uno/dispatcher.hxx" 35 #include "uno/mapping.hxx" 36 #include "cppuhelper/detail/XExceptionThrower.hpp" 37 #include "com/sun/star/uno/RuntimeException.hpp" 38 39 #include "cppuhelper/exc_hlp.hxx" 40 41 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 42 43 44 using namespace ::rtl; 45 using namespace ::osl; 46 using namespace ::cppu; 47 using namespace ::com::sun::star; 48 using namespace ::com::sun::star::uno; 49 50 namespace 51 { 52 53 using cppuhelper::detail::XExceptionThrower; 54 55 //============================================================================== 56 struct ExceptionThrower : public uno_Interface, XExceptionThrower 57 { 58 inline ExceptionThrower(); 59 60 public: 61 static ExceptionThrower * get(); 62 static inline Type const & getCppuType() 63 { 64 return ::getCppuType( 65 reinterpret_cast< Reference< XExceptionThrower > const * >(0) ); 66 } 67 68 // XInterface 69 virtual Any SAL_CALL queryInterface( Type const & type ) 70 throw (RuntimeException); 71 virtual void SAL_CALL acquire() throw (); 72 virtual void SAL_CALL release() throw (); 73 74 // XExceptionThrower 75 virtual void SAL_CALL throwException( Any const & exc ) throw (Exception); 76 virtual void SAL_CALL rethrowException() throw (Exception); 77 }; 78 79 extern "C" 80 { 81 82 //------------------------------------------------------------------------------ 83 static void SAL_CALL ExceptionThrower_acquire_release_nop( uno_Interface * ) 84 { 85 } 86 87 //------------------------------------------------------------------------------ 88 static void SAL_CALL ExceptionThrower_dispatch( 89 uno_Interface * pUnoI, typelib_TypeDescription const * pMemberType, 90 void * pReturn, void * pArgs [], uno_Any ** ppException ) 91 { 92 OSL_ASSERT( pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD ); 93 94 switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription * >( 95 const_cast< typelib_TypeDescription * >( pMemberType ) )-> 96 nPosition) 97 { 98 case 0: // queryInterace() 99 { 100 Type const & rType_demanded = 101 *reinterpret_cast< Type const * >( pArgs[ 0 ] ); 102 if (rType_demanded.equals( 103 ::getCppuType( reinterpret_cast< 104 Reference< XInterface > const * >(0) ) ) || 105 rType_demanded.equals( ExceptionThrower::getCppuType() )) 106 { 107 typelib_TypeDescription * pTD = 0; 108 TYPELIB_DANGER_GET( &pTD, rType_demanded.getTypeLibType() ); 109 uno_any_construct( 110 reinterpret_cast< uno_Any * >( pReturn ), &pUnoI, pTD, 0 ); 111 TYPELIB_DANGER_RELEASE( pTD ); 112 } 113 else 114 { 115 uno_any_construct( 116 reinterpret_cast< uno_Any * >( pReturn ), 0, 0, 0 ); 117 } 118 *ppException = 0; 119 break; 120 } 121 case 1: // acquire() 122 case 2: // release() 123 *ppException = 0; 124 break; 125 case 3: // throwException() 126 { 127 uno_Any * pAny = reinterpret_cast< uno_Any * >( pArgs[ 0 ] ); 128 OSL_ASSERT( pAny->pType->eTypeClass == typelib_TypeClass_EXCEPTION ); 129 uno_type_any_construct( *ppException, pAny->pData, pAny->pType, 0 ); 130 break; 131 } 132 default: 133 { 134 OSL_ASSERT( 0 ); 135 RuntimeException exc( 136 OUSTR("not implemented!"), Reference< XInterface >() ); 137 uno_type_any_construct( 138 *ppException, &exc, ::getCppuType( &exc ).getTypeLibType(), 0 ); 139 break; 140 } 141 } 142 } 143 144 } // extern "C" 145 146 //______________________________________________________________________________ 147 Any ExceptionThrower::queryInterface( Type const & type ) 148 throw (RuntimeException) 149 { 150 if (type.equals( ::getCppuType( reinterpret_cast< 151 Reference< XInterface > const * >(0) ) ) || 152 type.equals( ExceptionThrower::getCppuType() )) 153 { 154 XExceptionThrower * that = static_cast< XExceptionThrower * >( this ); 155 return Any( &that, type ); 156 } 157 return Any(); 158 } 159 160 //______________________________________________________________________________ 161 void ExceptionThrower::acquire() throw () 162 { 163 } 164 //______________________________________________________________________________ 165 void ExceptionThrower::release() throw () 166 { 167 } 168 169 //______________________________________________________________________________ 170 void ExceptionThrower::throwException( Any const & exc ) throw (Exception) 171 { 172 OSL_ENSURE( 0, "unexpected!" ); 173 throwException( exc ); 174 } 175 176 //______________________________________________________________________________ 177 void ExceptionThrower::rethrowException() throw (Exception) 178 { 179 throw; 180 } 181 182 //______________________________________________________________________________ 183 inline ExceptionThrower::ExceptionThrower() 184 { 185 uno_Interface::acquire = ExceptionThrower_acquire_release_nop; 186 uno_Interface::release = ExceptionThrower_acquire_release_nop; 187 uno_Interface::pDispatcher = ExceptionThrower_dispatch; 188 } 189 190 //______________________________________________________________________________ 191 ExceptionThrower * ExceptionThrower::get() 192 { 193 ExceptionThrower * s_pThrower = 0; 194 if (s_pThrower == 0) 195 { 196 MutexGuard guard( Mutex::getGlobalMutex() ); 197 static ExceptionThrower s_thrower; 198 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 199 s_pThrower = &s_thrower; 200 } 201 else 202 { 203 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 204 } 205 return s_pThrower; 206 } 207 208 } // anonymous namespace 209 210 211 namespace cppu 212 { 213 214 //============================================================================== 215 void SAL_CALL throwException( Any const & exc ) SAL_THROW( (Exception) ) 216 { 217 if (exc.getValueTypeClass() != TypeClass_EXCEPTION) 218 { 219 throw RuntimeException( 220 OUSTR("no UNO exception given " 221 "(must be derived from com::sun::star::uno::Exception)!"), 222 Reference< XInterface >() ); 223 } 224 225 Mapping uno2cpp(Environment(OUSTR(UNO_LB_UNO)), Environment::getCurrent()); 226 if (! uno2cpp.is()) 227 { 228 throw RuntimeException( 229 OUSTR("cannot get binary UNO to C++ mapping!"), 230 Reference< XInterface >() ); 231 } 232 233 Reference< XExceptionThrower > xThrower; 234 uno2cpp.mapInterface( 235 reinterpret_cast< void ** >( &xThrower ), 236 static_cast< uno_Interface * >( ExceptionThrower::get() ), 237 ExceptionThrower::getCppuType() ); 238 OSL_ASSERT( xThrower.is() ); 239 xThrower->throwException( exc ); 240 } 241 242 //============================================================================== 243 Any SAL_CALL getCaughtException() 244 { 245 Mapping cpp2uno(Environment::getCurrent(), Environment(OUSTR(UNO_LB_UNO))); 246 if (! cpp2uno.is()) 247 { 248 throw RuntimeException( 249 OUSTR("cannot get C++ to binary UNO mapping!"), 250 Reference< XInterface >() ); 251 } 252 Mapping uno2cpp(Environment(OUSTR(UNO_LB_UNO)), Environment::getCurrent()); 253 if (! uno2cpp.is()) 254 { 255 throw RuntimeException( 256 OUSTR("cannot get binary UNO to C++ mapping!"), 257 Reference< XInterface >() ); 258 } 259 260 typelib_TypeDescription * pTD = 0; 261 TYPELIB_DANGER_GET( 262 &pTD, ExceptionThrower::getCppuType().getTypeLibType() ); 263 264 UnoInterfaceReference unoI; 265 cpp2uno.mapInterface( 266 reinterpret_cast< void ** >( &unoI.m_pUnoI ), 267 static_cast< XExceptionThrower * >( ExceptionThrower::get() ), pTD ); 268 OSL_ASSERT( unoI.is() ); 269 270 typelib_TypeDescription * pMemberTD = 0; 271 TYPELIB_DANGER_GET( 272 &pMemberTD, 273 reinterpret_cast< typelib_InterfaceTypeDescription * >( pTD )-> 274 ppMembers[ 1 ] /* rethrowException() */ ); 275 276 uno_Any exc_mem; 277 uno_Any * exc = &exc_mem; 278 unoI.dispatch( pMemberTD, 0, 0, &exc ); 279 280 TYPELIB_DANGER_RELEASE( pMemberTD ); 281 TYPELIB_DANGER_RELEASE( pTD ); 282 283 if (exc == 0) 284 { 285 throw RuntimeException( 286 OUSTR("rethrowing C++ exception failed!"), 287 Reference< XInterface >() ); 288 } 289 290 Any ret; 291 uno_any_destruct( &ret, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 292 uno_type_any_constructAndConvert( 293 &ret, exc->pData, exc->pType, uno2cpp.get() ); 294 uno_any_destruct( exc, 0 ); 295 return ret; 296 } 297 298 } 299