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