1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cppuhelper.hxx"
30 
31 #include <cppuhelper/interfacecontainer.hxx>
32 #include <cppuhelper/queryinterface.hxx>
33 #include <cppuhelper/propshlp.hxx>
34 
35 #include <osl/diagnose.h>
36 #include <osl/mutex.hxx>
37 
38 #include <hash_map>
39 
40 #include <com/sun/star/lang/XEventListener.hpp>
41 
42 
43 using namespace osl;
44 using namespace com::sun::star::uno;
45 using namespace com::sun::star::lang;
46 
47 namespace cppu
48 {
49 
50 //===================================================================
51 //===================================================================
52 //===================================================================
53 /**
54  * Reallocate the sequence.
55  */
56 static void realloc( Sequence< Reference< XInterface > > & rSeq, sal_Int32 nNewLen )
57 	SAL_THROW( () )
58 {
59 	rSeq.realloc( nNewLen );
60 }
61 
62 /**
63  * Remove an element from an interface sequence.
64  */
65 static void sequenceRemoveElementAt( Sequence< Reference< XInterface > > & rSeq, sal_Int32 index )
66 	SAL_THROW( () )
67 {
68 	sal_Int32 nNewLen = rSeq.getLength() - 1;
69 
70 	Sequence< Reference< XInterface > > aDestSeq( rSeq.getLength() - 1 );
71 	// getArray on a const sequence is faster
72 	const Reference< XInterface > * pSource = ((const Sequence< Reference< XInterface > > &)rSeq).getConstArray();
73 	Reference< XInterface > * pDest = aDestSeq.getArray();
74 	sal_Int32 i = 0;
75 	for( ; i < index; i++ )
76 		pDest[i] = pSource[i];
77 	for( sal_Int32 j = i ; j < nNewLen; j++ )
78 		pDest[j] = pSource[j+1];
79 	rSeq = aDestSeq;
80 }
81 
82 
83 //-----------------------------------------------------------------------------
84 //-----------------------------------------------------------------------------
85 
86 #ifdef _MSC_VER
87 #pragma warning( disable: 4786 )
88 #endif
89 
90 //===================================================================
91 //===================================================================
92 //===================================================================
93 OInterfaceIteratorHelper::OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont_ )
94 	SAL_THROW( () )
95 	: rCont( rCont_ )
96 {
97 	MutexGuard aGuard( rCont.rMutex );
98 	if( rCont.bInUse )
99 		// worst case, two iterators at the same time
100 		rCont.copyAndResetInUse();
101 	bIsList = rCont_.bIsList;
102 	aData = rCont_.aData;
103 	if( bIsList )
104 	{
105 		rCont.bInUse = sal_True;
106 		nRemain = aData.pAsSequence->getLength();
107 	}
108 	else if( aData.pAsInterface )
109 	{
110 		aData.pAsInterface->acquire();
111 		nRemain = 1;
112 	}
113 	else
114 		nRemain = 0;
115 }
116 
117 OInterfaceIteratorHelper::~OInterfaceIteratorHelper() SAL_THROW( () )
118 {
119 	sal_Bool bShared;
120 	{
121 	MutexGuard aGuard( rCont.rMutex );
122 	// bResetInUse protect the iterator against recursion
123 	bShared = aData.pAsSequence == rCont.aData.pAsSequence && rCont.bIsList;
124 	if( bShared )
125 	{
126 		OSL_ENSURE( rCont.bInUse, "OInterfaceContainerHelper must be in use" );
127 		rCont.bInUse = sal_False;
128 	}
129 	}
130 
131 	if( !bShared )
132 	{
133 		if( bIsList )
134 			// Sequence owned by the iterator
135 			delete aData.pAsSequence;
136 		else if( aData.pAsInterface )
137 			// Interface is acquired by the iterator
138 			aData.pAsInterface->release();
139 	}
140 }
141 
142 XInterface * OInterfaceIteratorHelper::next() SAL_THROW( () )
143 {
144 	if( nRemain )
145 	{
146 		nRemain--;
147 		if( bIsList )
148 			// typecase to const,so the getArray method is faster
149 			return aData.pAsSequence->getConstArray()[nRemain].get();
150 		else if( aData.pAsInterface )
151 			return aData.pAsInterface;
152 	}
153 	// exception
154 	return 0;
155 }
156 
157 void OInterfaceIteratorHelper::remove() SAL_THROW( () )
158 {
159 	if( bIsList )
160 	{
161 		OSL_ASSERT( nRemain >= 0 &&
162 					nRemain < aData.pAsSequence->getLength() );
163         XInterface * p = aData.pAsSequence->getConstArray()[nRemain].get();
164 		rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >( &p ) );
165 	}
166 	else
167 	{
168 		OSL_ASSERT( 0 == nRemain );
169 		rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >(&aData.pAsInterface));
170 	}
171 }
172 
173 //===================================================================
174 //===================================================================
175 //===================================================================
176 
177 
178 OInterfaceContainerHelper::OInterfaceContainerHelper( Mutex & rMutex_ ) SAL_THROW( () )
179 	: rMutex( rMutex_ )
180 	, bInUse( sal_False )
181 	, bIsList( sal_False )
182 {
183 }
184 
185 OInterfaceContainerHelper::~OInterfaceContainerHelper() SAL_THROW( () )
186 {
187 	OSL_ENSURE( !bInUse, "~OInterfaceContainerHelper but is in use" );
188 	if( bIsList )
189 		delete aData.pAsSequence;
190 	else if( aData.pAsInterface )
191 		aData.pAsInterface->release();
192 }
193 
194 sal_Int32 OInterfaceContainerHelper::getLength() const SAL_THROW( () )
195 {
196 	MutexGuard aGuard( rMutex );
197 	if( bIsList )
198 		return aData.pAsSequence->getLength();
199 	else if( aData.pAsInterface )
200 		return 1;
201 	return 0;
202 }
203 
204 Sequence< Reference<XInterface> > OInterfaceContainerHelper::getElements() const SAL_THROW( () )
205 {
206 	MutexGuard aGuard( rMutex );
207 	if( bIsList )
208 		return *aData.pAsSequence;
209 	else if( aData.pAsInterface )
210 	{
211 		Reference<XInterface> x( aData.pAsInterface );
212 		return Sequence< Reference< XInterface > >( &x, 1 );
213 	}
214 	return Sequence< Reference< XInterface > >();
215 }
216 
217 void OInterfaceContainerHelper::copyAndResetInUse() SAL_THROW( () )
218 {
219 	OSL_ENSURE( bInUse, "OInterfaceContainerHelper not in use" );
220 	if( bInUse )
221 	{
222 		// this should be the worst case. If a iterator is active
223 		// and a new Listener is added.
224 		if( bIsList )
225 			aData.pAsSequence = new Sequence< Reference< XInterface > >( *aData.pAsSequence );
226 		else if( aData.pAsInterface )
227 			aData.pAsInterface->acquire();
228 
229 		bInUse = sal_False;
230 	}
231 }
232 
233 sal_Int32 OInterfaceContainerHelper::addInterface( const Reference<XInterface> & rListener ) SAL_THROW( () )
234 {
235 	OSL_ASSERT( rListener.is() );
236 	MutexGuard aGuard( rMutex );
237 	if( bInUse )
238 		copyAndResetInUse();
239 
240 	if( bIsList )
241 	{
242 		sal_Int32 nLen = aData.pAsSequence->getLength();
243 		realloc( *aData.pAsSequence, nLen +1 );
244 		aData.pAsSequence->getArray()[ nLen ] = rListener;
245 		return nLen +1;
246 	}
247 	else if( aData.pAsInterface )
248 	{
249 		Sequence< Reference< XInterface > > * pSeq = new Sequence< Reference< XInterface > >( 2 );
250 		Reference<XInterface> * pArray = pSeq->getArray();
251 		pArray[0] = aData.pAsInterface;
252 		pArray[1] = rListener;
253 		aData.pAsInterface->release();
254 		aData.pAsSequence = pSeq;
255 		bIsList = sal_True;
256 		return 2;
257 	}
258 	else
259 	{
260 		aData.pAsInterface = rListener.get();
261 		if( rListener.is() )
262 			rListener->acquire();
263 		return 1;
264 	}
265 }
266 
267 sal_Int32 OInterfaceContainerHelper::removeInterface( const Reference<XInterface> & rListener ) SAL_THROW( () )
268 {
269 	OSL_ASSERT( rListener.is() );
270 	MutexGuard aGuard( rMutex );
271 	if( bInUse )
272 		copyAndResetInUse();
273 
274 	if( bIsList )
275 	{
276 		const Reference<XInterface> * pL = aData.pAsSequence->getConstArray();
277 		sal_Int32 nLen = aData.pAsSequence->getLength();
278 		sal_Int32 i;
279 		for( i = 0; i < nLen; i++ )
280 		{
281 			// It is not valid to compare the Pointer direkt, but is is is much
282 			// more faster.
283 			if( pL[i].get() == rListener.get() )
284 			{
285 				sequenceRemoveElementAt( *aData.pAsSequence, i );
286 				break;
287 			}
288 		}
289 
290 		if( i == nLen )
291 		{
292 			// interface not found, use the correct compare method
293 			for( i = 0; i < nLen; i++ )
294 			{
295 				if( pL[i] == rListener )
296 				{
297 					sequenceRemoveElementAt(*aData.pAsSequence, i );
298 					break;
299 				}
300 			}
301 		}
302 
303 		if( aData.pAsSequence->getLength() == 1 )
304 		{
305 			XInterface * p = aData.pAsSequence->getConstArray()[0].get();
306 			p->acquire();
307 			delete aData.pAsSequence;
308 			aData.pAsInterface = p;
309 			bIsList = sal_False;
310 			return 1;
311 		}
312 		else
313 			return aData.pAsSequence->getLength();
314 	}
315 	else if( aData.pAsInterface && Reference<XInterface>( aData.pAsInterface ) == rListener )
316 	{
317 		aData.pAsInterface->release();
318 		aData.pAsInterface = 0;
319 	}
320 	return aData.pAsInterface ? 1 : 0;
321 }
322 
323 void OInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt ) SAL_THROW( () )
324 {
325 	ClearableMutexGuard aGuard( rMutex );
326 	OInterfaceIteratorHelper aIt( *this );
327 	// Container freigeben, falls im disposing neue Eintr�ge kommen
328 	OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" );
329 	if( !bIsList && aData.pAsInterface )
330 		aData.pAsInterface->release();
331 	// set the member to null, the iterator delete the values
332 	aData.pAsInterface = NULL;
333 	bIsList = sal_False;
334 	bInUse = sal_False;
335 	aGuard.clear();
336 	while( aIt.hasMoreElements() )
337 	{
338 		try
339 		{
340 			Reference<XEventListener > xLst( aIt.next(), UNO_QUERY );
341 			if( xLst.is() )
342 				xLst->disposing( rEvt );
343 		}
344 		catch ( RuntimeException & )
345 		{
346 			// be robust, if e.g. a remote bridge has disposed already.
347 			// there is no way, to delegate the error to the caller :o(.
348 		}
349 	}
350 }
351 
352 
353 void OInterfaceContainerHelper::clear() SAL_THROW( () )
354 {
355 	ClearableMutexGuard aGuard( rMutex );
356 	OInterfaceIteratorHelper aIt( *this );
357 	// Container freigeben, falls im disposing neue Eintr�ge kommen
358 	OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" );
359 	if( !bIsList && aData.pAsInterface )
360 		aData.pAsInterface->release();
361 	// set the member to null, the iterator delete the values
362 	aData.pAsInterface = 0;
363 	bIsList = sal_False;
364 	bInUse = sal_False;
365 	// release mutex before aIt destructor call
366 	aGuard.clear();
367 }
368 
369 //##################################################################################################
370 //##################################################################################################
371 //##################################################################################################
372 
373 // specialized class for type
374 
375 typedef ::std::vector< std::pair < Type , void* > > t_type2ptr;
376 
377 OMultiTypeInterfaceContainerHelper::OMultiTypeInterfaceContainerHelper( Mutex & rMutex_ )
378     SAL_THROW( () )
379     : rMutex( rMutex_ )
380 {
381 	m_pMap = new t_type2ptr();
382 }
383 OMultiTypeInterfaceContainerHelper::~OMultiTypeInterfaceContainerHelper()
384     SAL_THROW( () )
385 {
386     t_type2ptr * pMap = (t_type2ptr *)m_pMap;
387 	t_type2ptr::iterator iter = pMap->begin();
388 	t_type2ptr::iterator end = pMap->end();
389 
390 	while( iter != end )
391 	{
392 		delete (OInterfaceContainerHelper*)(*iter).second;
393 		(*iter).second = 0;
394 		++iter;
395 	}
396 	delete pMap;
397 }
398 Sequence< Type > OMultiTypeInterfaceContainerHelper::getContainedTypes() const
399     SAL_THROW( () )
400 {
401     t_type2ptr * pMap = (t_type2ptr *)m_pMap;
402 	t_type2ptr::size_type nSize;
403 
404 	::osl::MutexGuard aGuard( rMutex );
405 	nSize = pMap->size();
406 	if( nSize )
407 	{
408 		::com::sun::star::uno::Sequence< Type > aInterfaceTypes( nSize );
409 		Type * pArray = aInterfaceTypes.getArray();
410 
411 		t_type2ptr::iterator iter = pMap->begin();
412 		t_type2ptr::iterator end = pMap->end();
413 
414 		sal_Int32 i = 0;
415 		while( iter != end )
416 		{
417 			// are interfaces added to this container?
418 			if( ((OInterfaceContainerHelper*)(*iter).second)->getLength() )
419 				// yes, put the type in the array
420 				pArray[i++] = (*iter).first;
421 			++iter;
422 		}
423 		if( (t_type2ptr::size_type)i != nSize ) {
424 			// may be empty container, reduce the sequence to the right size
425 			aInterfaceTypes = ::com::sun::star::uno::Sequence< Type >( pArray, i );
426 		}
427 		return aInterfaceTypes;
428 	}
429 	return ::com::sun::star::uno::Sequence< Type >();
430 }
431 
432 static t_type2ptr::iterator findType(t_type2ptr *pMap, const Type & rKey )
433 {
434 	t_type2ptr::iterator iter = pMap->begin();
435 	t_type2ptr::iterator end = pMap->end();
436 
437 	while( iter != end )
438     {
439         if (iter->first == rKey)
440             break;
441         iter++;
442     }
443     return iter;
444 }
445 
446 OInterfaceContainerHelper * OMultiTypeInterfaceContainerHelper::getContainer( const Type & rKey ) const
447     SAL_THROW( () )
448 {
449 	::osl::MutexGuard aGuard( rMutex );
450 
451     t_type2ptr * pMap = (t_type2ptr *)m_pMap;
452  	t_type2ptr::iterator iter = findType( pMap, rKey );
453 	if( iter != pMap->end() )
454 			return (OInterfaceContainerHelper*) (*iter).second;
455 	return 0;
456 }
457 sal_Int32 OMultiTypeInterfaceContainerHelper::addInterface(
458     const Type & rKey, const Reference< XInterface > & rListener )
459     SAL_THROW( () )
460 {
461 	::osl::MutexGuard aGuard( rMutex );
462     t_type2ptr * pMap = (t_type2ptr *)m_pMap;
463 	t_type2ptr::iterator iter = findType( pMap, rKey );
464 	if( iter == pMap->end() )
465 	{
466 		OInterfaceContainerHelper * pLC = new OInterfaceContainerHelper( rMutex );
467         pMap->push_back(std::pair<Type, void*>(rKey, pLC));
468 		return pLC->addInterface( rListener );
469 	}
470 	else
471 		return ((OInterfaceContainerHelper*)(*iter).second)->addInterface( rListener );
472 }
473 sal_Int32 OMultiTypeInterfaceContainerHelper::removeInterface(
474     const Type & rKey, const Reference< XInterface > & rListener )
475     SAL_THROW( () )
476 {
477 	::osl::MutexGuard aGuard( rMutex );
478 
479 	// search container with id nUik
480     t_type2ptr * pMap = (t_type2ptr *)m_pMap;
481 	t_type2ptr::iterator iter = findType( pMap, rKey );
482 		// container found?
483 	if( iter != pMap->end() )
484         return ((OInterfaceContainerHelper*)(*iter).second)->removeInterface( rListener );
485 
486 	// no container with this id. Always return 0
487 	return 0;
488 }
489 void OMultiTypeInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt )
490     SAL_THROW( () )
491 {
492 	t_type2ptr::size_type nSize = 0;
493 	OInterfaceContainerHelper ** ppListenerContainers = NULL;
494 	{
495 		::osl::MutexGuard aGuard( rMutex );
496         t_type2ptr * pMap = (t_type2ptr *)m_pMap;
497 		nSize = pMap->size();
498 		if( nSize )
499 		{
500 			typedef OInterfaceContainerHelper* ppp;
501 			ppListenerContainers = new ppp[nSize];
502 			//ppListenerContainers = new (ListenerContainer*)[nSize];
503 
504 			t_type2ptr::iterator iter = pMap->begin();
505 			t_type2ptr::iterator end = pMap->end();
506 
507 			t_type2ptr::size_type i = 0;
508 			while( iter != end )
509 			{
510 				ppListenerContainers[i++] = (OInterfaceContainerHelper*)(*iter).second;
511 				++iter;
512 			}
513 		}
514 	}
515 
516 	// create a copy, because do not fire event in a guarded section
517 	for( t_type2ptr::size_type i = 0;
518 			i < nSize; i++ )
519 	{
520 		if( ppListenerContainers[i] )
521 			ppListenerContainers[i]->disposeAndClear( rEvt );
522 	}
523 
524 	delete [] ppListenerContainers;
525 }
526 void OMultiTypeInterfaceContainerHelper::clear()
527     SAL_THROW( () )
528 {
529 	::osl::MutexGuard aGuard( rMutex );
530     t_type2ptr * pMap = (t_type2ptr *)m_pMap;
531 	t_type2ptr::iterator iter = pMap->begin();
532 	t_type2ptr::iterator end = pMap->end();
533 
534 	while( iter != end )
535 	{
536 		((OInterfaceContainerHelper*)(*iter).second)->clear();
537 		++iter;
538 	}
539 }
540 
541 
542 //##################################################################################################
543 //##################################################################################################
544 //##################################################################################################
545 
546 // specialized class for long
547 
548 typedef ::std::vector< std::pair < sal_Int32 , void* > > t_long2ptr;
549 
550 static t_long2ptr::iterator findLong(t_long2ptr *pMap, sal_Int32 nKey )
551 {
552 	t_long2ptr::iterator iter = pMap->begin();
553 	t_long2ptr::iterator end = pMap->end();
554 
555 	while( iter != end )
556     {
557         if (iter->first == nKey)
558             break;
559         iter++;
560     }
561     return iter;
562 }
563 
564 OMultiTypeInterfaceContainerHelperInt32::OMultiTypeInterfaceContainerHelperInt32( Mutex & rMutex_ )
565     SAL_THROW( () )
566     : m_pMap( NULL )
567     , rMutex( rMutex_ )
568 {
569     // delay pMap allocation until necessary.
570 }
571 OMultiTypeInterfaceContainerHelperInt32::~OMultiTypeInterfaceContainerHelperInt32()
572     SAL_THROW( () )
573 {
574     if (!m_pMap)
575         return;
576 
577     t_long2ptr * pMap = (t_long2ptr *)m_pMap;
578 	t_long2ptr::iterator iter = pMap->begin();
579 	t_long2ptr::iterator end = pMap->end();
580 
581 	while( iter != end )
582 	{
583 		delete (OInterfaceContainerHelper*)(*iter).second;
584 		(*iter).second = 0;
585 		++iter;
586 	}
587 	delete pMap;
588 }
589 Sequence< sal_Int32 > OMultiTypeInterfaceContainerHelperInt32::getContainedTypes() const
590     SAL_THROW( () )
591 {
592     t_long2ptr * pMap = (t_long2ptr *)m_pMap;
593 	t_long2ptr::size_type nSize;
594 
595 	::osl::MutexGuard aGuard( rMutex );
596 	nSize = pMap ? pMap->size() : 0;
597 	if( nSize )
598 	{
599 		::com::sun::star::uno::Sequence< sal_Int32 > aInterfaceTypes( nSize );
600 		sal_Int32 * pArray = aInterfaceTypes.getArray();
601 
602 		t_long2ptr::iterator iter = pMap->begin();
603 		t_long2ptr::iterator end = pMap->end();
604 
605 		sal_Int32 i = 0;
606 		while( iter != end )
607 		{
608 			// are interfaces added to this container?
609 			if( ((OInterfaceContainerHelper*)(*iter).second)->getLength() )
610 				// yes, put the type in the array
611 				pArray[i++] = (*iter).first;
612 			++iter;
613 		}
614 		if( (t_long2ptr::size_type)i != nSize ) {
615 			// may be empty container, reduce the sequence to the right size
616 			aInterfaceTypes = ::com::sun::star::uno::Sequence< sal_Int32 >( pArray, i );
617 		}
618 		return aInterfaceTypes;
619 	}
620 	return ::com::sun::star::uno::Sequence< sal_Int32 >();
621 }
622 OInterfaceContainerHelper * OMultiTypeInterfaceContainerHelperInt32::getContainer( const sal_Int32 & rKey ) const
623     SAL_THROW( () )
624 {
625 	::osl::MutexGuard aGuard( rMutex );
626 
627     if (!m_pMap)
628         return 0;
629     t_long2ptr * pMap = (t_long2ptr *)m_pMap;
630  	t_long2ptr::iterator iter = findLong( pMap, rKey );
631 	if( iter != pMap->end() )
632 			return (OInterfaceContainerHelper*) (*iter).second;
633 	return 0;
634 }
635 sal_Int32 OMultiTypeInterfaceContainerHelperInt32::addInterface(
636     const sal_Int32 & rKey, const Reference< XInterface > & rListener )
637     SAL_THROW( () )
638 {
639 	::osl::MutexGuard aGuard( rMutex );
640     if (!m_pMap)
641     	m_pMap = new t_long2ptr();
642     t_long2ptr * pMap = (t_long2ptr *)m_pMap;
643 	t_long2ptr::iterator iter = findLong( pMap, rKey );
644  	if( iter == pMap->end() )
645 	{
646 		OInterfaceContainerHelper * pLC = new OInterfaceContainerHelper( rMutex );
647         pMap->push_back(std::pair< sal_Int32, void* >(rKey, pLC));
648 		return pLC->addInterface( rListener );
649 	}
650 	else
651 		return ((OInterfaceContainerHelper*)(*iter).second)->addInterface( rListener );
652 }
653 sal_Int32 OMultiTypeInterfaceContainerHelperInt32::removeInterface(
654     const sal_Int32 & rKey, const Reference< XInterface > & rListener )
655     SAL_THROW( () )
656 {
657 	::osl::MutexGuard aGuard( rMutex );
658 
659     if (!m_pMap)
660         return 0;
661 	// search container with id nUik
662     t_long2ptr * pMap = (t_long2ptr *)m_pMap;
663 	t_long2ptr::iterator iter = findLong( pMap, rKey );
664 		// container found?
665 	if( iter != pMap->end() )
666         return ((OInterfaceContainerHelper*)(*iter).second)->removeInterface( rListener );
667 
668 	// no container with this id. Always return 0
669 	return 0;
670 }
671 void OMultiTypeInterfaceContainerHelperInt32::disposeAndClear( const EventObject & rEvt )
672     SAL_THROW( () )
673 {
674 	t_long2ptr::size_type nSize = 0;
675 	OInterfaceContainerHelper ** ppListenerContainers = NULL;
676 	{
677 		::osl::MutexGuard aGuard( rMutex );
678         if (!m_pMap)
679             return;
680 
681         t_long2ptr * pMap = (t_long2ptr *)m_pMap;
682 		nSize = pMap->size();
683 		if( nSize )
684 		{
685 			typedef OInterfaceContainerHelper* ppp;
686 			ppListenerContainers = new ppp[nSize];
687 			//ppListenerContainers = new (ListenerContainer*)[nSize];
688 
689 			t_long2ptr::iterator iter = pMap->begin();
690 			t_long2ptr::iterator end = pMap->end();
691 
692 			t_long2ptr::size_type i = 0;
693 			while( iter != end )
694 			{
695 				ppListenerContainers[i++] = (OInterfaceContainerHelper*)(*iter).second;
696 				++iter;
697 			}
698 		}
699 	}
700 
701 	// create a copy, because do not fire event in a guarded section
702 	for( t_long2ptr::size_type i = 0;
703 			i < nSize; i++ )
704 	{
705 		if( ppListenerContainers[i] )
706 			ppListenerContainers[i]->disposeAndClear( rEvt );
707 	}
708 
709 	delete [] ppListenerContainers;
710 }
711 void OMultiTypeInterfaceContainerHelperInt32::clear()
712     SAL_THROW( () )
713 {
714 	::osl::MutexGuard aGuard( rMutex );
715     if (!m_pMap)
716         return;
717     t_long2ptr * pMap = (t_long2ptr *)m_pMap;
718 	t_long2ptr::iterator iter = pMap->begin();
719 	t_long2ptr::iterator end = pMap->end();
720 
721 	while( iter != end )
722 	{
723 		((OInterfaceContainerHelper*)(*iter).second)->clear();
724 		++iter;
725 	}
726 }
727 
728 }
729 
730