xref: /trunk/main/cppuhelper/source/implbase.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 {
224     if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
225     {
226         void * p = static_cast< lang::XComponent * >( this );
227         return Any( &p, rType );
228     }
229     return OWeakObject::queryInterface( rType );
230 }
231 //__________________________________________________________________________________________________
acquire()232 void WeakComponentImplHelperBase::acquire()
233     throw ()
234 {
235     OWeakObject::acquire();
236 }
237 //__________________________________________________________________________________________________
release()238 void WeakComponentImplHelperBase::release()
239     throw ()
240 {
241     if (osl_decrementInterlockedCount( &m_refCount ) == 0) {
242         // ensure no other references are created, via the weak connection point, from now on
243         disposeWeakConnectionPoint();
244         // restore reference count:
245         osl_incrementInterlockedCount( &m_refCount );
246         if (! rBHelper.bDisposed) {
247             try {
248                 dispose();
249             }
250             catch (RuntimeException const& exc) { // don't break throw ()
251                 OSL_ENSURE(
252                     false, OUStringToOString(
253                         exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
254                 static_cast<void>(exc);
255             }
256             OSL_ASSERT( rBHelper.bDisposed );
257         }
258         OWeakObject::release();
259     }
260 }
261 //__________________________________________________________________________________________________
dispose()262 void WeakComponentImplHelperBase::dispose()
263 {
264     ClearableMutexGuard aGuard( rBHelper.rMutex );
265     if (!rBHelper.bDisposed && !rBHelper.bInDispose)
266     {
267         rBHelper.bInDispose = sal_True;
268         aGuard.clear();
269         try
270         {
271             // side effect: keeping a reference to this
272             lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
273             try
274             {
275                 rBHelper.aLC.disposeAndClear( aEvt );
276                 disposing();
277             }
278             catch (...)
279             {
280                 MutexGuard aGuard2( rBHelper.rMutex );
281                 // bDisposed and bInDispose must be set in this order:
282                 rBHelper.bDisposed = sal_True;
283                 rBHelper.bInDispose = sal_False;
284                 throw;
285             }
286             MutexGuard aGuard2( rBHelper.rMutex );
287             // bDisposed and bInDispose must be set in this order:
288             rBHelper.bDisposed = sal_True;
289             rBHelper.bInDispose = sal_False;
290         }
291         catch (RuntimeException &)
292         {
293             throw;
294         }
295         catch (Exception & exc)
296         {
297             throw RuntimeException(
298                 OUString( RTL_CONSTASCII_USTRINGPARAM(
299                               "unexpected UNO exception caught: ") ) +
300                 exc.Message, Reference< XInterface >() );
301         }
302     }
303 }
304 //__________________________________________________________________________________________________
addEventListener(Reference<lang::XEventListener> const & xListener)305 void WeakComponentImplHelperBase::addEventListener(
306     Reference< lang::XEventListener > const & xListener )
307 {
308     ClearableMutexGuard aGuard( rBHelper.rMutex );
309     if (rBHelper.bDisposed || rBHelper.bInDispose)
310     {
311         aGuard.clear();
312         lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
313         xListener->disposing( aEvt );
314     }
315     else
316     {
317         rBHelper.addListener( ::getCppuType( &xListener ), xListener );
318     }
319 }
320 //__________________________________________________________________________________________________
removeEventListener(Reference<lang::XEventListener> const & xListener)321 void WeakComponentImplHelperBase::removeEventListener(
322     Reference< lang::XEventListener > const & xListener )
323 {
324     rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
325 }
326 
327 // WeakAggComponentImplHelperBase
328 //__________________________________________________________________________________________________
WeakAggComponentImplHelperBase(Mutex & rMutex)329 WeakAggComponentImplHelperBase::WeakAggComponentImplHelperBase( Mutex & rMutex )
330     SAL_THROW( () )
331     : rBHelper( rMutex )
332 {
333 }
334 //__________________________________________________________________________________________________
~WeakAggComponentImplHelperBase()335 WeakAggComponentImplHelperBase::~WeakAggComponentImplHelperBase()
336     SAL_THROW( () )
337 {
338 }
339 //__________________________________________________________________________________________________
disposing()340 void WeakAggComponentImplHelperBase::disposing()
341 {
342 }
343 //__________________________________________________________________________________________________
queryInterface(Type const & rType)344 Any WeakAggComponentImplHelperBase::queryInterface( Type const & rType )
345 {
346     return OWeakAggObject::queryInterface( rType );
347 }
348 //__________________________________________________________________________________________________
queryAggregation(Type const & rType)349 Any WeakAggComponentImplHelperBase::queryAggregation( Type const & rType )
350 {
351     if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
352     {
353         void * p = static_cast< lang::XComponent * >( this );
354         return Any( &p, rType );
355     }
356     return OWeakAggObject::queryAggregation( rType );
357 }
358 //__________________________________________________________________________________________________
acquire()359 void WeakAggComponentImplHelperBase::acquire()
360     throw ()
361 {
362     OWeakAggObject::acquire();
363 }
364 //__________________________________________________________________________________________________
release()365 void WeakAggComponentImplHelperBase::release()
366     throw ()
367 {
368     Reference<XInterface> const xDelegator_(xDelegator);
369     if (xDelegator_.is()) {
370         OWeakAggObject::release();
371     }
372     else if (osl_decrementInterlockedCount( &m_refCount ) == 0) {
373         // ensure no other references are created, via the weak connection point, from now on
374         disposeWeakConnectionPoint();
375         // restore reference count:
376         osl_incrementInterlockedCount( &m_refCount );
377         if (! rBHelper.bDisposed) {
378             try {
379                 dispose();
380             }
381             catch (RuntimeException const& exc) { // don't break throw ()
382                 OSL_ENSURE(
383                     false, OUStringToOString(
384                         exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
385                 static_cast<void>(exc);
386             }
387             OSL_ASSERT( rBHelper.bDisposed );
388         }
389         OWeakAggObject::release();
390     }
391 }
392 //__________________________________________________________________________________________________
dispose()393 void WeakAggComponentImplHelperBase::dispose()
394 {
395     ClearableMutexGuard aGuard( rBHelper.rMutex );
396     if (!rBHelper.bDisposed && !rBHelper.bInDispose)
397     {
398         rBHelper.bInDispose = sal_True;
399         aGuard.clear();
400         try
401         {
402             // side effect: keeping a reference to this
403             lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
404             try
405             {
406                 rBHelper.aLC.disposeAndClear( aEvt );
407                 disposing();
408             }
409             catch (...)
410             {
411                 MutexGuard aGuard2( rBHelper.rMutex );
412                 // bDisposed and bInDispose must be set in this order:
413                 rBHelper.bDisposed = sal_True;
414                 rBHelper.bInDispose = sal_False;
415                 throw;
416             }
417             MutexGuard aGuard2( rBHelper.rMutex );
418             // bDisposed and bInDispose must be set in this order:
419             rBHelper.bDisposed = sal_True;
420             rBHelper.bInDispose = sal_False;
421         }
422         catch (RuntimeException &)
423         {
424             throw;
425         }
426         catch (Exception & exc)
427         {
428             throw RuntimeException(
429                 OUString( RTL_CONSTASCII_USTRINGPARAM(
430                               "unexpected UNO exception caught: ") ) +
431                 exc.Message, Reference< XInterface >() );
432         }
433     }
434 }
435 //__________________________________________________________________________________________________
addEventListener(Reference<lang::XEventListener> const & xListener)436 void WeakAggComponentImplHelperBase::addEventListener(
437     Reference< lang::XEventListener > const & xListener )
438 {
439     ClearableMutexGuard aGuard( rBHelper.rMutex );
440     if (rBHelper.bDisposed || rBHelper.bInDispose)
441     {
442         aGuard.clear();
443         lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
444         xListener->disposing( aEvt );
445     }
446     else
447     {
448         rBHelper.addListener( ::getCppuType( &xListener ), xListener );
449     }
450 }
451 //__________________________________________________________________________________________________
removeEventListener(Reference<lang::XEventListener> const & xListener)452 void WeakAggComponentImplHelperBase::removeEventListener(
453     Reference< lang::XEventListener > const & xListener )
454 {
455     rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
456 }
457 
458 }
459