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_comphelper.hxx"
26 
27 #include <deque>
28 
29 #if defined( OS2 ) || defined( UNX )
30 #include <wchar.h>
31 #endif
32 #include <osl/mutex.hxx>
33 #ifndef _VOS_DIAGNOSE_HXX_
34 #include <vos/diagnose.hxx>
35 #endif
36 #include <vos/macros.hxx>
37 #include <comphelper/eventattachermgr.hxx>
38 #include <com/sun/star/beans/XIntrospection.hpp>
39 #include <com/sun/star/io/XObjectInputStream.hpp>
40 #include <com/sun/star/io/XPersistObject.hpp>
41 #include <com/sun/star/io/XObjectOutputStream.hpp>
42 #include <com/sun/star/io/XMarkableStream.hpp>
43 #include <com/sun/star/lang/XInitialization.hpp>
44 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45 #include <com/sun/star/reflection/XIdlClass.hpp>
46 #include <com/sun/star/reflection/XIdlReflection.hpp>
47 #include <com/sun/star/reflection/XIdlMethod.hpp>
48 #include <com/sun/star/script/XTypeConverter.hpp>
49 #include <com/sun/star/script/XEngineListener.hpp>
50 #include <com/sun/star/script/XEventAttacher.hpp>
51 #include <com/sun/star/script/XEventAttacherManager.hpp>
52 #include <com/sun/star/script/XScriptListener.hpp>
53 #include <cppuhelper/weak.hxx>
54 #include <cppuhelper/interfacecontainer.hxx>
55 #include <cppuhelper/implbase1.hxx>
56 #include <cppuhelper/implbase2.hxx>
57 
58 using namespace com::sun::star::uno;
59 using namespace com::sun::star::io;
60 using namespace com::sun::star::lang;
61 using namespace com::sun::star::beans;
62 using namespace com::sun::star::script;
63 using namespace com::sun::star::reflection;
64 using namespace cppu;
65 using namespace osl;
66 using namespace rtl;
67 
68 namespace comphelper
69 {
70 
71 //-----------------------------------------------------------------------------
72 struct AttachedObject_Impl
73 {
74 	Reference< XInterface >					xTarget;
75 	Sequence< Reference< XEventListener > > aAttachedListenerSeq;
76 	Any										aHelper;
77 
78 	bool operator<( const AttachedObject_Impl & ) const;
79 	bool operator==( const AttachedObject_Impl & ) const;
80 };
81 
82 struct AttacherIndex_Impl
83 {
84 #ifdef DEQUE_OK
85 	::std::deque< ScriptEventDescriptor > aEventList;
86 #else
87 	Sequence< ScriptEventDescriptor > aEventList;
88 #endif
89 	::std::deque< AttachedObject_Impl > aObjList;
90 
91 	bool operator<( const AttacherIndex_Impl & ) const;
92 	bool operator==( const AttacherIndex_Impl & ) const;
93 };
94 
95 #if 0
96 bool AttachedObject_Impl::operator<( const AttachedObject_Impl & r ) const
97 {
98 	VOS_ENSHURE( FALSE, "not implemented" );
99 	return FALSE;
100 	return this < &r;
101 }
102 
103 bool AttachedObject_Impl::operator==( const AttachedObject_Impl & r ) const
104 {
105 	VOS_ENSHURE( FALSE, "not implemented" );
106 	return this == &r;
107 }
108 
109 bool AttacherIndex_Impl::operator<( const AttacherIndex_Impl & r ) const
110 {
111 	VOS_ENSHURE( FALSE, "not implemented" );
112 	return this < &r;
113 }
114 bool AttacherIndex_Impl::operator==( const AttacherIndex_Impl & r ) const
115 {
116 	VOS_ENSHURE( FALSE, "not implemented" );
117 	return this == &r;
118 }
119 #endif
120 
121 //-----------------------------------------------------------------------------
122 class ImplEventAttacherManager
123 	: public WeakImplHelper2< XEventAttacherManager, XPersistObject >
124 {
125 	friend class AttacherAllListener_Impl;
126 	::std::deque< AttacherIndex_Impl >	aIndex;
127 	Mutex aLock;
128 	// Container fuer die ScriptListener
129 	OInterfaceContainerHelper			aScriptListeners;
130 	// EventAttacher-Instanz
131 	Reference< XEventAttacher >			xAttacher;
132 	Reference< XMultiServiceFactory > 	mxSMgr;
133 	Reference< XIdlReflection > 		mxCoreReflection;
134 	Reference< XIntrospection > 		mxIntrospection;
135 	Reference< XTypeConverter > 		xConverter;
136 	sal_Int16							nVersion;
137 public:
138 	ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
139 							  const Reference< XMultiServiceFactory > rSMgr );
140 	~ImplEventAttacherManager();
141 
142 	// Methoden von XEventAttacherManager
143 	virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent)
144 		throw( IllegalArgumentException, RuntimeException );
145 	virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents)
146 		throw( IllegalArgumentException, RuntimeException );
147 	virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam)
148 		throw( IllegalArgumentException, RuntimeException );
149 	virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index)
150 		throw( IllegalArgumentException, RuntimeException );
151 	virtual void SAL_CALL insertEntry(sal_Int32 Index)
152 		throw( IllegalArgumentException, RuntimeException );
153 	virtual void SAL_CALL removeEntry(sal_Int32 Index)
154 		throw( IllegalArgumentException, RuntimeException );
155 	virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index)
156 		throw( IllegalArgumentException, RuntimeException );
157 	virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper)
158 		throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException );
159 	virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
160 		throw( IllegalArgumentException, RuntimeException );
161 	virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener)
162 		throw( IllegalArgumentException, RuntimeException );
163 	virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener)
164 		throw( IllegalArgumentException, RuntimeException );
165 
166 	// Methoden von XPersistObject
167 	virtual OUString SAL_CALL getServiceName(void) throw( RuntimeException );
168 	virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream) throw( IOException, RuntimeException );
169 	virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) throw( IOException, RuntimeException );
170 
171 private:
172 	Reference< XIdlReflection >	getReflection() throw( Exception );
173 
174 	/** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
175 	@param _nIndex
176 		the index to check
177 	@return
178 		the iterator pointing to the position indicated by the index
179 	*/
180 	::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) );
181 };
182 
183 //========================================================================
184 //========================================================================
185 //========================================================================
186 
187 // Implementation eines EventAttacher-bezogenen AllListeners, der
188 // nur einzelne Events an einen allgemeinen AllListener weiterleitet
189 class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener >
190 {
191 	ImplEventAttacherManager*			mpManager;
192 	Reference< XEventAttacherManager >	xManager;
193 	OUString							aScriptType;
194 	OUString							aScriptCode;
195 	sal_Int16							nVersion;
196 
197 	void convertToEventReturn( Any & rRet, const Type & rRetType )
198 		throw( CannotConvertException );
199 public:
200 	AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_,
201 								const OUString & rScriptCode_ );
202 
203 	// Methoden von XAllListener
204 	virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException );
205 	virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException );
206 
207 	// Methoden von XEventListener
208 	virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
209 };
210 
211 //========================================================================
AttacherAllListener_Impl(ImplEventAttacherManager * pManager_,const OUString & rScriptType_,const OUString & rScriptCode_)212 AttacherAllListener_Impl::AttacherAllListener_Impl
213 (
214 	ImplEventAttacherManager*	pManager_,
215 	const OUString &			rScriptType_,
216 	const OUString &			rScriptCode_
217 )
218 	: mpManager( pManager_ )
219 	, xManager( pManager_ )
220 	, aScriptType( rScriptType_ )
221 	, aScriptCode( rScriptCode_ )
222 	, nVersion( 2 )
223 {
224 }
225 
226 
227 //========================================================================
228 // Methoden von XAllListener
firing(const AllEventObject & Event)229 void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
230 	throw( RuntimeException )
231 {
232 	ScriptEvent aScriptEvent;
233 	aScriptEvent.Source			= (OWeakObject *)mpManager; // get correct XInterface
234 	aScriptEvent.ListenerType	= Event.ListenerType;
235 	aScriptEvent.MethodName		= Event.MethodName;
236 	aScriptEvent.Arguments		= Event.Arguments;
237 	aScriptEvent.Helper			= Event.Helper;
238 	aScriptEvent.ScriptType		= aScriptType;
239 	aScriptEvent.ScriptCode		= aScriptCode;
240 
241 	// ueber alle Listener iterieren und Events senden
242 	OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
243 	while( aIt.hasMoreElements() )
244 		((XScriptListener *)aIt.next())->firing( aScriptEvent );
245 }
246 
247 //========================================================================
248 // Convert to the standard event return
convertToEventReturn(Any & rRet,const Type & rRetType)249 void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
250 	throw( CannotConvertException )
251 {
252 	// no return value? Set to the specified values
253 	if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
254 	{
255 		switch( rRetType.getTypeClass() )
256 		{
257 			case TypeClass_INTERFACE:
258 				{
259 				rRet <<= Reference< XInterface >();
260 				}
261 				break;
262 
263 			case TypeClass_BOOLEAN:
264 				rRet <<= sal_True;
265 				break;
266 
267 			case TypeClass_STRING:
268 				rRet <<= OUString();
269 				break;
270 
271 			case TypeClass_FLOAT:			rRet <<= float(0);			break;
272 			case TypeClass_DOUBLE:			rRet <<= double(0.0);		break;
273 			case TypeClass_BYTE:			rRet <<= sal_uInt8(0);		break;
274 			case TypeClass_SHORT:			rRet <<= sal_Int16( 0 );	break;
275 			case TypeClass_LONG:			rRet <<= sal_Int32( 0 );	break;
276 			case TypeClass_UNSIGNED_SHORT:	rRet <<= sal_uInt16( 0 );	break;
277 			case TypeClass_UNSIGNED_LONG:	rRet <<= sal_uInt32( 0 );	break;
278 
279 			default:
280 				OSL_ASSERT(false);
281 				break;
282 		}
283 	}
284 	else if( !rRet.getValueType().equals( rRetType ) )
285 	{
286 		if( mpManager->xConverter.is() )
287 			rRet = mpManager->xConverter->convertTo( rRet, rRetType );
288 		else
289 			throw CannotConvertException();
290 	}
291 }
292 
293 //========================================================================
294 // Methoden von XAllListener
approveFiring(const AllEventObject & Event)295 Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event )
296 	throw( InvocationTargetException, RuntimeException )
297 {
298 	ScriptEvent aScriptEvent;
299 	aScriptEvent.Source			= (OWeakObject *)mpManager; // get correct XInterface
300 	aScriptEvent.ListenerType	= Event.ListenerType;
301 	aScriptEvent.MethodName		= Event.MethodName;
302 	aScriptEvent.Arguments		= Event.Arguments;
303 	aScriptEvent.Helper			= Event.Helper;
304 	aScriptEvent.ScriptType		= aScriptType;
305 	aScriptEvent.ScriptCode		= aScriptCode;
306 
307 	Any aRet;
308 	// ueber alle Listener iterieren und Events senden
309 	OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
310 	while( aIt.hasMoreElements() )
311 	{
312 		aRet = ((XScriptListener *)aIt.next())->approveFiring( aScriptEvent );
313 		try
314 		{
315 			Reference< XIdlClass > xListenerType = mpManager->getReflection()->
316 						forName( Event.ListenerType.getTypeName() );
317 			Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
318 			if( xMeth.is() )
319 			{
320 				Reference< XIdlClass > xRetType = xMeth->getReturnType();
321 				Type aRetType(xRetType->getTypeClass(), xRetType->getName());
322 				convertToEventReturn( aRet, aRetType );
323 			}
324 
325 			switch( aRet.getValueType().getTypeClass() )
326 			{
327 				case TypeClass_INTERFACE:
328 					{
329 					// Interface not null, return
330 					Reference< XInterface > x;
331 					aRet >>= x;
332 					if( x.is() )
333 						return aRet;
334 					}
335 					break;
336 
337 				case TypeClass_BOOLEAN:
338 					// FALSE -> Return
339 					if( !(*(sal_Bool*)aRet.getValue()) )
340 						return aRet;
341 					break;
342 
343 				case TypeClass_STRING:
344 					// none empty string -> return
345 					if( ((OUString*)aRet.getValue())->isEmpty() == false )
346 						return aRet;
347 					break;
348 
349 					// none zero number -> return
350 				case TypeClass_FLOAT:			if( *((float*)aRet.getValue()) )		return aRet; break;
351 				case TypeClass_DOUBLE:			if( *((double*)aRet.getValue()) )		return aRet; break;
352 				case TypeClass_BYTE:			if( *((sal_uInt8*)aRet.getValue()) )	return aRet; break;
353 				case TypeClass_SHORT:			if( *((sal_Int16*)aRet.getValue()) )	return aRet; break;
354 				case TypeClass_LONG:			if( *((sal_Int32*)aRet.getValue()) )	return aRet; break;
355 				case TypeClass_UNSIGNED_SHORT:	if( *((sal_uInt16*)aRet.getValue()) )	return aRet; break;
356 				case TypeClass_UNSIGNED_LONG:	if( *((sal_uInt32*)aRet.getValue()) )	return aRet; break;
357 
358 				default:
359 					OSL_ASSERT(false);
360 					break;
361 			}
362 		}
363 		catch( CannotConvertException& )
364 		{
365 			// silent ignore conversions errors from a script call
366 			Reference< XIdlClass > xListenerType = mpManager->getReflection()->
367 						forName( Event.ListenerType.getTypeName() );
368 			Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
369 			if( xMeth.is() )
370 			{
371 				Reference< XIdlClass > xRetType = xMeth->getReturnType();
372 				Type aRetType(xRetType->getTypeClass(), xRetType->getName());
373 				aRet.clear();
374 				convertToEventReturn( aRet, aRetType );
375 			}
376 		}
377 	}
378 	return aRet;
379 }
380 
381 //========================================================================
382 // Methoden von XEventListener
disposing(const EventObject &)383 void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
384 	throw( RuntimeException )
385 {
386 	// It is up to the container to release the object
387 }
388 
389 
390 //========================================================================
391 //========================================================================
392 //========================================================================
393 
394 // Create-Methode fuer EventAttacherManager
createEventAttacherManager(const Reference<XIntrospection> & rIntrospection,const Reference<XMultiServiceFactory> & rSMgr)395 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
396 															   const Reference< XMultiServiceFactory > & rSMgr )
397 	throw( Exception )
398 {
399 	return new ImplEventAttacherManager( rIntrospection, rSMgr );
400 }
401 
402 // Create-Methode fuer EventAttacherManager
createEventAttacherManager(const Reference<XMultiServiceFactory> & rSMgr)403 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XMultiServiceFactory > & rSMgr )
404 	throw( Exception )
405 {
406 	if ( rSMgr.is() )
407 	{
408 		Reference< XInterface > xIFace( rSMgr->createInstance( OUString::createFromAscii("com.sun.star.beans.Introspection") ) );
409 		if ( xIFace.is() )
410 		{
411 			Reference< XIntrospection > xIntrospection( xIFace, UNO_QUERY);
412 			return new ImplEventAttacherManager( xIntrospection, rSMgr );
413 		}
414 	}
415 
416 	return Reference< XEventAttacherManager >();
417 }
418 
419 //-----------------------------------------------------------------------------
ImplEventAttacherManager(const Reference<XIntrospection> & rIntrospection,const Reference<XMultiServiceFactory> rSMgr)420 ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
421 													const Reference< XMultiServiceFactory > rSMgr )
422 	: aScriptListeners( aLock )
423 	, mxSMgr( rSMgr )
424 	, mxIntrospection( rIntrospection )
425 {
426 	if ( rSMgr.is() )
427 	{
428 		Reference< XInterface > xIFace( rSMgr->createInstance( OUString::createFromAscii("com.sun.star.script.EventAttacher") ) );
429 		if ( xIFace.is() )
430 		{
431 			xAttacher = Reference< XEventAttacher >::query( xIFace );
432 		}
433 		xIFace = rSMgr->createInstance( OUString::createFromAscii("com.sun.star.script.Converter") );
434 		if ( xIFace.is() )
435 		{
436 			xConverter = Reference< XTypeConverter >::query( xIFace );
437 		}
438 	}
439 
440 	Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
441 	if( xInit.is() )
442 	{
443 		Sequence< Any > Arguments( 1 );
444 		Arguments[0] <<= rIntrospection;
445 		xInit->initialize( Arguments );
446 	}
447 }
448 
449 //-----------------------------------------------------------------------------
~ImplEventAttacherManager()450 ImplEventAttacherManager::~ImplEventAttacherManager()
451 {
452 }
453 
getReflection()454 Reference< XIdlReflection > ImplEventAttacherManager::getReflection() throw( Exception )
455 {
456 	Guard< Mutex > aGuard( aLock );
457 	// Haben wir den Service schon? Sonst anlegen
458 	if( !mxCoreReflection.is() )
459 	{
460 		Reference< XInterface > xIFace( mxSMgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection") ) );
461 		mxCoreReflection = Reference< XIdlReflection >( xIFace, UNO_QUERY);
462 	}
463 	return mxCoreReflection;
464 }
465 
466 
467 //-----------------------------------------------------------------------------
implCheckIndex(sal_Int32 _nIndex)468 ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) )
469 {
470 	if (_nIndex < 0)
471 		throw IllegalArgumentException();
472 
473 	::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
474 	for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
475 		;
476 
477 	if( aIt == aIndex.end() )
478 		throw IllegalArgumentException();
479 
480 	return aIt;
481 }
482 
483 //-----------------------------------------------------------------------------
detachAll_Impl(ImplEventAttacherManager * pMgr,sal_Int32 nIdx,::std::deque<AttachedObject_Impl> & rList)484 void detachAll_Impl
485 (
486 	ImplEventAttacherManager * pMgr,
487 	sal_Int32 nIdx,
488 	::std::deque< AttachedObject_Impl > & rList
489 )
490 {
491 	::std::deque< AttachedObject_Impl >::iterator aObjIt =  rList.begin();
492 	::std::deque< AttachedObject_Impl >::iterator aObjEnd = rList.end();
493 	while( aObjIt != aObjEnd )
494 	{
495 		pMgr->detach( nIdx, (*aObjIt).xTarget );
496 		aObjIt++;
497 	}
498 }
499 
500 //-----------------------------------------------------------------------------
attachAll_Impl(ImplEventAttacherManager * pMgr,sal_Int32 nIdx,::std::deque<AttachedObject_Impl> & rList)501 void attachAll_Impl
502 (
503 	ImplEventAttacherManager * pMgr,
504 	sal_Int32 nIdx,
505 	::std::deque< AttachedObject_Impl > & rList
506 )
507 {
508 	::std::deque< AttachedObject_Impl >::iterator aObjIt =  rList.begin();
509 	::std::deque< AttachedObject_Impl >::iterator aObjEnd = rList.end();
510 	while( aObjIt != aObjEnd )
511 	{
512 		pMgr->attach( nIdx, (*aObjIt).xTarget, (*aObjIt).aHelper );
513 		aObjIt++;
514 	}
515 }
516 
517 //-----------------------------------------------------------------------------
518 //*** Methoden von XEventAttacherManager ***
registerScriptEvent(sal_Int32 nIndex,const ScriptEventDescriptor & ScriptEvent)519 void SAL_CALL ImplEventAttacherManager::registerScriptEvent
520 (
521 	sal_Int32 nIndex,
522 	const ScriptEventDescriptor& ScriptEvent
523 )
524 	throw( IllegalArgumentException, RuntimeException )
525 {
526 	Guard< Mutex > aGuard( aLock );
527 
528 	// Index pruefen und Array anpassen
529 	::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
530 
531 	::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
532 
533 	ScriptEventDescriptor aEvt = ScriptEvent;
534 	const sal_Unicode* pLastDot = aEvt.ListenerType.getStr();
535 	pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
536 	if( pLastDot )
537 		aEvt.ListenerType = pLastDot +1;
538 #ifdef DEQUE_OK
539 	(*aIt).aEventList.push_back( aEvt );
540 #else
541 	(*aIt).aEventList.realloc( (*aIt).aEventList.getLength() +1 );
542 	(*aIt).aEventList.getArray()[(*aIt).aEventList.getLength() -1] = aEvt;
543 #endif
544 
545 	// register new new Event
546 	::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.begin();
547 	::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end();
548 	while( aObjIt != aObjEnd )
549 	{
550 		// resize
551 		sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
552 		(*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
553 		Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
554 
555 		Reference< XAllListener > xAll =
556 			new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
557 		try
558 		{
559 		pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
560 						(*aObjIt).aHelper, ScriptEvent.ListenerType,
561 						ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
562 		}
563 		catch( Exception& )
564 		{
565 		}
566 
567 		aObjIt++;
568 	}
569 }
570 
571 //-----------------------------------------------------------------------------
registerScriptEvents(sal_Int32 nIndex,const Sequence<ScriptEventDescriptor> & ScriptEvents)572 void SAL_CALL ImplEventAttacherManager::registerScriptEvents
573 (
574 	sal_Int32 nIndex,
575 	const Sequence< ScriptEventDescriptor >& ScriptEvents
576 )
577 	throw( IllegalArgumentException, RuntimeException )
578 {
579 	Guard< Mutex > aGuard( aLock );
580 
581 	// Index pruefen und Array anpassen
582 	::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
583 
584 	::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
585 	detachAll_Impl( this, nIndex, aList );
586 
587 	const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
588 	sal_Int32 nLen = ScriptEvents.getLength();
589 	for( sal_Int32 i = 0 ; i < nLen ; i++ )
590 		registerScriptEvent( nIndex, pArray[ i ] );
591 
592 	attachAll_Impl( this, nIndex, aList );
593 }
594 
595 //-----------------------------------------------------------------------------
revokeScriptEvent(sal_Int32 nIndex,const OUString & ListenerType,const OUString & EventMethod,const OUString & ToRemoveListenerParam)596 void SAL_CALL ImplEventAttacherManager::revokeScriptEvent
597 (
598 	sal_Int32 nIndex,
599 	const OUString& ListenerType,
600 	const OUString& EventMethod,
601 	const OUString& ToRemoveListenerParam
602 )
603 	throw( IllegalArgumentException, RuntimeException )
604 {
605 	Guard< Mutex > aGuard( aLock );
606 
607 	::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
608 
609 	::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
610 	detachAll_Impl( this, nIndex, aList );
611 
612 	OUString aLstType = ListenerType;
613 	const sal_Unicode * pLastDot = aLstType.getStr();
614 	pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
615 	if( pLastDot )
616 		aLstType = pLastDot +1;
617 
618 #ifdef DEQUE_OK
619 	::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
620 	::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
621 	while( aEvtIt != aEvtEnd )
622 	{
623 		if( aLstType				== (*aEvtIt).ListenerType
624 			&& EventMethod			== (*aEvtIt).EventMethod
625 			&& ToRemoveListenerParam	== (*aEvtIt).AddListenerParam )
626 		{
627 			(*aIt).aEventList.erase( aEvtIt );
628 			break;
629 		}
630 
631 		aEvtIt++;
632 	}
633 #else
634 	Sequence< ScriptEventDescriptor >& rEventList = (*aIt).aEventList;
635 
636 			ScriptEventDescriptor* pEventList = rEventList.getArray();
637 	const	ScriptEventDescriptor* pEventListEnd = pEventList + rEventList.getLength();
638 	for( ; pEventList < pEventListEnd; ++pEventList )
639 	{
640 		if	(	(aLstType				== pEventList->ListenerType	)
641 			&&	(EventMethod			== pEventList->EventMethod		)
642 			&&	(ToRemoveListenerParam	== pEventList->AddListenerParam)
643 			)
644 		{
645 			ScriptEventDescriptor* pMoveTo = pEventList;
646 			const ScriptEventDescriptor* pMoveFrom = pMoveTo + 1;
647 			while (pMoveFrom < pEventListEnd)
648 			{
649 				*pMoveTo++ = *pMoveFrom++;
650 			}
651 			rEventList.realloc( rEventList.getLength() - 1 );
652 			break;
653 		}
654 	}
655 #endif
656 	attachAll_Impl( this, nIndex, aList );
657 }
658 
659 //-----------------------------------------------------------------------------
revokeScriptEvents(sal_Int32 nIndex)660 void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
661 	throw( IllegalArgumentException, RuntimeException )
662 {
663 	Guard< Mutex > aGuard( aLock );
664 	::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
665 
666 	::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
667 	detachAll_Impl( this, nIndex, aList );
668 #ifdef DEQUE_OK
669 	(*aIt).aEventList = ::std::deque< ScriptEventDescriptor >();
670 #else
671 	(*aIt).aEventList.realloc( 0 );
672 #endif
673 	attachAll_Impl( this, nIndex, aList );
674 }
675 
676 //-----------------------------------------------------------------------------
insertEntry(sal_Int32 nIndex)677 void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
678 	throw( IllegalArgumentException, RuntimeException )
679 {
680 	Guard< Mutex > aGuard( aLock );
681 	if( nIndex < 0 )
682 		throw IllegalArgumentException();
683 
684 //	::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
685 //	while( nIndex-- )
686 //		aIt++;
687 
688 	if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
689 		aIndex.resize(nIndex+1);
690 
691 	AttacherIndex_Impl aTmp;
692 	aIndex.insert( aIndex.begin() + nIndex, aTmp );
693 }
694 
695 //-----------------------------------------------------------------------------
removeEntry(sal_Int32 nIndex)696 void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
697 	throw( IllegalArgumentException, RuntimeException )
698 {
699 	Guard< Mutex > aGuard( aLock );
700 	::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
701 
702 	::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
703 	detachAll_Impl( this, nIndex, aList );
704 	aIndex.erase( aIt );
705 }
706 
707 //-----------------------------------------------------------------------------
getScriptEvents(sal_Int32 nIndex)708 Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
709 	throw( IllegalArgumentException, RuntimeException )
710 {
711 	Guard< Mutex > aGuard( aLock );
712 	::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
713 
714 #ifdef DEQUE_OK
715 	Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
716 	ScriptEventDescriptor * pArray = aSeq.getArray();
717 
718 	::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
719 	::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
720 	sal_Int32 i = 0;
721 	while( aEvtIt != aEvtEnd )
722 	{
723 		pArray[i++] = *aEvtIt;
724 		aEvtIt++;
725 	}
726 	return aSeq;
727 #else
728 	return (*aIt).aEventList;
729 #endif
730 }
731 
732 //-----------------------------------------------------------------------------
attach(sal_Int32 nIndex,const Reference<XInterface> & xObject,const Any & Helper)733 void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
734 	throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException )
735 {
736 	Guard< Mutex > aGuard( aLock );
737 	if( nIndex < 0 || !xObject.is() )
738 		throw IllegalArgumentException();
739 
740 	if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
741 	{
742 		// alte Dateien lesen
743 		if( nVersion == 1 )
744 		{
745 			insertEntry( nIndex );
746 			attach( nIndex, xObject, Helper );
747 			return;
748 		}
749 		else
750 			throw IllegalArgumentException();
751 	}
752 
753 	::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
754 
755 	AttachedObject_Impl aTmp;
756 	aTmp.xTarget = xObject;
757 	aTmp.aHelper = Helper;
758 	aCurrentPosition->aObjList.push_back( aTmp );
759 
760 	//::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back();
761 	AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
762 #ifdef DEQUE_OK
763 	rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
764 #else
765 	rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.getLength() );
766 #endif
767 	Reference< XEventListener > * pArray = rCurObj.aAttachedListenerSeq.getArray();
768 
769 #ifdef DEQUE_OK
770 	::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
771 	::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
772 	sal_Int32 i = 0;
773 	while( aEvtIt != aEvtEnd )
774 	{
775 		Reference< XAllListener > xAll =
776 			new AttacherAllListener_Impl( this, (*aEvtIt).ScriptType, (*aEvtIt).ScriptCode );
777 		Reference< XEventListener > xAdapter;
778 		try
779 		{
780 		xAdapter = xAttacher->attachSingleEventListener( rCurObj.xTarget, xAll,
781 						rCurObj.aHelper, (*aEvtIt).ScriptType,
782 						(*aEvtIt).AddListenerParam, (*aEvtIt).EventMethod );
783 		}
784 		catch( Exception& )
785 		{
786 		}
787 
788 		pArray[i++] = xAdapter;
789 		aEvtIt++;
790 	}
791 #else
792 	sal_Int32 nLen = aCurrentPosition->aEventList.getLength();
793 	ScriptEventDescriptor * pEL = aCurrentPosition->aEventList.getArray();
794 	for(sal_Int32 i = 0; i < nLen; ++i )
795 	{
796 		Reference< XAllListener > xAll =
797 			new AttacherAllListener_Impl( this, pEL[i].ScriptType, pEL[i].ScriptCode );
798 		Reference< XEventListener > xAdapter;
799 		try
800 		{
801 		xAdapter = xAttacher->attachSingleEventListener( rCurObj.xTarget, xAll,
802 						rCurObj.aHelper, pEL[i].ListenerType,
803 						pEL[i].AddListenerParam, pEL[i].EventMethod );
804 		}
805 		catch( Exception& )
806 		{
807 		}
808 
809 		pArray[i] = xAdapter;
810 	}
811 #endif
812 }
813 
814 //-----------------------------------------------------------------------------
detach(sal_Int32 nIndex,const Reference<XInterface> & xObject)815 void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
816 	throw( IllegalArgumentException, RuntimeException )
817 {
818 	Guard< Mutex > aGuard( aLock );
819 	//return;
820 	if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
821 		throw IllegalArgumentException();
822 
823 	::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
824 	::std::deque< AttachedObject_Impl >::iterator aObjIt = aCurrentPosition->aObjList.begin();
825 	::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end();
826 	while( aObjIt != aObjEnd )
827 	{
828 		if( (*aObjIt).xTarget == xObject )
829 		{
830 			Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
831 #ifdef DEQUE_OK
832 
833 			::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
834 			::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
835 			sal_Int32 i = 0;
836 			while( aEvtIt != aEvtEnd )
837 			{
838 				if( pArray[i].is() )
839 				{
840 					try
841 					{
842 					xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
843 												(*aEvtIt).AddListenerParam, pArray[i] );
844 					}
845 					catch( Exception& )
846 					{
847 					}
848 				}
849 				i++;
850 				aEvtIt++;
851 			}
852 #else
853 			sal_Int32 nLen = aCurrentPosition->aEventList.getLength();
854 			ScriptEventDescriptor * pEL = aCurrentPosition->aEventList.getArray();
855 			for( sal_Int32 i = 0; i < nLen; i++ )
856 			{
857 				if( pArray[i].is() )
858 				{
859 					try
860 					{
861 					xAttacher->removeListener( (*aObjIt).xTarget, pEL[i].ListenerType,
862 												pEL[i].AddListenerParam, pArray[i] );
863 					}
864 					catch( Exception& )
865 					{
866 					}
867 				}
868 			}
869 #endif
870 			aCurrentPosition->aObjList.erase( aObjIt );
871 			break;
872 		}
873 		aObjIt++;
874 	}
875 }
876 
addScriptListener(const Reference<XScriptListener> & aListener)877 void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
878 	throw( IllegalArgumentException, RuntimeException )
879 {
880 	Guard< Mutex > aGuard( aLock );
881 	aScriptListeners.addInterface( aListener );
882 }
883 
removeScriptListener(const Reference<XScriptListener> & aListener)884 void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
885 	throw( IllegalArgumentException, RuntimeException )
886 {
887 	Guard< Mutex > aGuard( aLock );
888 	aScriptListeners.removeInterface( aListener );
889 }
890 
891 
892 // Methoden von XPersistObject
getServiceName(void)893 OUString SAL_CALL ImplEventAttacherManager::getServiceName(void)
894 	throw( RuntimeException )
895 {
896 	return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.script.EventAttacherManager") );
897 }
898 
write(const Reference<XObjectOutputStream> & OutStream)899 void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
900 	throw( IOException, RuntimeException )
901 {
902 	Guard< Mutex > aGuard( aLock );
903 	// Ohne XMarkableStream laeuft nichts
904 	Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
905 	if( !xMarkStream.is() )
906 		return;
907 
908 	// Version schreiben
909 	OutStream->writeShort( 2 );
910 
911 	// Position fuer Laenge merken
912 	sal_Int32 nObjLenMark = xMarkStream->createMark();
913 	OutStream->writeLong( 0L );
914 
915 	OutStream->writeLong( aIndex.size() );
916 
917 	// Sequences schreiben
918 	::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
919 	::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end();
920 	while( aIt != aEnd )
921 	{
922 #ifdef DEQUE_OK
923 		// Laenge der Sequence und alle Descriptoren schreiben
924 		OutStream->writeLong( (*aIt).aEventList.size() );
925 		::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
926 		::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
927 		while( aEvtIt != aEvtEnd )
928 		{
929 			const ScriptEventDescriptor& rDesc = (*aEvtIt);
930 			OutStream->writeUTF( rDesc.ListenerType );
931 			OutStream->writeUTF( rDesc.EventMethod );
932 			OutStream->writeUTF( rDesc.AddListenerParam );
933 			OutStream->writeUTF( rDesc.ScriptType );
934 			OutStream->writeUTF( rDesc.ScriptCode );
935 
936 			aEvtIt++;
937 		}
938 #else
939 		sal_Int32 nLen = (*aIt).aEventList.getLength();
940 		// Laenge der Sequence und alle Descriptoren schreiben
941 		OutStream->writeLong( nLen );
942 		ScriptEventDescriptor * pEL = (*aIt).aEventList.getArray();
943 		for( sal_Int32 i = 0; i < nLen; i++ )
944 		{
945 			const ScriptEventDescriptor& rDesc = pEL[i];
946 			OutStream->writeUTF( rDesc.ListenerType );
947 			OutStream->writeUTF( rDesc.EventMethod );
948 			OutStream->writeUTF( rDesc.AddListenerParam );
949 			OutStream->writeUTF( rDesc.ScriptType );
950 			OutStream->writeUTF( rDesc.ScriptCode );
951 		}
952 #endif
953 		aIt++;
954 	}
955 
956 	// Die jetzt bekannte Laenge eintragen
957 	sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
958 	xMarkStream->jumpToMark( nObjLenMark );
959 	OutStream->writeLong( nObjLen );
960 	xMarkStream->jumpToFurthest();
961 	xMarkStream->deleteMark( nObjLenMark );
962 }
963 
read(const Reference<XObjectInputStream> & InStream)964 void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
965 	throw( IOException, RuntimeException )
966 {
967 	Guard< Mutex > aGuard( aLock );
968 	// Ohne XMarkableStream laeuft nichts
969 	Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
970 	if( !xMarkStream.is() )
971 		return;
972 
973 	// Version lesen
974 	nVersion = InStream->readShort();
975 
976 	// Zunaechst kommen die Daten gemaess Version 1,
977 	// muss auch bei hoeheren Versionen beibehalten werden
978 	sal_Int32 nLen = InStream->readLong();
979 
980 	// Position fuer Vergleichszwecke
981 	sal_Int32 nObjLenMark = xMarkStream->createMark();
982 
983 	// Anzahl der zu lesenden Sequences
984 	sal_Int32 nItemCount = InStream->readLong();
985 
986 	for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
987 	{
988 		insertEntry( i );
989 		// Laenge der Sequence lesen
990 		sal_Int32 nSeqLen = InStream->readLong();
991 
992 		// Sequence anlegen und Descriptoren lesen
993 		Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
994 		ScriptEventDescriptor* pArray = aSEDSeq.getArray();
995 		for( sal_Int32 j = 0 ; j < nSeqLen ; j++ )
996 		{
997 			ScriptEventDescriptor& rDesc = pArray[ j ];
998 			rDesc.ListenerType = InStream->readUTF();
999 			rDesc.EventMethod = InStream->readUTF();
1000 			rDesc.AddListenerParam = InStream->readUTF();
1001 			rDesc.ScriptType = InStream->readUTF();
1002 			rDesc.ScriptCode = InStream->readUTF();
1003 		}
1004 		registerScriptEvents( i, aSEDSeq );
1005 	}
1006 
1007 	// Haben wir die angegebene Laenge gelesen?
1008 	sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
1009 	if( nRealLen != nLen )
1010 	{
1011 		// Nur wenn die StreamVersion > 1 ist und noch Daten folgen, kann das
1012 		// Ganze richtig sein. Sonst ist etwas voellig daneben gegangen.
1013 		if( nRealLen > nLen || nVersion == 1 )
1014 		{
1015 			VOS_ENSHURE( sal_False, "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
1016 		}
1017 		else
1018 		{
1019 			// TODO: Pruefen, ob Zwischen-Speicherung der Daten sinnvoll sein koennte
1020 
1021 			// Vorerst einfach nur Skippen
1022 			sal_Int32 nSkipCount = nLen - nRealLen;
1023 			InStream->skipBytes( nSkipCount );
1024 		}
1025 	}
1026 	xMarkStream->jumpToFurthest();
1027 	xMarkStream->deleteMark( nObjLenMark );
1028 }
1029 
1030 } // namesapce comphelper
1031