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