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