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