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