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