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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_cppuhelper.hxx" 26 27 #include "osl/diagnose.h" 28 #include "osl/doublecheckedlocking.h" 29 #include "osl/mutex.hxx" 30 #include "uno/dispatcher.hxx" 31 #include "uno/mapping.hxx" 32 #include "cppuhelper/detail/XExceptionThrower.hpp" 33 #include "com/sun/star/uno/RuntimeException.hpp" 34 35 #include "cppuhelper/exc_hlp.hxx" 36 37 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 38 39 40 using namespace ::rtl; 41 using namespace ::osl; 42 using namespace ::cppu; 43 using namespace ::com::sun::star; 44 using namespace ::com::sun::star::uno; 45 46 namespace 47 { 48 49 using cppuhelper::detail::XExceptionThrower; 50 51 //============================================================================== 52 struct ExceptionThrower : public uno_Interface, XExceptionThrower 53 { 54 inline ExceptionThrower(); 55 56 public: 57 static ExceptionThrower * get(); 58 static inline Type const & getCppuType() 59 { 60 return ::getCppuType( 61 reinterpret_cast< Reference< XExceptionThrower > const * >(0) ); 62 } 63 64 // XInterface 65 virtual Any SAL_CALL queryInterface( Type const & type ); 66 virtual void SAL_CALL acquire() throw (); 67 virtual void SAL_CALL release() throw (); 68 69 // XExceptionThrower 70 virtual void SAL_CALL throwException( Any const & exc ); 71 virtual void SAL_CALL rethrowException(); 72 }; 73 74 extern "C" 75 { 76 77 //------------------------------------------------------------------------------ 78 static void SAL_CALL ExceptionThrower_acquire_release_nop( uno_Interface * ) 79 { 80 } 81 82 //------------------------------------------------------------------------------ 83 static void SAL_CALL ExceptionThrower_dispatch( 84 uno_Interface * pUnoI, typelib_TypeDescription const * pMemberType, 85 void * pReturn, void * pArgs [], uno_Any ** ppException ) 86 { 87 OSL_ASSERT( pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD ); 88 89 switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription * >( 90 const_cast< typelib_TypeDescription * >( pMemberType ) )-> 91 nPosition) 92 { 93 case 0: // queryInterace() 94 { 95 Type const & rType_demanded = 96 *reinterpret_cast< Type const * >( pArgs[ 0 ] ); 97 if (rType_demanded.equals( 98 ::getCppuType( reinterpret_cast< 99 Reference< XInterface > const * >(0) ) ) || 100 rType_demanded.equals( ExceptionThrower::getCppuType() )) 101 { 102 typelib_TypeDescription * pTD = 0; 103 TYPELIB_DANGER_GET( &pTD, rType_demanded.getTypeLibType() ); 104 uno_any_construct( 105 reinterpret_cast< uno_Any * >( pReturn ), &pUnoI, pTD, 0 ); 106 TYPELIB_DANGER_RELEASE( pTD ); 107 } 108 else 109 { 110 uno_any_construct( 111 reinterpret_cast< uno_Any * >( pReturn ), 0, 0, 0 ); 112 } 113 *ppException = 0; 114 break; 115 } 116 case 1: // acquire() 117 case 2: // release() 118 *ppException = 0; 119 break; 120 case 3: // throwException() 121 { 122 uno_Any * pAny = reinterpret_cast< uno_Any * >( pArgs[ 0 ] ); 123 OSL_ASSERT( pAny->pType->eTypeClass == typelib_TypeClass_EXCEPTION ); 124 uno_type_any_construct( *ppException, pAny->pData, pAny->pType, 0 ); 125 break; 126 } 127 default: 128 { 129 OSL_ASSERT( 0 ); 130 RuntimeException exc( 131 OUSTR("not implemented!"), Reference< XInterface >() ); 132 uno_type_any_construct( 133 *ppException, &exc, ::getCppuType( &exc ).getTypeLibType(), 0 ); 134 break; 135 } 136 } 137 } 138 139 } // extern "C" 140 141 //______________________________________________________________________________ 142 Any ExceptionThrower::queryInterface( Type const & type ) 143 { 144 if (type.equals( ::getCppuType( reinterpret_cast< 145 Reference< XInterface > const * >(0) ) ) || 146 type.equals( ExceptionThrower::getCppuType() )) 147 { 148 XExceptionThrower * that = static_cast< XExceptionThrower * >( this ); 149 return Any( &that, type ); 150 } 151 return Any(); 152 } 153 154 //______________________________________________________________________________ 155 void ExceptionThrower::acquire() throw () 156 { 157 } 158 //______________________________________________________________________________ 159 void ExceptionThrower::release() throw () 160 { 161 } 162 163 //______________________________________________________________________________ 164 void ExceptionThrower::throwException( Any const & exc ) 165 { 166 OSL_ENSURE( 0, "unexpected!" ); 167 ::cppu::throwException( exc ); 168 } 169 170 //______________________________________________________________________________ 171 void ExceptionThrower::rethrowException() 172 { 173 throw; 174 } 175 176 //______________________________________________________________________________ 177 inline ExceptionThrower::ExceptionThrower() 178 { 179 uno_Interface::acquire = ExceptionThrower_acquire_release_nop; 180 uno_Interface::release = ExceptionThrower_acquire_release_nop; 181 uno_Interface::pDispatcher = ExceptionThrower_dispatch; 182 } 183 184 //______________________________________________________________________________ 185 ExceptionThrower * ExceptionThrower::get() 186 { 187 ExceptionThrower * s_pThrower = 0; 188 if (s_pThrower == 0) 189 { 190 MutexGuard guard( Mutex::getGlobalMutex() ); 191 static ExceptionThrower s_thrower; 192 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 193 s_pThrower = &s_thrower; 194 } 195 else 196 { 197 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 198 } 199 return s_pThrower; 200 } 201 202 } // anonymous namespace 203 204 205 namespace cppu 206 { 207 208 //============================================================================== 209 void SAL_CALL throwException( Any const & exc ) 210 { 211 if (exc.getValueTypeClass() != TypeClass_EXCEPTION) 212 { 213 throw RuntimeException( 214 OUSTR("no UNO exception given " 215 "(must be derived from com::sun::star::uno::Exception)!"), 216 Reference< XInterface >() ); 217 } 218 219 Mapping uno2cpp(Environment(OUSTR(UNO_LB_UNO)), Environment::getCurrent()); 220 if (! uno2cpp.is()) 221 { 222 throw RuntimeException( 223 OUSTR("cannot get binary UNO to C++ mapping!"), 224 Reference< XInterface >() ); 225 } 226 227 Reference< XExceptionThrower > xThrower; 228 uno2cpp.mapInterface( 229 reinterpret_cast< void ** >( &xThrower ), 230 static_cast< uno_Interface * >( ExceptionThrower::get() ), 231 ExceptionThrower::getCppuType() ); 232 OSL_ASSERT( xThrower.is() ); 233 xThrower->throwException( exc ); 234 } 235 236 //============================================================================== 237 Any SAL_CALL getCaughtException() 238 { 239 Mapping cpp2uno(Environment::getCurrent(), Environment(OUSTR(UNO_LB_UNO))); 240 if (! cpp2uno.is()) 241 { 242 throw RuntimeException( 243 OUSTR("cannot get C++ to binary UNO mapping!"), 244 Reference< XInterface >() ); 245 } 246 Mapping uno2cpp(Environment(OUSTR(UNO_LB_UNO)), Environment::getCurrent()); 247 if (! uno2cpp.is()) 248 { 249 throw RuntimeException( 250 OUSTR("cannot get binary UNO to C++ mapping!"), 251 Reference< XInterface >() ); 252 } 253 254 typelib_TypeDescription * pTD = 0; 255 TYPELIB_DANGER_GET( 256 &pTD, ExceptionThrower::getCppuType().getTypeLibType() ); 257 258 UnoInterfaceReference unoI; 259 cpp2uno.mapInterface( 260 reinterpret_cast< void ** >( &unoI.m_pUnoI ), 261 static_cast< XExceptionThrower * >( ExceptionThrower::get() ), pTD ); 262 OSL_ASSERT( unoI.is() ); 263 264 typelib_TypeDescription * pMemberTD = 0; 265 TYPELIB_DANGER_GET( 266 &pMemberTD, 267 reinterpret_cast< typelib_InterfaceTypeDescription * >( pTD )-> 268 ppMembers[ 1 ] /* rethrowException() */ ); 269 270 uno_Any exc_mem; 271 uno_Any * exc = &exc_mem; 272 unoI.dispatch( pMemberTD, 0, 0, &exc ); 273 274 TYPELIB_DANGER_RELEASE( pMemberTD ); 275 TYPELIB_DANGER_RELEASE( pTD ); 276 277 if (exc == 0) 278 { 279 throw RuntimeException( 280 OUSTR("rethrowing C++ exception failed!"), 281 Reference< XInterface >() ); 282 } 283 284 Any ret; 285 uno_any_destruct( &ret, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 286 uno_type_any_constructAndConvert( 287 &ret, exc->pData, exc->pType, uno2cpp.get() ); 288 uno_any_destruct( exc, 0 ); 289 return ret; 290 } 291 292 } 293