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 : #include <cppuhelper/implbase.hxx>
21 : #include <cppuhelper/compbase.hxx>
22 : #include <osl/diagnose.h>
23 : #include <rtl/instance.hxx>
24 : #include <rtl/string.hxx>
25 :
26 : #include <com/sun/star/lang/XComponent.hpp>
27 : #include "com/sun/star/uno/RuntimeException.hpp"
28 :
29 : using namespace ::osl;
30 : using namespace ::com::sun::star;
31 : using namespace ::com::sun::star::uno;
32 :
33 : using rtl::OUString;
34 : using rtl::OString;
35 :
36 : namespace
37 : {
38 : class theImplHelperInitMutex : public rtl::Static<Mutex, theImplHelperInitMutex>{};
39 : }
40 :
41 : namespace cppu
42 : {
43 :
44 14 : Mutex & SAL_CALL getImplHelperInitMutex(void) SAL_THROW(())
45 : {
46 14 : return theImplHelperInitMutex::get();
47 : }
48 :
49 : // ClassDataBase
50 :
51 0 : ClassDataBase::ClassDataBase() SAL_THROW(())
52 : : bOffsetsInit( sal_False )
53 : , nType2Offset( 0 )
54 : , nClassCode( 0 )
55 : , pTypes( 0 )
56 0 : , pId( 0 )
57 : {
58 0 : }
59 :
60 0 : ClassDataBase::ClassDataBase( sal_Int32 nClassCode_ ) SAL_THROW(())
61 : : bOffsetsInit( sal_False )
62 : , nType2Offset( 0 )
63 : , nClassCode( nClassCode_ )
64 : , pTypes( 0 )
65 0 : , pId( 0 )
66 : {
67 0 : }
68 :
69 0 : ClassDataBase::~ClassDataBase() SAL_THROW(())
70 : {
71 0 : delete pTypes;
72 0 : delete pId;
73 :
74 0 : for ( sal_Int32 nPos = nType2Offset; nPos--; )
75 : {
76 : typelib_typedescription_release(
77 0 : (typelib_TypeDescription *)((ClassData *)this)->arType2Offset[nPos].pTD );
78 : }
79 0 : }
80 :
81 : // ClassData
82 :
83 0 : void ClassData::writeTypeOffset( const Type & rType, sal_Int32 nOffset ) SAL_THROW(())
84 : {
85 0 : arType2Offset[nType2Offset].nOffset = nOffset;
86 :
87 0 : arType2Offset[nType2Offset].pTD = 0;
88 : typelib_typedescriptionreference_getDescription(
89 0 : (typelib_TypeDescription **)&arType2Offset[nType2Offset].pTD, rType.getTypeLibType() );
90 :
91 0 : if (arType2Offset[nType2Offset].pTD)
92 0 : ++nType2Offset;
93 : #if OSL_DEBUG_LEVEL > 1
94 : else
95 : {
96 : OString msg( "### cannot get type description for " );
97 : msg += OUStringToOString( rType.getTypeName(), RTL_TEXTENCODING_ASCII_US );
98 : OSL_FAIL( msg.getStr() );
99 : }
100 : #endif
101 0 : }
102 :
103 0 : void ClassData::initTypeProvider() SAL_THROW(())
104 : {
105 0 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
106 0 : if (! pTypes)
107 : {
108 : // collect types
109 : Sequence< Type > * types = new Sequence< Type >(
110 0 : nType2Offset + 1 + (nClassCode == 4 ? 2 : nClassCode) );
111 0 : Type * pTypeAr = types->getArray();
112 :
113 : // given types
114 0 : sal_Int32 nPos = nType2Offset;
115 0 : while (nPos--)
116 0 : pTypeAr[nPos] = ((typelib_TypeDescription *)arType2Offset[nPos].pTD)->pWeakRef;
117 :
118 : // XTypeProvider
119 0 : pTypeAr[nType2Offset] = ::getCppuType( (const Reference< lang::XTypeProvider > *)0 );
120 :
121 : // class code extra types: [[XComponent,] XWeak[, XAggregation]]
122 0 : switch (nClassCode)
123 : {
124 : case 4:
125 0 : pTypeAr[nType2Offset +2] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
126 0 : pTypeAr[nType2Offset +1] = ::getCppuType( (const Reference< XWeak > *)0 );
127 0 : break;
128 : case 3:
129 0 : pTypeAr[nType2Offset +3] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
130 : case 2:
131 0 : pTypeAr[nType2Offset +2] = ::getCppuType( (const Reference< XAggregation > *)0 );
132 : case 1:
133 0 : pTypeAr[nType2Offset +1] = ::getCppuType( (const Reference< XWeak > *)0 );
134 : }
135 :
136 0 : pTypes = types;
137 0 : }
138 0 : }
139 :
140 0 : Sequence< Type > ClassData::getTypes() SAL_THROW(())
141 : {
142 0 : if (! pTypes)
143 0 : initTypeProvider();
144 0 : return *pTypes;
145 : }
146 :
147 0 : Sequence< sal_Int8 > ClassData::getImplementationId() SAL_THROW(())
148 : {
149 0 : return css::uno::Sequence<sal_Int8>();
150 : }
151 :
152 :
153 0 : static inline bool td_equals(
154 : typelib_TypeDescription * pTD, typelib_TypeDescriptionReference * pType )
155 : SAL_THROW(())
156 : {
157 0 : return (pTD->pWeakRef == pType ||
158 0 : (pTD->pTypeName->length == pType->pTypeName->length &&
159 0 : rtl_ustr_compare( pTD->pTypeName->buffer, pType->pTypeName->buffer ) == 0));
160 : }
161 :
162 0 : Any ClassData::query( const Type & rType, lang::XTypeProvider * pBase ) SAL_THROW(())
163 : {
164 0 : if (rType == ::getCppuType( (const Reference< XInterface > *)0 ))
165 0 : return Any( &pBase, ::getCppuType( (const Reference< XInterface > *)0 ) );
166 0 : for ( sal_Int32 nPos = 0; nPos < nType2Offset; ++nPos )
167 : {
168 0 : const Type_Offset & rTO = arType2Offset[nPos];
169 0 : typelib_InterfaceTypeDescription * pTD = rTO.pTD;
170 0 : while (pTD)
171 : {
172 0 : if (td_equals( (typelib_TypeDescription *)pTD,
173 0 : *(typelib_TypeDescriptionReference **)&rType ))
174 : {
175 0 : void * pInterface = (char *)pBase + rTO.nOffset;
176 0 : return Any( &pInterface, (typelib_TypeDescription *)pTD );
177 : }
178 0 : pTD = pTD->pBaseTypeDescription;
179 : }
180 : }
181 0 : if (rType == ::getCppuType( (const Reference< lang::XTypeProvider > *)0 ))
182 0 : return Any( &pBase, ::getCppuType( (const Reference< lang::XTypeProvider > *)0 ) );
183 :
184 0 : return Any();
185 : }
186 :
187 :
188 :
189 :
190 :
191 : // WeakComponentImplHelperBase
192 :
193 4 : WeakComponentImplHelperBase::WeakComponentImplHelperBase( Mutex & rMutex )
194 : SAL_THROW(())
195 4 : : rBHelper( rMutex )
196 : {
197 4 : }
198 :
199 4 : WeakComponentImplHelperBase::~WeakComponentImplHelperBase()
200 : SAL_THROW(())
201 : {
202 4 : }
203 :
204 0 : void WeakComponentImplHelperBase::disposing()
205 : {
206 0 : }
207 :
208 7 : Any WeakComponentImplHelperBase::queryInterface( Type const & rType )
209 : throw (RuntimeException, std::exception)
210 : {
211 7 : if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
212 : {
213 5 : void * p = static_cast< lang::XComponent * >( this );
214 5 : return Any( &p, rType );
215 : }
216 2 : return OWeakObject::queryInterface( rType );
217 : }
218 :
219 229 : void WeakComponentImplHelperBase::acquire()
220 : throw ()
221 : {
222 229 : OWeakObject::acquire();
223 229 : }
224 :
225 229 : void WeakComponentImplHelperBase::release()
226 : throw ()
227 : {
228 229 : if (osl_atomic_decrement( &m_refCount ) == 0) {
229 : // ensure no other references are created, via the weak connection point, from now on
230 4 : disposeWeakConnectionPoint();
231 : // restore reference count:
232 4 : osl_atomic_increment( &m_refCount );
233 4 : if (! rBHelper.bDisposed) {
234 : try {
235 0 : dispose();
236 : }
237 0 : catch (RuntimeException const& exc) { // don't break throw ()
238 : OSL_FAIL(
239 : OUStringToOString(
240 : exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
241 : static_cast<void>(exc);
242 : }
243 : OSL_ASSERT( rBHelper.bDisposed );
244 : }
245 4 : OWeakObject::release();
246 : }
247 229 : }
248 :
249 4 : void WeakComponentImplHelperBase::dispose()
250 : throw (RuntimeException, std::exception)
251 : {
252 4 : ClearableMutexGuard aGuard( rBHelper.rMutex );
253 4 : if (!rBHelper.bDisposed && !rBHelper.bInDispose)
254 : {
255 4 : rBHelper.bInDispose = sal_True;
256 4 : aGuard.clear();
257 : try
258 : {
259 : // side effect: keeping a reference to this
260 4 : lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
261 : try
262 : {
263 4 : rBHelper.aLC.disposeAndClear( aEvt );
264 4 : disposing();
265 : }
266 0 : catch (...)
267 : {
268 0 : MutexGuard aGuard2( rBHelper.rMutex );
269 : // bDisposed and bInDispose must be set in this order:
270 0 : rBHelper.bDisposed = sal_True;
271 0 : rBHelper.bInDispose = sal_False;
272 0 : throw;
273 : }
274 8 : MutexGuard aGuard2( rBHelper.rMutex );
275 : // bDisposed and bInDispose must be set in this order:
276 4 : rBHelper.bDisposed = sal_True;
277 8 : rBHelper.bInDispose = sal_False;
278 : }
279 0 : catch (RuntimeException &)
280 : {
281 0 : throw;
282 : }
283 0 : catch (Exception & exc)
284 : {
285 : throw RuntimeException(
286 : OUString(
287 0 : "unexpected UNO exception caught: ") +
288 0 : exc.Message, Reference< XInterface >() );
289 : }
290 4 : }
291 4 : }
292 :
293 1 : void WeakComponentImplHelperBase::addEventListener(
294 : Reference< lang::XEventListener > const & xListener )
295 : throw (RuntimeException, std::exception)
296 : {
297 1 : ClearableMutexGuard aGuard( rBHelper.rMutex );
298 1 : if (rBHelper.bDisposed || rBHelper.bInDispose)
299 : {
300 0 : aGuard.clear();
301 0 : lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
302 0 : xListener->disposing( aEvt );
303 : }
304 : else
305 : {
306 1 : rBHelper.addListener( ::getCppuType( &xListener ), xListener );
307 1 : }
308 1 : }
309 :
310 0 : void WeakComponentImplHelperBase::removeEventListener(
311 : Reference< lang::XEventListener > const & xListener )
312 : throw (RuntimeException, std::exception)
313 : {
314 0 : rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
315 0 : }
316 :
317 : // WeakAggComponentImplHelperBase
318 :
319 0 : WeakAggComponentImplHelperBase::WeakAggComponentImplHelperBase( Mutex & rMutex )
320 : SAL_THROW(())
321 0 : : rBHelper( rMutex )
322 : {
323 0 : }
324 :
325 0 : WeakAggComponentImplHelperBase::~WeakAggComponentImplHelperBase()
326 : SAL_THROW(())
327 : {
328 0 : }
329 :
330 0 : void WeakAggComponentImplHelperBase::disposing()
331 : {
332 0 : }
333 :
334 0 : Any WeakAggComponentImplHelperBase::queryInterface( Type const & rType )
335 : throw (RuntimeException, std::exception)
336 : {
337 0 : return OWeakAggObject::queryInterface( rType );
338 : }
339 :
340 0 : Any WeakAggComponentImplHelperBase::queryAggregation( Type const & rType )
341 : throw (RuntimeException, std::exception)
342 : {
343 0 : if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
344 : {
345 0 : void * p = static_cast< lang::XComponent * >( this );
346 0 : return Any( &p, rType );
347 : }
348 0 : return OWeakAggObject::queryAggregation( rType );
349 : }
350 :
351 0 : void WeakAggComponentImplHelperBase::acquire()
352 : throw ()
353 : {
354 0 : OWeakAggObject::acquire();
355 0 : }
356 :
357 0 : void WeakAggComponentImplHelperBase::release()
358 : throw ()
359 : {
360 0 : Reference<XInterface> const xDelegator_(xDelegator);
361 0 : if (xDelegator_.is()) {
362 0 : OWeakAggObject::release();
363 : }
364 0 : else if (osl_atomic_decrement( &m_refCount ) == 0) {
365 : // ensure no other references are created, via the weak connection point, from now on
366 0 : disposeWeakConnectionPoint();
367 : // restore reference count:
368 0 : osl_atomic_increment( &m_refCount );
369 0 : if (! rBHelper.bDisposed) {
370 : try {
371 0 : dispose();
372 : }
373 0 : catch (RuntimeException const& exc) { // don't break throw ()
374 : OSL_FAIL(
375 : OUStringToOString(
376 : exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
377 : static_cast<void>(exc);
378 : }
379 : OSL_ASSERT( rBHelper.bDisposed );
380 : }
381 0 : OWeakAggObject::release();
382 0 : }
383 0 : }
384 :
385 0 : void WeakAggComponentImplHelperBase::dispose()
386 : throw (RuntimeException, std::exception)
387 : {
388 0 : ClearableMutexGuard aGuard( rBHelper.rMutex );
389 0 : if (!rBHelper.bDisposed && !rBHelper.bInDispose)
390 : {
391 0 : rBHelper.bInDispose = sal_True;
392 0 : aGuard.clear();
393 : try
394 : {
395 : // side effect: keeping a reference to this
396 0 : lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
397 : try
398 : {
399 0 : rBHelper.aLC.disposeAndClear( aEvt );
400 0 : disposing();
401 : }
402 0 : catch (...)
403 : {
404 0 : MutexGuard aGuard2( rBHelper.rMutex );
405 : // bDisposed and bInDispose must be set in this order:
406 0 : rBHelper.bDisposed = sal_True;
407 0 : rBHelper.bInDispose = sal_False;
408 0 : throw;
409 : }
410 0 : MutexGuard aGuard2( rBHelper.rMutex );
411 : // bDisposed and bInDispose must be set in this order:
412 0 : rBHelper.bDisposed = sal_True;
413 0 : rBHelper.bInDispose = sal_False;
414 : }
415 0 : catch (RuntimeException &)
416 : {
417 0 : throw;
418 : }
419 0 : catch (Exception & exc)
420 : {
421 : throw RuntimeException(
422 : OUString(
423 0 : "unexpected UNO exception caught: ") +
424 0 : exc.Message, Reference< XInterface >() );
425 : }
426 0 : }
427 0 : }
428 :
429 0 : void WeakAggComponentImplHelperBase::addEventListener(
430 : Reference< lang::XEventListener > const & xListener )
431 : throw (RuntimeException, std::exception)
432 : {
433 0 : ClearableMutexGuard aGuard( rBHelper.rMutex );
434 0 : if (rBHelper.bDisposed || rBHelper.bInDispose)
435 : {
436 0 : aGuard.clear();
437 0 : lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
438 0 : xListener->disposing( aEvt );
439 : }
440 : else
441 : {
442 0 : rBHelper.addListener( ::getCppuType( &xListener ), xListener );
443 0 : }
444 0 : }
445 :
446 0 : void WeakAggComponentImplHelperBase::removeEventListener(
447 : Reference< lang::XEventListener > const & xListener )
448 : throw (RuntimeException, std::exception)
449 : {
450 0 : rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
451 0 : }
452 :
453 : }
454 :
455 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|