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