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_forms.hxx"
26 
27 #include "frm_resource.hrc"
28 #include "frm_resource.hxx"
29 #include "InterfaceContainer.hxx"
30 #include "componenttools.hxx"
31 #include "property.hrc"
32 #include "services.hxx"
33 
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/container/XNamed.hpp>
36 #include <com/sun/star/io/WrongFormatException.hpp>
37 #include <com/sun/star/io/XMarkableStream.hpp>
38 #include <com/sun/star/lang/XComponent.hpp>
39 #include <com/sun/star/util/XCloneable.hpp>
40 #include <com/sun/star/form/XForm.hpp>
41 
42 #include <comphelper/container.hxx>
43 #include <comphelper/enumhelper.hxx>
44 #include <comphelper/eventattachermgr.hxx>
45 #include <comphelper/property.hxx>
46 #include <comphelper/sequence.hxx>
47 #include <comphelper/types.hxx>
48 #include <cppuhelper/exc_hlp.hxx>
49 #include <cppuhelper/queryinterface.hxx>
50 #include <rtl/logfile.hxx>
51 #include <tools/debug.hxx>
52 #include <tools/diagnose_ex.h>
53 
54 #include <algorithm>
55 #include <memory>
56 
57 //.........................................................................
58 #include <com/sun/star/frame/XModel.hpp>
59 #include <com/sun/star/document/XCodeNameQuery.hpp>
60 #include <ooo/vba/XVBAToOOEventDescGen.hpp>
61 #include <comphelper/processfactory.hxx>
62 
63 namespace frm
64 {
65 //.........................................................................
66 
67 using namespace ::com::sun::star::frame;
68 using namespace ::com::sun::star::lang;
69 using namespace ::com::sun::star::uno;
70 using namespace ::com::sun::star::beans;
71 using namespace ::com::sun::star::document;
72 using namespace ::com::sun::star::container;
73 using namespace ::com::sun::star::script;
74 using namespace ::com::sun::star::io;
75 using namespace ::com::sun::star::form;
76 using namespace ::com::sun::star::util;
77 
78 namespace
79 {
80 	//---------------------------------------------------------------------
lcl_throwIllegalArgumentException()81 	static void lcl_throwIllegalArgumentException()
82 	{
83 		throw IllegalArgumentException();
84 	}
85 }
86 
87 bool
lcl_hasVbaEvents(const Sequence<ScriptEventDescriptor> & sEvents)88 lcl_hasVbaEvents( const Sequence< ScriptEventDescriptor >& sEvents  )
89 {
90 	const ScriptEventDescriptor* pDesc = sEvents.getConstArray();
91 	const ScriptEventDescriptor* pEnd = ( pDesc + sEvents.getLength() );
92 	for ( ; pDesc != pEnd; ++pDesc )
93 	{
94 		if ( pDesc->ScriptType.equals( rtl::OUString::createFromAscii( "VBAInterop" ) ) )
95 			return true;
96 	}
97 	return false;
98 }
99 
100 Sequence< ScriptEventDescriptor >
lcl_stripVbaEvents(const Sequence<ScriptEventDescriptor> & sEvents)101 lcl_stripVbaEvents( const Sequence< ScriptEventDescriptor >& sEvents )
102 {
103 	Sequence< ScriptEventDescriptor > sStripped( sEvents.getLength() );
104 
105 	const ScriptEventDescriptor* pDesc = sEvents.getConstArray();
106 	const ScriptEventDescriptor* pEnd = ( pDesc + sEvents.getLength() );
107 	sal_Int32 nCopied = 0;
108 	for ( ; pDesc != pEnd; ++pDesc )
109 	{
110 		if ( !pDesc->ScriptType.equals( rtl::OUString::createFromAscii( "VBAInterop" ) ) )
111 		{
112 			sStripped[ nCopied++ ] = *pDesc;
113 		}
114 	}
115 	if ( nCopied )
116 		sStripped.realloc( nCopied );
117 	return sStripped;
118 }
119 
impl_addVbEvents_nolck_nothrow(const sal_Int32 i_nIndex)120 void OInterfaceContainer::impl_addVbEvents_nolck_nothrow(  const sal_Int32 i_nIndex )
121 {
122 	// we are dealing with form controls
123 	try
124 	{
125         do
126         {
127             Reference< XModel > xDoc( getXModel( static_cast< XContainer *> ( this ) ) );
128 		    if ( !xDoc.is() )
129                 break;
130 
131             Reference< XMultiServiceFactory > xDocFac( xDoc, UNO_QUERY_THROW );
132             Reference< XCodeNameQuery > xNameQuery( xDocFac->createInstance( rtl::OUString::createFromAscii( "ooo.vba.VBACodeNameProvider" ) ), UNO_QUERY );
133             if ( !xNameQuery.is() )
134                 break;
135 
136             ::osl::MutexGuard aGuard( m_rMutex );
137             bool hasVBABindings = lcl_hasVbaEvents( m_xEventAttacher->getScriptEvents( i_nIndex ) );
138 			if ( hasVBABindings )
139 				break;
140 
141             Reference< XInterface > xElement( getByIndex( i_nIndex ) , UNO_QUERY_THROW );
142             Reference< XForm > xElementAsForm( xElement, UNO_QUERY );
143             if ( xElementAsForm.is() )
144                 break;
145 
146             ::rtl::OUString sCodeName( xNameQuery->getCodeNameForObject( xElement ) );
147 
148             Reference< XPropertySet > xProps( xElement, UNO_QUERY_THROW );
149 			::rtl::OUString sServiceName;
150 			xProps->getPropertyValue( rtl::OUString::createFromAscii("DefaultControl" ) ) >>= sServiceName;
151 
152 			Reference< ooo::vba::XVBAToOOEventDescGen > xDescSupplier( m_xServiceFactory->createInstance( rtl::OUString::createFromAscii( "ooo.vba.VBAToOOEventDesc" ) ), UNO_QUERY_THROW );
153 			Sequence< ScriptEventDescriptor > vbaEvents = xDescSupplier->getEventDescriptions( m_xServiceFactory->createInstance( sServiceName ), sCodeName );
154 			// register the vba script events
155 			m_xEventAttacher->registerScriptEvents( i_nIndex, vbaEvents );
156 		}
157         while ( false );
158 	}
159     catch ( const ServiceNotRegisteredException& )
160     {
161         // silence this, not all document types support the ooo.vba.VBACodeNameProvider service
162     }
163 	catch( const Exception& )
164 	{
165         DBG_UNHANDLED_EXCEPTION();
166 	}
167 
168 }
169 //==================================================================
170 //= ElementDescription
171 //==================================================================
172 //------------------------------------------------------------------
ElementDescription()173 ElementDescription::ElementDescription( )
174 {
175 }
176 
177 //------------------------------------------------------------------
~ElementDescription()178 ElementDescription::~ElementDescription()
179 {
180 }
181 
182 //==================================================================
183 //= OInterfaceContainer
184 //==================================================================
185 //------------------------------------------------------------------
OInterfaceContainer(const Reference<XMultiServiceFactory> & _rxFactory,::osl::Mutex & _rMutex,const Type & _rElementType)186 OInterfaceContainer::OInterfaceContainer(
187 				const Reference<XMultiServiceFactory>& _rxFactory,
188 				::osl::Mutex& _rMutex,
189 				const Type& _rElementType)
190     :OInterfaceContainer_BASE()
191     ,m_rMutex(_rMutex)
192     ,m_aContainerListeners(_rMutex)
193     ,m_aElementType(_rElementType)
194     ,m_xServiceFactory(_rxFactory)
195 {
196     impl_createEventAttacher_nothrow();
197 }
198 
199 //------------------------------------------------------------------------------
OInterfaceContainer(::osl::Mutex & _rMutex,const OInterfaceContainer & _cloneSource)200 OInterfaceContainer::OInterfaceContainer( ::osl::Mutex& _rMutex, const OInterfaceContainer& _cloneSource )
201     :OInterfaceContainer_BASE()
202     ,m_rMutex( _rMutex )
203     ,m_aContainerListeners( _rMutex )
204     ,m_aElementType( _cloneSource.m_aElementType )
205     ,m_xServiceFactory( _cloneSource.m_xServiceFactory )
206 {
207     impl_createEventAttacher_nothrow();
208 }
209 
210 //------------------------------------------------------------------------------
clonedFrom(const OInterfaceContainer & _cloneSource)211 void OInterfaceContainer::clonedFrom( const OInterfaceContainer& _cloneSource )
212 {
213     try
214     {
215         const Reference< XIndexAccess > xSourceHierarchy( const_cast< OInterfaceContainer* >( &_cloneSource ) );
216         const sal_Int32 nCount = xSourceHierarchy->getCount();
217         for ( sal_Int32 i=0; i<nCount; ++i )
218         {
219             Reference< XCloneable > xCloneable( xSourceHierarchy->getByIndex( i ), UNO_QUERY_THROW );
220             Reference< XInterface > xClone( xCloneable->createClone() );
221             insertByIndex( i, makeAny( xClone ) );
222         }
223     }
224     catch( const Exception& )
225     {
226         throw WrappedTargetException(
227             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not clone the given interface hierarchy." ) ),
228             static_cast< XIndexContainer* >( const_cast< OInterfaceContainer* >( &_cloneSource ) ),
229             ::cppu::getCaughtException()
230         );
231     }
232 }
233 
234 //------------------------------------------------------------------------------
impl_createEventAttacher_nothrow()235 void OInterfaceContainer::impl_createEventAttacher_nothrow()
236 {
237     try
238     {
239 	    m_xEventAttacher.set( ::comphelper::createEventAttacherManager( m_xServiceFactory ), UNO_SET_THROW );
240     }
241     catch( const Exception& )
242     {
243         DBG_UNHANDLED_EXCEPTION();
244     }
245 }
246 
247 //------------------------------------------------------------------------------
~OInterfaceContainer()248 OInterfaceContainer::~OInterfaceContainer()
249 {
250 }
251 
252 //------------------------------------------------------------------------------
disposing()253 void OInterfaceContainer::disposing()
254 {
255 	// dispose all elements
256 	for (sal_Int32 i = m_aItems.size(); i > 0; --i)
257 	{
258 		Reference<XPropertySet>  xSet(m_aItems[i - 1], UNO_QUERY);
259 		if (xSet.is())
260 			xSet->removePropertyChangeListener(PROPERTY_NAME, this);
261 
262 		// revoke event knittings
263         if ( m_xEventAttacher.is() )
264         {
265     		Reference< XInterface > xIfc( xSet, UNO_QUERY );
266 	    	m_xEventAttacher->detach( i - 1, xIfc );
267 		    m_xEventAttacher->removeEntry( i - 1 );
268         }
269 
270 		Reference<XComponent>  xComponent(xSet, UNO_QUERY);
271 		if (xComponent.is())
272 			xComponent->dispose();
273 	}
274 	m_aMap.clear();
275 	m_aItems.clear();
276 
277 	EventObject aEvt(static_cast<XContainer*>(this));
278 	m_aContainerListeners.disposeAndClear(aEvt);
279 }
280 
281 // XPersistObject
282 //------------------------------------------------------------------------------
283 namespace
284 {
285 	//..........................................................................
lcl_saveEvents(::std::vector<Sequence<ScriptEventDescriptor>> & _rSave,const Reference<XEventAttacherManager> & _rxManager,const sal_Int32 _nItemCount)286 	void lcl_saveEvents( ::std::vector< Sequence< ScriptEventDescriptor > >& _rSave,
287 		const Reference< XEventAttacherManager >& _rxManager, const sal_Int32 _nItemCount )
288 	{
289         OSL_ENSURE( _rxManager.is(), "lcl_saveEvents: invalid event attacher manager!" );
290         if ( !_rxManager.is() )
291             return;
292 
293 		// reserve the space needed
294 		_rSave.reserve( _nItemCount );
295 
296 		// copy the events
297         for (sal_Int32 i=0; i<_nItemCount; ++i)
298             _rSave.push_back(_rxManager->getScriptEvents( i ));
299 	}
300 
301 	//..........................................................................
lcl_restoreEvents(const::std::vector<Sequence<ScriptEventDescriptor>> & _rSave,const Reference<XEventAttacherManager> & _rxManager)302 	void lcl_restoreEvents( const ::std::vector< Sequence< ScriptEventDescriptor > >& _rSave,
303 		const Reference< XEventAttacherManager >& _rxManager )
304 	{
305         OSL_ENSURE( _rxManager.is(), "lcl_restoreEvents: invalid event attacher manager!" );
306         if ( !_rxManager.is() )
307             return;
308 
309 		::std::vector< Sequence< ScriptEventDescriptor > >::const_iterator aLoop = _rSave.begin();
310 		::std::vector< Sequence< ScriptEventDescriptor > >::const_iterator aEnd = _rSave.end();
311 		for ( sal_Int32 i=0; aLoop != aEnd; ++aLoop, ++i )
312 		{
313 			_rxManager->revokeScriptEvents( i );
314 			_rxManager->registerScriptEvents( i, *aLoop );
315 		}
316 	}
317 }
318 
319 //------------------------------------------------------------------------------
writeEvents(const Reference<XObjectOutputStream> & _rxOutStream)320 void SAL_CALL OInterfaceContainer::writeEvents(const Reference<XObjectOutputStream>& _rxOutStream)
321 {
322 	// We're writing a document in SO 5.2 format (or even from earlier versions)
323 	// -> convert the events from the new runtime format to the format of the 5.2 files
324 	// but before, remember the current script events set for our children
325 	::std::vector< Sequence< ScriptEventDescriptor > > aSave;
326     if ( m_xEventAttacher.is() )
327 	    lcl_saveEvents( aSave, m_xEventAttacher, m_aItems.size() );
328 
329     transformEvents( efVersionSO5x );
330 
331 	try
332 	{
333 		Reference<XMarkableStream>  xMark(_rxOutStream, UNO_QUERY);
334 		sal_Int32 nMark = xMark->createMark();
335 
336 		sal_Int32 nObjLen = 0;
337 		_rxOutStream->writeLong(nObjLen);
338 
339 		Reference<XPersistObject>  xScripts(m_xEventAttacher, UNO_QUERY);
340 		if (xScripts.is())
341 			xScripts->write(_rxOutStream);
342 
343 		// feststellen der Laenge
344 		nObjLen = xMark->offsetToMark(nMark) - 4;
345 		xMark->jumpToMark(nMark);
346 		_rxOutStream->writeLong(nObjLen);
347 		xMark->jumpToFurthest();
348 		xMark->deleteMark(nMark);
349 	}
350 	catch( const Exception& )
351 	{
352 		// restore the events
353         if ( m_xEventAttacher.is() )
354 		    lcl_restoreEvents( aSave, m_xEventAttacher );
355 		throw;
356 	}
357 
358 	// restore the events
359     if ( m_xEventAttacher.is() )
360     	lcl_restoreEvents( aSave, m_xEventAttacher );
361 }
362 
363 //------------------------------------------------------------------------------
364 struct TransformEventTo52Format : public ::std::unary_function< ScriptEventDescriptor, void >
365 {
operator ()frm::TransformEventTo52Format366 	void operator()( ScriptEventDescriptor& _rDescriptor )
367 	{
368 		if ( 0 == _rDescriptor.ScriptType.compareToAscii( "StarBasic" ) )
369 		{	// it's a starbasic macro
370 			sal_Int32 nPrefixLength = _rDescriptor.ScriptCode.indexOf( ':' );
371 			if ( 0 <= nPrefixLength )
372 			{	// the macro name does not already contain a :
373 #ifdef DBG_UTIL
374 				const ::rtl::OUString sPrefix = _rDescriptor.ScriptCode.copy( 0, nPrefixLength );
375 				DBG_ASSERT(	0 == sPrefix.compareToAscii( "document" )
376 						||	0 == sPrefix.compareToAscii( "application" ),
377 						"TransformEventTo52Format: invalid (unknown) prefix!" );
378 #endif
379 				// cut the prefix
380 				_rDescriptor.ScriptCode = _rDescriptor.ScriptCode.copy( nPrefixLength + 1 );
381 			}
382 		}
383 	}
384 };
385 
386 //------------------------------------------------------------------------------
387 struct TransformEventTo60Format : public ::std::unary_function< ScriptEventDescriptor, void >
388 {
operator ()frm::TransformEventTo60Format389 	void operator()( ScriptEventDescriptor& _rDescriptor )
390 	{
391 		if ( 0 == _rDescriptor.ScriptType.compareToAscii( "StarBasic" ) )
392 		{	// it's a starbasic macro
393 			if ( _rDescriptor.ScriptCode.indexOf( ':' ) < 0 )
394 			{	// the macro name does not already contain a :
395 				// -> default the type to "document"
396 				::rtl::OUString sNewScriptCode( RTL_CONSTASCII_USTRINGPARAM( "document:" ) );
397 				sNewScriptCode += _rDescriptor.ScriptCode;
398 				_rDescriptor.ScriptCode = sNewScriptCode;
399 			}
400 		}
401 	}
402 };
403 
404 //------------------------------------------------------------------------------
transformEvents(const EventFormat _eTargetFormat)405 void OInterfaceContainer::transformEvents( const EventFormat _eTargetFormat )
406 {
407     OSL_ENSURE( m_xEventAttacher.is(), "OInterfaceContainer::transformEvents: no event attacher manager!" );
408     if ( !m_xEventAttacher.is() )
409         return;
410 
411     try
412 	{
413 		// loop through all our children
414 		sal_Int32 nItems = m_aItems.size();
415 		Sequence< ScriptEventDescriptor > aChildEvents;
416 
417 		for (sal_Int32 i=0; i<nItems; ++i)
418 		{
419 			// get the script events for this object
420 			aChildEvents = m_xEventAttacher->getScriptEvents( i );
421 
422 			if ( aChildEvents.getLength() )
423 			{
424 				// the "iterators" for the events for this child
425 				ScriptEventDescriptor* pChildEvents		=						aChildEvents.getArray();
426 				ScriptEventDescriptor* pChildEventsEnd	=	pChildEvents	+	aChildEvents.getLength();
427 
428 				// do the transformation
429 				if ( efVersionSO6x == _eTargetFormat )
430 					::std::for_each( pChildEvents, pChildEventsEnd, TransformEventTo60Format() );
431 				else
432 					::std::for_each( pChildEvents, pChildEventsEnd, TransformEventTo52Format() );
433 
434 				// revoke the script events
435 				m_xEventAttacher->revokeScriptEvents( i );
436 				// and re-register them
437 				m_xEventAttacher->registerScriptEvents( i, aChildEvents );
438 			}
439 		}
440 	}
441 	catch( const Exception& )
442 	{
443 		DBG_UNHANDLED_EXCEPTION();
444 	}
445 }
446 
447 //------------------------------------------------------------------------------
readEvents(const Reference<XObjectInputStream> & _rxInStream)448 void SAL_CALL OInterfaceContainer::readEvents(const Reference<XObjectInputStream>& _rxInStream)
449 {
450 	::osl::MutexGuard aGuard( m_rMutex );
451 
452 	// Scripting Info lesen
453 	Reference<XMarkableStream>  xMark(_rxInStream, UNO_QUERY);
454 	sal_Int32 nObjLen = _rxInStream->readLong();
455 	if (nObjLen)
456 	{
457 		sal_Int32 nMark = xMark->createMark();
458 		Reference<XPersistObject>  xObj(m_xEventAttacher, UNO_QUERY);
459 		if (xObj.is())
460 			xObj->read(_rxInStream);
461 		xMark->jumpToMark(nMark);
462 		_rxInStream->skipBytes(nObjLen);
463 		xMark->deleteMark(nMark);
464 	}
465 
466 	// Attachement lesen
467     if ( m_xEventAttacher.is() )
468     {
469 	    OInterfaceArray::const_iterator aAttach = m_aItems.begin();
470 	    OInterfaceArray::const_iterator aAttachEnd = m_aItems.end();
471 	    for ( sal_Int32 i=0; aAttach != aAttachEnd; ++aAttach, ++i )
472 	    {
473 		    Reference< XInterface > xAsIFace( *aAttach, UNO_QUERY );	// important to normalize this ....
474 		    Reference< XPropertySet > xAsSet( xAsIFace, UNO_QUERY );
475 		    m_xEventAttacher->attach( i, xAsIFace, makeAny( xAsSet ) );
476 	    }
477     }
478 }
479 
480 //------------------------------------------------------------------------------
write(const Reference<XObjectOutputStream> & _rxOutStream)481 void SAL_CALL OInterfaceContainer::write( const Reference< XObjectOutputStream >& _rxOutStream ) throw(IOException, RuntimeException)
482 {
483 	::osl::MutexGuard aGuard( m_rMutex );
484 	sal_Int32 nLen = m_aItems.size();
485 
486 	// schreiben der laenge
487 	_rxOutStream->writeLong(nLen);
488 
489 	if (nLen)
490 	{
491 		// 1. Version
492 		_rxOutStream->writeShort(0x0001);
493 
494 		// 2. Objekte
495 		for (sal_Int32 i = 0; i < nLen; i++)
496 		{
497 			Reference<XPersistObject>  xObj(m_aItems[i], UNO_QUERY);
498 			if (xObj.is())
499 				_rxOutStream->writeObject(xObj);
500 			else
501 			{
502 				// ::com::sun::star::chaos::Error
503 			}
504 		}
505 
506 		// 3. Scripts
507 		writeEvents(_rxOutStream);
508 	}
509 }
510 
511 //------------------------------------------------------------------------------
512 namespace
513 {
lcl_createPlaceHolder(const Reference<XMultiServiceFactory> & _rxORB)514 	Reference< XPersistObject > lcl_createPlaceHolder( const Reference< XMultiServiceFactory >& _rxORB )
515 	{
516 		Reference< XPersistObject > xObject( _rxORB->createInstance( FRM_COMPONENT_HIDDENCONTROL ), UNO_QUERY );
517 		DBG_ASSERT( xObject.is(), "lcl_createPlaceHolder: could not create a substitute for the unknown object!" );
518 		if ( xObject.is() )
519 		{
520 			// set some properties describing what we did
521 			Reference< XPropertySet > xObjProps( xObject, UNO_QUERY );
522 			if ( xObject.is()  )
523 			{
524 				try
525 				{
526 					xObjProps->setPropertyValue( PROPERTY_NAME, makeAny( FRM_RES_STRING( RID_STR_CONTROL_SUBSTITUTED_NAME ) ) );
527 					xObjProps->setPropertyValue( PROPERTY_TAG, makeAny( FRM_RES_STRING( RID_STR_CONTROL_SUBSTITUTED_EPXPLAIN ) ) );
528 				}
529 				catch(Exception&)
530 				{
531 				}
532 			}
533 		}
534 		return xObject;
535 	}
536 }
537 
538 //------------------------------------------------------------------------------
read(const Reference<XObjectInputStream> & _rxInStream)539 void SAL_CALL OInterfaceContainer::read( const Reference< XObjectInputStream >& _rxInStream ) throw(IOException, RuntimeException)
540 {
541 	::osl::MutexGuard aGuard( m_rMutex );
542 
543 	// after ::read the object is expected to be in the state it was when ::write was called, so we have
544 	// to empty ourself here
545 	// FS - 71598 - 12.01.00
546 	while (getCount())
547 		removeByIndex(0);
548 
549     // Schreibt nur in Abhaengigkeit der Laenge
550 	sal_Int32 nLen = _rxInStream->readLong();
551 
552 	if (nLen)
553 	{
554 		// 1. Version
555 		sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion;
556 
557 		// 2. Objekte
558 		for (sal_Int32 i = 0; i < nLen; i++)
559 		{
560 			Reference<XPersistObject>  xObj;
561 			try
562 			{
563 				xObj = _rxInStream->readObject();
564 			}
565 			catch(WrongFormatException& e)
566 			{
567 				(void)e;    // make compiler happy
568 				// the object could not be read
569 				// create a object (so the readEvents below will assign the events to the right controls)
570 				xObj = lcl_createPlaceHolder( m_xServiceFactory );
571 				if ( !xObj.is() )
572 					// couldn't handle it
573 					throw;
574 				// 72133 - 09.02.00 - FS
575 			}
576 			catch(Exception&)
577 			{
578 				// unsere Map leeren
579 				while (!m_aItems.empty())
580 					removeElementsNoEvents(0);
581 
582 				// und die Exception nach aussen
583 				throw;
584 			}
585 
586 			if ( xObj.is() )
587 			{
588 				Reference< XPropertySet > xElement( xObj, UNO_QUERY );
589 				try
590 				{
591 					implInsert(
592 						m_aItems.size(),	// position
593 						xElement,			// element to insert
594 						sal_False,			// no event attacher manager handling
595 						NULL,				// not yet approved - let implInsert do it
596 						sal_True			// fire the event
597 					);
598 				}
599 				catch( const Exception& )
600 				{
601 					DBG_ERROR( "OInterfaceContainerHelper::read: reading succeeded, but not inserting!" );
602 					// create a placeholder
603 					xElement = xElement.query( lcl_createPlaceHolder( m_xServiceFactory ) );
604 					if ( !xElement.is() )
605 						// couldn't handle it
606 						throw;
607 					// insert the placeholder
608 					implInsert( m_aItems.size(), xElement, sal_False, NULL, sal_True );
609 				}
610 			}
611 		}
612 
613 		readEvents(_rxInStream);
614 	}
615 	else
616     {
617         try
618         {
619 		    m_xEventAttacher = ::comphelper::createEventAttacherManager( m_xServiceFactory );
620             OSL_ENSURE( m_xEventAttacher.is(), "OInterfaceContainer::read: could not create an event attacher manager!" );
621         }
622         catch( const Exception& )
623         {
624             DBG_UNHANDLED_EXCEPTION();
625         }
626     }
627 }
628 
629 // XContainer
630 //------------------------------------------------------------------------------
addContainerListener(const Reference<XContainerListener> & _rxListener)631 void SAL_CALL OInterfaceContainer::addContainerListener(const Reference<XContainerListener>& _rxListener) throw( RuntimeException )
632 {
633 	m_aContainerListeners.addInterface(_rxListener);
634 }
635 
636 //------------------------------------------------------------------------------
removeContainerListener(const Reference<XContainerListener> & _rxListener)637 void SAL_CALL OInterfaceContainer::removeContainerListener(const Reference<XContainerListener>& _rxListener) throw( RuntimeException )
638 {
639 	m_aContainerListeners.removeInterface(_rxListener);
640 }
641 
642 // XEventListener
643 //------------------------------------------------------------------------------
disposing(const EventObject & _rSource)644 void SAL_CALL OInterfaceContainer::disposing(const EventObject& _rSource) throw( RuntimeException )
645 {
646 	::osl::MutexGuard aGuard( m_rMutex );
647 
648 	Reference< XInterface > xSource( _rSource.Source, UNO_QUERY );
649 		// normalized source
650 
651 	OInterfaceArray::iterator j;
652 	for ( j = m_aItems.begin(); j != m_aItems.end(); ++j )
653 	{
654 		DBG_ASSERT( j->get() == Reference< XInterface >( *j, UNO_QUERY ).get(),
655 			"OInterfaceContainer::disposing: vector element not normalized!" );
656 
657 		if ( xSource.get() == j->get() )
658 			// found the element
659 			break;
660 	}
661 
662 	if ( m_aItems.end() != j )
663 	{
664         m_aItems.erase(j);
665 
666         // look up in, and erase from, m_aMap, too
667 		OInterfaceMap::iterator i = m_aMap.begin();
668 		while ( i != m_aMap.end() )
669 		{
670 			DBG_ASSERT( i->second.get() == Reference< XInterface >( i->second, UNO_QUERY ).get(),
671 				"OInterfaceContainer::disposing: map element not normalized!" );
672 
673 			if ( i->second.get() == xSource.get() )
674             {
675 				// found it
676                 m_aMap.erase(i);
677 				break;
678             }
679 
680 			++i;
681 
682             DBG_ASSERT( i != m_aMap.end(), "OInterfaceContainer::disposing: inconsistency: the element was in m_aItems, but not in m_aMap!" );
683 		}
684 	}
685 }
686 
687 // XPropertyChangeListener
688 //------------------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & evt)689 void OInterfaceContainer::propertyChange(const PropertyChangeEvent& evt)
690 throw (::com::sun::star::uno::RuntimeException) {
691 	if (evt.PropertyName == PROPERTY_NAME)
692 	{
693 		::osl::MutexGuard aGuard( m_rMutex );
694 		OInterfaceMap::iterator i = ::std::find(m_aMap.begin(), m_aMap.end(),
695 			::std::pair<const ::rtl::OUString, InterfaceRef >(::comphelper::getString(evt.OldValue),evt.Source));
696 		if (i != m_aMap.end())
697 		{
698 			InterfaceRef  xCorrectType((*i).second);
699 			m_aMap.erase(i);
700 			m_aMap.insert(::std::pair<const ::rtl::OUString, InterfaceRef >(::comphelper::getString(evt.NewValue),xCorrectType));
701 		}
702 	}
703 }
704 
705 // XElementAccess
706 //------------------------------------------------------------------------------
hasElements()707 sal_Bool SAL_CALL OInterfaceContainer::hasElements() throw( RuntimeException )
708 {
709 	return !m_aMap.empty();
710 }
711 
712 //------------------------------------------------------------------------------
getElementType()713 Type SAL_CALL OInterfaceContainer::getElementType() throw(RuntimeException)
714 {
715 	return m_aElementType;
716 }
717 
718 // XEnumerationAccess
719 //------------------------------------------------------------------------------
createEnumeration()720 Reference<XEnumeration> SAL_CALL OInterfaceContainer::createEnumeration() throw( RuntimeException )
721 {
722 	::osl::MutexGuard aGuard( m_rMutex );
723 	return new ::comphelper::OEnumerationByIndex(static_cast<XIndexAccess*>(this));
724 }
725 
726 // XNameAccess
727 //------------------------------------------------------------------------------
getByName(const::rtl::OUString & _rName)728 Any SAL_CALL OInterfaceContainer::getByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException)
729 {
730 	::std::pair <OInterfaceMap::iterator,
731 		  OInterfaceMap::iterator> aPair = m_aMap.equal_range(_rName);
732 
733 	if (aPair.first == aPair.second)
734 		throw NoSuchElementException();
735 
736 	return (*aPair.first).second->queryInterface( m_aElementType );
737 }
738 
739 //------------------------------------------------------------------------------
getElementNames()740 StringSequence SAL_CALL OInterfaceContainer::getElementNames() throw(RuntimeException)
741 {
742 	StringSequence aNameList(m_aItems.size());
743 	::rtl::OUString* pStringArray = aNameList.getArray();
744 
745 	for (OInterfaceMap::const_iterator i = m_aMap.begin(); i != m_aMap.end(); ++i, ++pStringArray)
746 	{
747 		*pStringArray = (*i).first;
748 	}
749 	return aNameList;
750 }
751 
752 //------------------------------------------------------------------------------
hasByName(const::rtl::OUString & _rName)753 sal_Bool SAL_CALL OInterfaceContainer::hasByName( const ::rtl::OUString& _rName ) throw(RuntimeException)
754 {
755 	::std::pair <OInterfaceMap::iterator,
756 		  OInterfaceMap::iterator> aPair = m_aMap.equal_range(_rName);
757 	return aPair.first != aPair.second;
758 }
759 
760 // XIndexAccess
761 //------------------------------------------------------------------------------
getCount()762 sal_Int32 OInterfaceContainer::getCount() throw( RuntimeException )
763 {
764 	return m_aItems.size();
765 }
766 
767 //------------------------------------------------------------------------------
getByIndex(sal_Int32 _nIndex)768 Any OInterfaceContainer::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
769 {
770 	if (_nIndex < 0 || (_nIndex >= (sal_Int32)m_aItems.size()))
771 		throw IndexOutOfBoundsException();
772 
773 	return m_aItems[_nIndex]->queryInterface( m_aElementType );
774 }
775 
776 //------------------------------------------------------------------------------
approveNewElement(const Reference<XPropertySet> & _rxObject,ElementDescription * _pElement)777 void OInterfaceContainer::approveNewElement( const Reference< XPropertySet >& _rxObject, ElementDescription* _pElement )
778 {
779 	// it has to be non-NULL
780 	if ( !_rxObject.is() )
781 		throw IllegalArgumentException(FRM_RES_STRING(RID_STR_NEED_NON_NULL_OBJECT), static_cast<XContainer*>(this), 1);
782 
783 	// it has to support our element type interface
784 	Any aCorrectType = _rxObject->queryInterface( m_aElementType );
785 	if ( !aCorrectType.hasValue() )
786 		lcl_throwIllegalArgumentException();
787 
788 	// it has to have a "Name" property
789 	if ( !hasProperty( PROPERTY_NAME, _rxObject ) )
790 		lcl_throwIllegalArgumentException();
791 
792 	// it has to be a child, and it must not have a parent already
793 	Reference< XChild > xChild( _rxObject, UNO_QUERY );
794 	if ( !xChild.is() || xChild->getParent().is() )
795 	{
796 #ifdef FS_PRIV_DEBUG
797 		::rtl::OUString sChildName, sParentName;
798 		Reference< XNamed > xNamed( xChild, UNO_QUERY );
799 		if ( xNamed.is() )
800 			sChildName = xNamed->getName();
801 		if ( xChild.is() )
802 		{
803 			xNamed = xNamed.query( xChild->getParent() );
804 			if ( xNamed.is() )
805 				sParentName = xNamed->getName();
806 		}
807 #endif
808 		lcl_throwIllegalArgumentException();
809 	}
810 
811 	// passed all tests. cache the information we have so far
812 	DBG_ASSERT( _pElement, "OInterfaceContainer::approveNewElement: invalid event descriptor!" );
813 	if ( _pElement )
814 	{
815 		_pElement->xPropertySet = _rxObject;
816 		_pElement->xChild = xChild;
817 		_pElement->aElementTypeInterface = aCorrectType;
818 		_pElement->xInterface = Reference< XInterface >( _rxObject, UNO_QUERY );	// normalized XInterface
819 	}
820 }
821 
822 //------------------------------------------------------------------------------
implInsert(sal_Int32 _nIndex,const Reference<XPropertySet> & _rxElement,sal_Bool _bEvents,ElementDescription * _pApprovalResult,sal_Bool _bFire)823 void OInterfaceContainer::implInsert(sal_Int32 _nIndex, const Reference< XPropertySet >& _rxElement,
824 	sal_Bool _bEvents, ElementDescription* _pApprovalResult, sal_Bool _bFire ) throw( IllegalArgumentException )
825 {
826     const bool bHandleEvents = _bEvents && m_xEventAttacher.is();
827 
828     // SYNCHRONIZED ----->
829 	::osl::ClearableMutexGuard aGuard( m_rMutex );
830 
831 	::std::auto_ptr< ElementDescription > aAutoDeleteMetaData;
832 	ElementDescription* pElementMetaData = _pApprovalResult;
833 	if ( !pElementMetaData )
834 	{	// not yet approved by the caller -> do ourself
835 		pElementMetaData = createElementMetaData();
836 		DBG_ASSERT( pElementMetaData, "OInterfaceContainer::implInsert: createElementMetaData returned nonsense!" );
837 
838 		// ensure that the meta data structure will be deleted later on
839 		aAutoDeleteMetaData = ::std::auto_ptr< ElementDescription >( pElementMetaData );
840 
841 		// will throw an exception if necessary
842 		approveNewElement( _rxElement, pElementMetaData );
843 	}
844 
845 
846 	// approveNewElement (no matter if called here or outside) has ensure that all relevant interfaces
847 	// exist
848 
849 	// set the name, and add as change listener for the name
850 	::rtl::OUString sName;
851 	_rxElement->getPropertyValue(PROPERTY_NAME) >>= sName;
852 	_rxElement->addPropertyChangeListener(PROPERTY_NAME, this);
853 
854 	// insert the object into our internal structures
855 	if (_nIndex > (sal_Int32)m_aItems.size()) // ermitteln des tatsaechlichen Indexs
856 	{
857 		_nIndex = m_aItems.size();
858 		m_aItems.push_back( pElementMetaData->xInterface );
859 	}
860 	else
861 		m_aItems.insert( m_aItems.begin() + _nIndex, pElementMetaData->xInterface );
862 
863 	m_aMap.insert( ::std::pair< const ::rtl::OUString, InterfaceRef >( sName, pElementMetaData->xInterface ) );
864 
865 	// announce ourself as parent to the new element
866 	pElementMetaData->xChild->setParent(static_cast<XContainer*>(this));
867 
868 	// handle the events
869 	if ( bHandleEvents )
870 	{
871 		m_xEventAttacher->insertEntry(_nIndex);
872 		m_xEventAttacher->attach( _nIndex, pElementMetaData->xInterface, makeAny( _rxElement ) );
873 	}
874 
875 	// notify derived classes
876 	implInserted( pElementMetaData );
877 
878     aGuard.clear();
879     // <----- SYNCHRONIZED
880 
881 	// insert faked VBA events?
882 	if ( bHandleEvents )
883 	{
884 	    Reference< XEventAttacherManager > xMgr ( pElementMetaData->xInterface, UNO_QUERY );
885 	    if ( xMgr.is() )
886 	    {
887 		    OInterfaceContainer* pIfcMgr = dynamic_cast< OInterfaceContainer* >( xMgr.get() );
888 		    sal_Int32 nLen = pIfcMgr->getCount();
889 		    for ( sal_Int32 i = 0; (i < nLen) && pIfcMgr ; ++i )
890 		    {
891 			    // add fake events to the control at index i
892 			    pIfcMgr->impl_addVbEvents_nolck_nothrow( i );
893 		    }
894 	    }
895 	    else
896 	    {
897 		    // add fake events to the control at index i
898 		    impl_addVbEvents_nolck_nothrow( _nIndex );
899 	    }
900     }
901 
902 	// fire the notification about the change
903 	if ( _bFire )
904 	{
905 		// notify listeners
906 		ContainerEvent aEvt;
907 		aEvt.Source   = static_cast<XContainer*>(this);
908 		aEvt.Accessor <<= _nIndex;
909 		aEvt.Element  = pElementMetaData->aElementTypeInterface;
910 
911 		aGuard.clear();
912         m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvt );
913 	}
914 }
915 
916 //------------------------------------------------------------------------------
removeElementsNoEvents(sal_Int32 nIndex)917 void OInterfaceContainer::removeElementsNoEvents(sal_Int32 nIndex)
918 {
919 	OInterfaceArray::iterator i = m_aItems.begin() + nIndex;
920 	InterfaceRef  xElement(*i);
921 
922 	OInterfaceMap::iterator j = m_aMap.begin();
923 	while (j != m_aMap.end() && (*j).second != xElement) ++j;
924 
925 	m_aItems.erase(i);
926 	m_aMap.erase(j);
927 
928 	Reference<XPropertySet>  xSet(xElement, UNO_QUERY);
929 	if (xSet.is())
930 		xSet->removePropertyChangeListener(PROPERTY_NAME, this);
931 
932 	Reference<XChild>  xChild(xElement, UNO_QUERY);
933 	if (xChild.is())
934 		xChild->setParent(InterfaceRef ());
935 }
936 
937 //------------------------------------------------------------------------------
implInserted(const ElementDescription *)938 void OInterfaceContainer::implInserted( const ElementDescription* /*_pElement*/ )
939 {
940     // not inrerested in
941 }
942 
943 //------------------------------------------------------------------------------
implRemoved(const InterfaceRef &)944 void OInterfaceContainer::implRemoved( const InterfaceRef& /*_rxObject*/ )
945 {
946     // not inrerested in
947 }
948 
949 //------------------------------------------------------------------------------
impl_replacedElement(const ContainerEvent & _rEvent,::osl::ClearableMutexGuard & _rInstanceLock)950 void OInterfaceContainer::impl_replacedElement( const ContainerEvent& _rEvent, ::osl::ClearableMutexGuard& _rInstanceLock )
951 {
952     _rInstanceLock.clear();
953     m_aContainerListeners.notifyEach( &XContainerListener::elementReplaced, _rEvent );
954 }
955 
956 // XIndexContainer
957 //------------------------------------------------------------------------------
insertByIndex(sal_Int32 _nIndex,const Any & _rElement)958 void SAL_CALL OInterfaceContainer::insertByIndex( sal_Int32 _nIndex, const Any& _rElement ) throw(IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
959 {
960 	Reference< XPropertySet > xElement;
961 	_rElement >>= xElement;
962 	implInsert( _nIndex, xElement, sal_True /* event handling */ , NULL /* not yet approved */ , sal_True /* notification */ );
963 }
964 
965 //------------------------------------------------------------------------------
implReplaceByIndex(const sal_Int32 _nIndex,const Any & _rNewElement,::osl::ClearableMutexGuard & _rClearBeforeNotify)966 void OInterfaceContainer::implReplaceByIndex( const sal_Int32 _nIndex, const Any& _rNewElement, ::osl::ClearableMutexGuard& _rClearBeforeNotify )
967 {
968 	OSL_PRECOND( ( _nIndex >= 0 ) && ( _nIndex < (sal_Int32)m_aItems.size() ), "OInterfaceContainer::implReplaceByIndex: precondition not met (index)!" );
969 
970 	// approve the new object
971 	::std::auto_ptr< ElementDescription > aElementMetaData( createElementMetaData() );
972 	DBG_ASSERT( aElementMetaData.get(), "OInterfaceContainer::implReplaceByIndex: createElementMetaData returned nonsense!" );
973 	{
974 		Reference< XPropertySet > xElementProps;
975 		_rNewElement >>= xElementProps;
976 		approveNewElement( xElementProps, aElementMetaData.get() );
977 	}
978 
979 	// get the old element
980 	InterfaceRef  xOldElement( m_aItems[ _nIndex ] );
981 	DBG_ASSERT( xOldElement.get() == Reference< XInterface >( xOldElement, UNO_QUERY ).get(),
982 		"OInterfaceContainer::implReplaceByIndex: elements should be held normalized!" );
983 
984 	// locate the old element in the map
985 	OInterfaceMap::iterator j = m_aMap.begin();
986 	while ( ( j != m_aMap.end() ) && ( j->second.get() != xOldElement.get() ) )
987 		++j;
988 
989 	// remove event knittings
990     if ( m_xEventAttacher.is() )
991     {
992     	InterfaceRef xNormalized( xOldElement, UNO_QUERY );
993 	    m_xEventAttacher->detach( _nIndex, xNormalized );
994 	    m_xEventAttacher->removeEntry( _nIndex );
995     }
996 
997 	// don't listen for property changes anymore
998 	Reference<XPropertySet>  xSet( xOldElement, UNO_QUERY );
999 	if (xSet.is())
1000 		xSet->removePropertyChangeListener(PROPERTY_NAME, this);
1001 
1002 	// give the old element a new (void) parent
1003 	Reference<XChild>  xChild(xOldElement, UNO_QUERY);
1004 	if (xChild.is())
1005 		xChild->setParent(InterfaceRef ());
1006 
1007 	// remove the old one
1008 	m_aMap.erase(j);
1009 
1010 	// examine the new element
1011 	::rtl::OUString sName;
1012 	DBG_ASSERT( aElementMetaData.get()->xPropertySet.is(), "OInterfaceContainer::implReplaceByIndex: what did approveNewElement do?" );
1013 
1014 	aElementMetaData.get()->xPropertySet->getPropertyValue(PROPERTY_NAME) >>= sName;
1015 	aElementMetaData.get()->xPropertySet->addPropertyChangeListener(PROPERTY_NAME, this);
1016 
1017 	// insert the new one
1018 	m_aMap.insert( ::std::pair<const ::rtl::OUString, InterfaceRef  >( sName, aElementMetaData.get()->xInterface ) );
1019 	m_aItems[ _nIndex ] = aElementMetaData.get()->xInterface;
1020 
1021 	aElementMetaData.get()->xChild->setParent(static_cast<XContainer*>(this));
1022 
1023     if ( m_xEventAttacher.is() )
1024     {
1025 	    m_xEventAttacher->insertEntry( _nIndex );
1026 	    m_xEventAttacher->attach( _nIndex, aElementMetaData.get()->xInterface, makeAny( aElementMetaData.get()->xPropertySet ) );
1027     }
1028 
1029 	ContainerEvent aReplaceEvent;
1030 	aReplaceEvent.Source   = static_cast< XContainer* >( this );
1031 	aReplaceEvent.Accessor <<= _nIndex;
1032 	aReplaceEvent.Element  = aElementMetaData.get()->xInterface->queryInterface( m_aElementType );
1033 	aReplaceEvent.ReplacedElement = xOldElement->queryInterface( m_aElementType );
1034 
1035 	impl_replacedElement( aReplaceEvent, _rClearBeforeNotify );
1036 }
1037 
1038 //------------------------------------------------------------------------------
implCheckIndex(const sal_Int32 _nIndex)1039 void OInterfaceContainer::implCheckIndex( const sal_Int32 _nIndex ) SAL_THROW( ( ::com::sun::star::lang::IndexOutOfBoundsException ) )
1040 {
1041 	if (_nIndex < 0 || _nIndex >= (sal_Int32)m_aItems.size())
1042 		throw IndexOutOfBoundsException();
1043 }
1044 
1045 //------------------------------------------------------------------------------
replaceByIndex(sal_Int32 _nIndex,const Any & Element)1046 void SAL_CALL OInterfaceContainer::replaceByIndex(sal_Int32 _nIndex, const Any& Element) throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
1047 {
1048 	::osl::ClearableMutexGuard aGuard( m_rMutex );
1049 	// check the index
1050 	implCheckIndex( _nIndex );
1051 	// do the replace
1052 	implReplaceByIndex( _nIndex, Element, aGuard );
1053 }
1054 
1055 //------------------------------------------------------------------------------
implRemoveByIndex(const sal_Int32 _nIndex,::osl::ClearableMutexGuard & _rClearBeforeNotify)1056 void OInterfaceContainer::implRemoveByIndex( const sal_Int32 _nIndex, ::osl::ClearableMutexGuard& _rClearBeforeNotify )
1057 {
1058 	OSL_PRECOND( ( _nIndex >= 0 ) && ( _nIndex < (sal_Int32)m_aItems.size() ), "OInterfaceContainer::implRemoveByIndex: precondition not met (index)!" );
1059 
1060 	OInterfaceArray::iterator i = m_aItems.begin() + _nIndex;
1061 	InterfaceRef  xElement(*i);
1062 
1063 	OInterfaceMap::iterator j = m_aMap.begin();
1064 	while (j != m_aMap.end() && (*j).second != xElement) ++j;
1065 
1066 	m_aItems.erase(i);
1067 	m_aMap.erase(j);
1068 
1069 	// remove event knittings
1070     if ( m_xEventAttacher.is() )
1071     {
1072     	InterfaceRef xNormalized( xElement, UNO_QUERY );
1073 	    m_xEventAttacher->detach( _nIndex, xNormalized );
1074 	    m_xEventAttacher->removeEntry( _nIndex );
1075     }
1076 
1077 	Reference<XPropertySet>  xSet(xElement, UNO_QUERY);
1078 	if (xSet.is())
1079 		xSet->removePropertyChangeListener(PROPERTY_NAME, this);
1080 
1081 	Reference<XChild>  xChild(xElement, UNO_QUERY);
1082 	if (xChild.is())
1083 		xChild->setParent(InterfaceRef ());
1084 
1085 	// notify derived classes
1086 	implRemoved(xElement);
1087 
1088 	// notify listeners
1089 	ContainerEvent aEvt;
1090 	aEvt.Source     = static_cast<XContainer*>(this);
1091 	aEvt.Element    = xElement->queryInterface( m_aElementType );
1092 	aEvt.Accessor   <<= _nIndex;
1093 
1094 	_rClearBeforeNotify.clear();
1095     m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvt );
1096 }
1097 
1098 //------------------------------------------------------------------------------
removeByIndex(sal_Int32 _nIndex)1099 void SAL_CALL OInterfaceContainer::removeByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
1100 {
1101 	::osl::ClearableMutexGuard aGuard( m_rMutex );
1102 	// check the index
1103 	implCheckIndex( _nIndex );
1104 	// do the removal
1105 	implRemoveByIndex( _nIndex, aGuard );
1106 }
1107 
1108 //------------------------------------------------------------------------
createElementMetaData()1109 ElementDescription* OInterfaceContainer::createElementMetaData( )
1110 {
1111 	return new ElementDescription;
1112 }
1113 
1114 //------------------------------------------------------------------------
insertByName(const::rtl::OUString & _rName,const Any & _rElement)1115 void SAL_CALL OInterfaceContainer::insertByName(const ::rtl::OUString& _rName, const Any& _rElement) throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException )
1116 {
1117 	Reference< XPropertySet > xElementProps;
1118 
1119 	::std::auto_ptr< ElementDescription > aElementMetaData( createElementMetaData() );
1120 	DBG_ASSERT( aElementMetaData.get(), "OInterfaceContainer::insertByName: createElementMetaData returned nonsense!" );
1121 
1122 	// ensure the correct name of the element
1123 	try
1124 	{
1125 		_rElement >>= xElementProps;
1126 		approveNewElement( xElementProps, aElementMetaData.get() );
1127 
1128 		xElementProps->setPropertyValue( PROPERTY_NAME, makeAny( _rName ) );
1129 	}
1130 	catch( const IllegalArgumentException& )
1131 	{
1132 		throw;	// allowed to leave
1133 	}
1134 	catch( const ElementExistException& )
1135 	{
1136 		throw;	// allowed to leave
1137 	}
1138 	catch( const Exception& )
1139 	{
1140 		DBG_ERROR( "OInterfaceContainer::insertByName: caught an exception!" );
1141 	}
1142 	implInsert( m_aItems.size(), xElementProps, sal_True, aElementMetaData.get(), sal_True );
1143 }
1144 
1145 //------------------------------------------------------------------------
replaceByName(const::rtl::OUString & Name,const Any & Element)1146 void SAL_CALL OInterfaceContainer::replaceByName(const ::rtl::OUString& Name, const Any& Element) throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException )
1147 {
1148 	::osl::ClearableMutexGuard aGuard( m_rMutex );
1149 	::std::pair <OInterfaceMap::iterator,
1150 		  OInterfaceMap::iterator> aPair = m_aMap.equal_range(Name);
1151 	if (aPair.first == aPair.second)
1152 		throw NoSuchElementException();
1153 
1154 	if (Element.getValueType().getTypeClass() != TypeClass_INTERFACE)
1155 		lcl_throwIllegalArgumentException();
1156 
1157 	Reference<XPropertySet> xSet;
1158 	Element >>= xSet;
1159 	if (xSet.is())
1160 	{
1161 		if (!hasProperty(PROPERTY_NAME, xSet))
1162 			lcl_throwIllegalArgumentException();
1163 
1164 		xSet->setPropertyValue(PROPERTY_NAME, makeAny(Name));
1165 	}
1166 
1167 	// determine the element pos
1168 	sal_Int32 nPos = ::std::find(m_aItems.begin(), m_aItems.end(), (*aPair.first).second) - m_aItems.begin();
1169 
1170 	implReplaceByIndex( nPos, Element, aGuard );
1171 }
1172 
1173 //------------------------------------------------------------------------
removeByName(const::rtl::OUString & Name)1174 void SAL_CALL OInterfaceContainer::removeByName(const ::rtl::OUString& Name) throw( NoSuchElementException, WrappedTargetException, RuntimeException )
1175 {
1176 	::osl::MutexGuard aGuard( m_rMutex );
1177 	::std::pair <OInterfaceMap::iterator,
1178 		  OInterfaceMap::iterator> aPair = m_aMap.equal_range(Name);
1179 	if (aPair.first == aPair.second)
1180 		throw NoSuchElementException();
1181 
1182 	sal_Int32 nPos = ::std::find(m_aItems.begin(), m_aItems.end(), (*aPair.first).second) - m_aItems.begin();
1183 	removeByIndex(nPos);
1184 }
1185 
1186 
1187 // XEventAttacherManager
1188 //------------------------------------------------------------------------
registerScriptEvent(sal_Int32 nIndex,const ScriptEventDescriptor & aScriptEvent)1189 void SAL_CALL OInterfaceContainer::registerScriptEvent( sal_Int32 nIndex, const ScriptEventDescriptor& aScriptEvent ) throw(IllegalArgumentException, RuntimeException)
1190 {
1191 	::osl::ClearableMutexGuard aGuard( m_rMutex );
1192     if ( m_xEventAttacher.is() )
1193     {
1194 	    m_xEventAttacher->registerScriptEvent( nIndex, aScriptEvent );
1195         aGuard.clear();
1196         impl_addVbEvents_nolck_nothrow( nIndex ); // add fake vba events
1197     }
1198 }
1199 
1200 //------------------------------------------------------------------------
registerScriptEvents(sal_Int32 nIndex,const Sequence<ScriptEventDescriptor> & aScriptEvents)1201 void SAL_CALL OInterfaceContainer::registerScriptEvents( sal_Int32 nIndex, const Sequence< ScriptEventDescriptor >& aScriptEvents ) throw(IllegalArgumentException, RuntimeException)
1202 {
1203 	::osl::ClearableMutexGuard aGuard( m_rMutex );
1204     if ( m_xEventAttacher.is() )
1205     {
1206     	m_xEventAttacher->registerScriptEvents( nIndex, aScriptEvents );
1207         aGuard.clear();
1208         impl_addVbEvents_nolck_nothrow( nIndex ); // add fake vba events
1209     }
1210 }
1211 
1212 //------------------------------------------------------------------------
revokeScriptEvent(sal_Int32 nIndex,const::rtl::OUString & aListenerType,const::rtl::OUString & aEventMethod,const::rtl::OUString & aRemoveListenerParam)1213 void SAL_CALL OInterfaceContainer::revokeScriptEvent( sal_Int32 nIndex, const ::rtl::OUString& aListenerType, const ::rtl::OUString& aEventMethod, const ::rtl::OUString& aRemoveListenerParam ) throw(IllegalArgumentException, RuntimeException)
1214 {
1215     if ( m_xEventAttacher.is() )
1216     	m_xEventAttacher->revokeScriptEvent( nIndex, aListenerType, aEventMethod, aRemoveListenerParam );
1217 }
1218 
1219 //------------------------------------------------------------------------
revokeScriptEvents(sal_Int32 nIndex)1220 void SAL_CALL OInterfaceContainer::revokeScriptEvents( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException)
1221 {
1222     if ( m_xEventAttacher.is() )
1223         m_xEventAttacher->revokeScriptEvents( nIndex );
1224 }
1225 
1226 //------------------------------------------------------------------------
insertEntry(sal_Int32 nIndex)1227 void SAL_CALL OInterfaceContainer::insertEntry( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException)
1228 {
1229     if ( m_xEventAttacher.is() )
1230     	m_xEventAttacher->insertEntry( nIndex );
1231 }
1232 
1233 //------------------------------------------------------------------------
removeEntry(sal_Int32 nIndex)1234 void SAL_CALL OInterfaceContainer::removeEntry( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException)
1235 {
1236     if ( m_xEventAttacher.is() )
1237 	    m_xEventAttacher->removeEntry( nIndex );
1238 }
1239 
1240 //------------------------------------------------------------------------
getScriptEvents(sal_Int32 nIndex)1241 Sequence< ScriptEventDescriptor > SAL_CALL OInterfaceContainer::getScriptEvents( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException)
1242 {
1243     Sequence< ScriptEventDescriptor > aReturn;
1244     if ( m_xEventAttacher.is() )
1245     {
1246 	    aReturn = m_xEventAttacher->getScriptEvents( nIndex );
1247             if ( lcl_hasVbaEvents( aReturn ) )
1248             {
1249                 aReturn = lcl_stripVbaEvents( aReturn );
1250             }
1251     }
1252     return aReturn;
1253 }
1254 
1255 //------------------------------------------------------------------------
attach(sal_Int32 nIndex,const Reference<XInterface> & xObject,const Any & aHelper)1256 void SAL_CALL OInterfaceContainer::attach( sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any& aHelper ) throw(IllegalArgumentException, ServiceNotRegisteredException, RuntimeException)
1257 {
1258     if ( m_xEventAttacher.is() )
1259     	m_xEventAttacher->attach( nIndex, xObject, aHelper );
1260 }
1261 
1262 //------------------------------------------------------------------------
detach(sal_Int32 nIndex,const Reference<XInterface> & xObject)1263 void SAL_CALL OInterfaceContainer::detach( sal_Int32 nIndex, const Reference< XInterface >& xObject ) throw(IllegalArgumentException, RuntimeException)
1264 {
1265     if ( m_xEventAttacher.is() )
1266 	    m_xEventAttacher->detach( nIndex, xObject );
1267 }
1268 
1269 //------------------------------------------------------------------------
addScriptListener(const Reference<XScriptListener> & xListener)1270 void SAL_CALL OInterfaceContainer::addScriptListener( const Reference< XScriptListener >& xListener ) throw(IllegalArgumentException, RuntimeException)
1271 {
1272     if ( m_xEventAttacher.is() )
1273 	    m_xEventAttacher->addScriptListener( xListener );
1274 }
1275 
1276 //------------------------------------------------------------------------
removeScriptListener(const Reference<XScriptListener> & xListener)1277 void SAL_CALL OInterfaceContainer::removeScriptListener( const Reference< XScriptListener >& xListener ) throw(IllegalArgumentException, RuntimeException)
1278 {
1279     if ( m_xEventAttacher.is() )
1280 	    m_xEventAttacher->removeScriptListener( xListener );
1281 }
1282 
1283 //==================================================================
1284 //= OFormComponents
1285 //==================================================================
1286 //------------------------------------------------------------------------------
queryAggregation(const Type & _rType)1287 Any SAL_CALL OFormComponents::queryAggregation(const Type& _rType) throw(RuntimeException)
1288 {
1289 	Any aReturn = OFormComponents_BASE::queryInterface(_rType);
1290 	if (!aReturn.hasValue())
1291 	{
1292 		aReturn = OInterfaceContainer::queryInterface(_rType);
1293 
1294 		if (!aReturn.hasValue())
1295 			aReturn = FormComponentsBase::queryAggregation(_rType);
1296 	}
1297 
1298 	return aReturn;
1299 }
1300 
1301 //------------------------------------------------------------------
getTypes()1302 Sequence<Type> SAL_CALL OFormComponents::getTypes() throw(RuntimeException)
1303 {
1304 	return ::comphelper::concatSequences(OInterfaceContainer::getTypes(), FormComponentsBase::getTypes(), OFormComponents_BASE::getTypes());
1305 }
1306 
1307 //------------------------------------------------------------------------------
OFormComponents(const Reference<XMultiServiceFactory> & _rxFactory)1308 OFormComponents::OFormComponents(const Reference<XMultiServiceFactory>& _rxFactory)
1309     :FormComponentsBase( m_aMutex )
1310     ,OInterfaceContainer( _rxFactory, m_aMutex, XFormComponent::static_type() )
1311     ,OFormComponents_BASE()
1312 {
1313 }
1314 
1315 //------------------------------------------------------------------------------
OFormComponents(const OFormComponents & _cloneSource)1316 OFormComponents::OFormComponents( const OFormComponents& _cloneSource )
1317     :FormComponentsBase( m_aMutex )
1318     ,OInterfaceContainer( m_aMutex, _cloneSource )
1319     ,OFormComponents_BASE()
1320 {
1321 }
1322 
1323 //------------------------------------------------------------------------------
~OFormComponents()1324 OFormComponents::~OFormComponents()
1325 {
1326 	if (!FormComponentsBase::rBHelper.bDisposed)
1327 	{
1328 		acquire();
1329 		dispose();
1330 	}
1331 }
1332 
1333 // OComponentHelper
1334 //------------------------------------------------------------------------------
disposing()1335 void OFormComponents::disposing()
1336 {
1337 	OInterfaceContainer::disposing();
1338 	FormComponentsBase::disposing();
1339 	m_xParent = NULL;
1340 }
1341 
1342 //XChild
1343 //------------------------------------------------------------------------------
setParent(const InterfaceRef & Parent)1344 void OFormComponents::setParent(const InterfaceRef& Parent) throw( NoSupportException, RuntimeException )
1345 {
1346 	::osl::MutexGuard aGuard( m_aMutex );
1347 	m_xParent = Parent;
1348 }
1349 
1350 //------------------------------------------------------------------------------
getParent()1351 InterfaceRef OFormComponents::getParent() throw( RuntimeException )
1352 {
1353 	return m_xParent;
1354 }
1355 
1356 //.........................................................................
1357 }	// namespace frm
1358 //.........................................................................
1359 
1360