Update ooo320-m1
[ooovba.git] / comphelper / source / eventattachermgr / eventattachermgr.cxx
blob1f85be1c0e9bae8823b8fcf1a2c773db0959184e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: eventattachermgr.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_comphelper.hxx"
34 #include <deque>
36 #if defined( OS2 ) || defined( UNX )
37 #include <wchar.h>
38 #endif
39 #include <osl/mutex.hxx>
40 #ifndef _VOS_DIAGNOSE_HXX_
41 #include <vos/diagnose.hxx>
42 #endif
43 #include <vos/macros.hxx>
44 #include <comphelper/eventattachermgr.hxx>
45 #include <com/sun/star/beans/XIntrospection.hpp>
46 #include <com/sun/star/io/XObjectInputStream.hpp>
47 #include <com/sun/star/io/XPersistObject.hpp>
48 #include <com/sun/star/io/XObjectOutputStream.hpp>
49 #include <com/sun/star/io/XMarkableStream.hpp>
50 #include <com/sun/star/lang/XInitialization.hpp>
51 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
52 #include <com/sun/star/reflection/XIdlClass.hpp>
53 #include <com/sun/star/reflection/XIdlReflection.hpp>
54 #include <com/sun/star/reflection/XIdlMethod.hpp>
55 #include <com/sun/star/script/XTypeConverter.hpp>
56 #include <com/sun/star/script/XEngineListener.hpp>
57 #include <com/sun/star/script/XEventAttacher.hpp>
58 #include <com/sun/star/script/XEventAttacherManager.hpp>
59 #include <com/sun/star/script/XScriptListener.hpp>
60 #include <cppuhelper/weak.hxx>
61 #include <cppuhelper/interfacecontainer.hxx>
62 #include <cppuhelper/implbase1.hxx>
63 #include <cppuhelper/implbase2.hxx>
65 using namespace com::sun::star::uno;
66 using namespace com::sun::star::io;
67 using namespace com::sun::star::lang;
68 using namespace com::sun::star::beans;
69 using namespace com::sun::star::script;
70 using namespace com::sun::star::reflection;
71 using namespace cppu;
72 using namespace osl;
73 using namespace rtl;
75 namespace comphelper
78 //-----------------------------------------------------------------------------
79 struct AttachedObject_Impl
81 Reference< XInterface > xTarget;
82 Sequence< Reference< XEventListener > > aAttachedListenerSeq;
83 Any aHelper;
85 bool operator<( const AttachedObject_Impl & ) const;
86 bool operator==( const AttachedObject_Impl & ) const;
89 struct AttacherIndex_Impl
91 #ifdef DEQUE_OK
92 ::std::deque< ScriptEventDescriptor > aEventList;
93 #else
94 Sequence< ScriptEventDescriptor > aEventList;
95 #endif
96 ::std::deque< AttachedObject_Impl > aObjList;
98 bool operator<( const AttacherIndex_Impl & ) const;
99 bool operator==( const AttacherIndex_Impl & ) const;
102 #if 0
103 bool AttachedObject_Impl::operator<( const AttachedObject_Impl & r ) const
105 VOS_ENSHURE( FALSE, "not implemented" );
106 return FALSE;
107 return this < &r;
110 bool AttachedObject_Impl::operator==( const AttachedObject_Impl & r ) const
112 VOS_ENSHURE( FALSE, "not implemented" );
113 return this == &r;
116 bool AttacherIndex_Impl::operator<( const AttacherIndex_Impl & r ) const
118 VOS_ENSHURE( FALSE, "not implemented" );
119 return this < &r;
121 bool AttacherIndex_Impl::operator==( const AttacherIndex_Impl & r ) const
123 VOS_ENSHURE( FALSE, "not implemented" );
124 return this == &r;
126 #endif
128 //-----------------------------------------------------------------------------
129 class ImplEventAttacherManager
130 : public WeakImplHelper2< XEventAttacherManager, XPersistObject >
132 friend class AttacherAllListener_Impl;
133 ::std::deque< AttacherIndex_Impl > aIndex;
134 Mutex aLock;
135 // Container fuer die ScriptListener
136 OInterfaceContainerHelper aScriptListeners;
137 // EventAttacher-Instanz
138 Reference< XEventAttacher > xAttacher;
139 Reference< XMultiServiceFactory > mxSMgr;
140 Reference< XIdlReflection > mxCoreReflection;
141 Reference< XIntrospection > mxIntrospection;
142 Reference< XTypeConverter > xConverter;
143 sal_Int16 nVersion;
144 public:
145 ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
146 const Reference< XMultiServiceFactory > rSMgr );
147 ~ImplEventAttacherManager();
149 // Methoden von XEventAttacherManager
150 virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent)
151 throw( IllegalArgumentException, RuntimeException );
152 virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents)
153 throw( IllegalArgumentException, RuntimeException );
154 virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam)
155 throw( IllegalArgumentException, RuntimeException );
156 virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index)
157 throw( IllegalArgumentException, RuntimeException );
158 virtual void SAL_CALL insertEntry(sal_Int32 Index)
159 throw( IllegalArgumentException, RuntimeException );
160 virtual void SAL_CALL removeEntry(sal_Int32 Index)
161 throw( IllegalArgumentException, RuntimeException );
162 virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index)
163 throw( IllegalArgumentException, RuntimeException );
164 virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper)
165 throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException );
166 virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
167 throw( IllegalArgumentException, RuntimeException );
168 virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener)
169 throw( IllegalArgumentException, RuntimeException );
170 virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener)
171 throw( IllegalArgumentException, RuntimeException );
173 // Methoden von XPersistObject
174 virtual OUString SAL_CALL getServiceName(void) throw( RuntimeException );
175 virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream) throw( IOException, RuntimeException );
176 virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) throw( IOException, RuntimeException );
178 private:
179 Reference< XIdlReflection > getReflection() throw( Exception );
181 /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
182 @param _nIndex
183 the index to check
184 @return
185 the iterator pointing to the position indicated by the index
187 ::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) );
190 //========================================================================
191 //========================================================================
192 //========================================================================
194 // Implementation eines EventAttacher-bezogenen AllListeners, der
195 // nur einzelne Events an einen allgemeinen AllListener weiterleitet
196 class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener >
198 ImplEventAttacherManager* mpManager;
199 Reference< XEventAttacherManager > xManager;
200 OUString aScriptType;
201 OUString aScriptCode;
202 sal_Int16 nVersion;
204 void convertToEventReturn( Any & rRet, const Type & rRetType )
205 throw( CannotConvertException );
206 public:
207 AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_,
208 const OUString & rScriptCode_ );
210 // Methoden von XAllListener
211 virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException );
212 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException );
214 // Methoden von XEventListener
215 virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
218 //========================================================================
219 AttacherAllListener_Impl::AttacherAllListener_Impl
221 ImplEventAttacherManager* pManager_,
222 const OUString & rScriptType_,
223 const OUString & rScriptCode_
225 : mpManager( pManager_ )
226 , xManager( pManager_ )
227 , aScriptType( rScriptType_ )
228 , aScriptCode( rScriptCode_ )
229 , nVersion( 2 )
234 //========================================================================
235 // Methoden von XAllListener
236 void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
237 throw( RuntimeException )
239 ScriptEvent aScriptEvent;
240 aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface
241 aScriptEvent.ListenerType = Event.ListenerType;
242 aScriptEvent.MethodName = Event.MethodName;
243 aScriptEvent.Arguments = Event.Arguments;
244 aScriptEvent.Helper = Event.Helper;
245 aScriptEvent.ScriptType = aScriptType;
246 aScriptEvent.ScriptCode = aScriptCode;
248 // ueber alle Listener iterieren und Events senden
249 OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
250 while( aIt.hasMoreElements() )
251 ((XScriptListener *)aIt.next())->firing( aScriptEvent );
254 //========================================================================
255 // Convert to the standard event return
256 void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
257 throw( CannotConvertException )
259 // no return value? Set to the specified values
260 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
262 switch( rRetType.getTypeClass() )
264 case TypeClass_INTERFACE:
266 rRet <<= Reference< XInterface >();
268 break;
270 case TypeClass_BOOLEAN:
271 rRet <<= sal_True;
272 break;
274 case TypeClass_STRING:
275 rRet <<= OUString();
276 break;
278 case TypeClass_FLOAT: rRet <<= float(0); break;
279 case TypeClass_DOUBLE: rRet <<= double(0.0); break;
280 case TypeClass_BYTE: rRet <<= sal_uInt8(0); break;
281 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
282 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
283 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
284 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
286 default:
287 OSL_ASSERT(false);
288 break;
291 else if( !rRet.getValueType().equals( rRetType ) )
293 if( mpManager->xConverter.is() )
294 rRet = mpManager->xConverter->convertTo( rRet, rRetType );
295 else
296 throw CannotConvertException();
300 //========================================================================
301 // Methoden von XAllListener
302 Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event )
303 throw( InvocationTargetException, RuntimeException )
305 ScriptEvent aScriptEvent;
306 aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface
307 aScriptEvent.ListenerType = Event.ListenerType;
308 aScriptEvent.MethodName = Event.MethodName;
309 aScriptEvent.Arguments = Event.Arguments;
310 aScriptEvent.Helper = Event.Helper;
311 aScriptEvent.ScriptType = aScriptType;
312 aScriptEvent.ScriptCode = aScriptCode;
314 Any aRet;
315 // ueber alle Listener iterieren und Events senden
316 OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
317 while( aIt.hasMoreElements() )
319 aRet = ((XScriptListener *)aIt.next())->approveFiring( aScriptEvent );
322 Reference< XIdlClass > xListenerType = mpManager->getReflection()->
323 forName( Event.ListenerType.getTypeName() );
324 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
325 if( xMeth.is() )
327 Reference< XIdlClass > xRetType = xMeth->getReturnType();
328 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
329 convertToEventReturn( aRet, aRetType );
332 switch( aRet.getValueType().getTypeClass() )
334 case TypeClass_INTERFACE:
336 // Interface not null, return
337 Reference< XInterface > x;
338 aRet >>= x;
339 if( x.is() )
340 return aRet;
342 break;
344 case TypeClass_BOOLEAN:
345 // FALSE -> Return
346 if( !(*(sal_Bool*)aRet.getValue()) )
347 return aRet;
348 break;
350 case TypeClass_STRING:
351 // none empty string -> return
352 if( ((OUString*)aRet.getValue())->getLength() > 0 )
353 return aRet;
354 break;
356 // none zero number -> return
357 case TypeClass_FLOAT: if( *((float*)aRet.getValue()) ) return aRet; break;
358 case TypeClass_DOUBLE: if( *((double*)aRet.getValue()) ) return aRet; break;
359 case TypeClass_BYTE: if( *((sal_uInt8*)aRet.getValue()) ) return aRet; break;
360 case TypeClass_SHORT: if( *((sal_Int16*)aRet.getValue()) ) return aRet; break;
361 case TypeClass_LONG: if( *((sal_Int32*)aRet.getValue()) ) return aRet; break;
362 case TypeClass_UNSIGNED_SHORT: if( *((sal_uInt16*)aRet.getValue()) ) return aRet; break;
363 case TypeClass_UNSIGNED_LONG: if( *((sal_uInt32*)aRet.getValue()) ) return aRet; break;
365 default:
366 OSL_ASSERT(false);
367 break;
370 catch( CannotConvertException& )
372 // silent ignore conversions errors from a script call
373 Reference< XIdlClass > xListenerType = mpManager->getReflection()->
374 forName( Event.ListenerType.getTypeName() );
375 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
376 if( xMeth.is() )
378 Reference< XIdlClass > xRetType = xMeth->getReturnType();
379 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
380 aRet.clear();
381 convertToEventReturn( aRet, aRetType );
385 return aRet;
388 //========================================================================
389 // Methoden von XEventListener
390 void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
391 throw( RuntimeException )
393 // It is up to the container to release the object
397 //========================================================================
398 //========================================================================
399 //========================================================================
401 // Create-Methode fuer EventAttacherManager
402 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
403 const Reference< XMultiServiceFactory > & rSMgr )
404 throw( Exception )
406 return new ImplEventAttacherManager( rIntrospection, rSMgr );
409 // Create-Methode fuer EventAttacherManager
410 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XMultiServiceFactory > & rSMgr )
411 throw( Exception )
413 if ( rSMgr.is() )
415 Reference< XInterface > xIFace( rSMgr->createInstance( OUString::createFromAscii("com.sun.star.beans.Introspection") ) );
416 if ( xIFace.is() )
418 Reference< XIntrospection > xIntrospection( xIFace, UNO_QUERY);
419 return new ImplEventAttacherManager( xIntrospection, rSMgr );
423 return Reference< XEventAttacherManager >();
426 //-----------------------------------------------------------------------------
427 ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
428 const Reference< XMultiServiceFactory > rSMgr )
429 : aScriptListeners( aLock )
430 , mxSMgr( rSMgr )
431 , mxIntrospection( rIntrospection )
433 if ( rSMgr.is() )
435 Reference< XInterface > xIFace( rSMgr->createInstance( OUString::createFromAscii("com.sun.star.script.EventAttacher") ) );
436 if ( xIFace.is() )
438 xAttacher = Reference< XEventAttacher >::query( xIFace );
440 xIFace = rSMgr->createInstance( OUString::createFromAscii("com.sun.star.script.Converter") );
441 if ( xIFace.is() )
443 xConverter = Reference< XTypeConverter >::query( xIFace );
447 Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
448 if( xInit.is() )
450 Sequence< Any > Arguments( 1 );
451 Arguments[0] <<= rIntrospection;
452 xInit->initialize( Arguments );
456 //-----------------------------------------------------------------------------
457 ImplEventAttacherManager::~ImplEventAttacherManager()
461 Reference< XIdlReflection > ImplEventAttacherManager::getReflection() throw( Exception )
463 Guard< Mutex > aGuard( aLock );
464 // Haben wir den Service schon? Sonst anlegen
465 if( !mxCoreReflection.is() )
467 Reference< XInterface > xIFace( mxSMgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection") ) );
468 mxCoreReflection = Reference< XIdlReflection >( xIFace, UNO_QUERY);
470 return mxCoreReflection;
474 //-----------------------------------------------------------------------------
475 ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) )
477 if (_nIndex < 0)
478 throw IllegalArgumentException();
480 ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
481 for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
484 if( aIt == aIndex.end() )
485 throw IllegalArgumentException();
487 return aIt;
490 //-----------------------------------------------------------------------------
491 void detachAll_Impl
493 ImplEventAttacherManager * pMgr,
494 sal_Int32 nIdx,
495 ::std::deque< AttachedObject_Impl > & rList
498 ::std::deque< AttachedObject_Impl >::iterator aObjIt = rList.begin();
499 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = rList.end();
500 while( aObjIt != aObjEnd )
502 pMgr->detach( nIdx, (*aObjIt).xTarget );
503 aObjIt++;
507 //-----------------------------------------------------------------------------
508 void attachAll_Impl
510 ImplEventAttacherManager * pMgr,
511 sal_Int32 nIdx,
512 ::std::deque< AttachedObject_Impl > & rList
515 ::std::deque< AttachedObject_Impl >::iterator aObjIt = rList.begin();
516 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = rList.end();
517 while( aObjIt != aObjEnd )
519 pMgr->attach( nIdx, (*aObjIt).xTarget, (*aObjIt).aHelper );
520 aObjIt++;
524 //-----------------------------------------------------------------------------
525 //*** Methoden von XEventAttacherManager ***
526 void SAL_CALL ImplEventAttacherManager::registerScriptEvent
528 sal_Int32 nIndex,
529 const ScriptEventDescriptor& ScriptEvent
531 throw( IllegalArgumentException, RuntimeException )
533 Guard< Mutex > aGuard( aLock );
535 // Index pruefen und Array anpassen
536 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
538 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
540 ScriptEventDescriptor aEvt = ScriptEvent;
541 const sal_Unicode* pLastDot = aEvt.ListenerType.getStr();
542 pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
543 if( pLastDot )
544 aEvt.ListenerType = pLastDot +1;
545 #ifdef DEQUE_OK
546 (*aIt).aEventList.push_back( aEvt );
547 #else
548 (*aIt).aEventList.realloc( (*aIt).aEventList.getLength() +1 );
549 (*aIt).aEventList.getArray()[(*aIt).aEventList.getLength() -1] = aEvt;
550 #endif
552 // register new new Event
553 ::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.begin();
554 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end();
555 while( aObjIt != aObjEnd )
557 // resize
558 sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
559 (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
560 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
562 Reference< XAllListener > xAll =
563 new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
566 pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
567 (*aObjIt).aHelper, ScriptEvent.ListenerType,
568 ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
570 catch( Exception& )
574 aObjIt++;
578 //-----------------------------------------------------------------------------
579 void SAL_CALL ImplEventAttacherManager::registerScriptEvents
581 sal_Int32 nIndex,
582 const Sequence< ScriptEventDescriptor >& ScriptEvents
584 throw( IllegalArgumentException, RuntimeException )
586 Guard< Mutex > aGuard( aLock );
588 // Index pruefen und Array anpassen
589 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
591 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
592 detachAll_Impl( this, nIndex, aList );
594 const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
595 sal_Int32 nLen = ScriptEvents.getLength();
596 for( sal_Int32 i = 0 ; i < nLen ; i++ )
597 registerScriptEvent( nIndex, pArray[ i ] );
599 attachAll_Impl( this, nIndex, aList );
602 //-----------------------------------------------------------------------------
603 void SAL_CALL ImplEventAttacherManager::revokeScriptEvent
605 sal_Int32 nIndex,
606 const OUString& ListenerType,
607 const OUString& EventMethod,
608 const OUString& ToRemoveListenerParam
610 throw( IllegalArgumentException, RuntimeException )
612 Guard< Mutex > aGuard( aLock );
614 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
616 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
617 detachAll_Impl( this, nIndex, aList );
619 OUString aLstType = ListenerType;
620 const sal_Unicode * pLastDot = aLstType.getStr();
621 pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
622 if( pLastDot )
623 aLstType = pLastDot +1;
625 #ifdef DEQUE_OK
626 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
627 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
628 while( aEvtIt != aEvtEnd )
630 if( aLstType == (*aEvtIt).ListenerType
631 && EventMethod == (*aEvtIt).EventMethod
632 && ToRemoveListenerParam == (*aEvtIt).AddListenerParam )
634 (*aIt).aEventList.erase( aEvtIt );
635 break;
638 aEvtIt++;
640 #else
641 Sequence< ScriptEventDescriptor >& rEventList = (*aIt).aEventList;
643 ScriptEventDescriptor* pEventList = rEventList.getArray();
644 const ScriptEventDescriptor* pEventListEnd = pEventList + rEventList.getLength();
645 for( ; pEventList < pEventListEnd; ++pEventList )
647 if ( (aLstType == pEventList->ListenerType )
648 && (EventMethod == pEventList->EventMethod )
649 && (ToRemoveListenerParam == pEventList->AddListenerParam)
652 ScriptEventDescriptor* pMoveTo = pEventList;
653 const ScriptEventDescriptor* pMoveFrom = pMoveTo + 1;
654 while (pMoveFrom < pEventListEnd)
656 *pMoveTo++ = *pMoveFrom++;
658 rEventList.realloc( rEventList.getLength() - 1 );
659 break;
662 #endif
663 attachAll_Impl( this, nIndex, aList );
666 //-----------------------------------------------------------------------------
667 void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
668 throw( IllegalArgumentException, RuntimeException )
670 Guard< Mutex > aGuard( aLock );
671 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
673 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
674 detachAll_Impl( this, nIndex, aList );
675 #ifdef DEQUE_OK
676 (*aIt).aEventList = ::std::deque< ScriptEventDescriptor >();
677 #else
678 (*aIt).aEventList.realloc( 0 );
679 #endif
680 attachAll_Impl( this, nIndex, aList );
683 //-----------------------------------------------------------------------------
684 void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
685 throw( IllegalArgumentException, RuntimeException )
687 Guard< Mutex > aGuard( aLock );
688 if( nIndex < 0 )
689 throw IllegalArgumentException();
691 // ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
692 // while( nIndex-- )
693 // aIt++;
695 if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
696 aIndex.resize(nIndex+1);
698 AttacherIndex_Impl aTmp;
699 aIndex.insert( aIndex.begin() + nIndex, aTmp );
702 //-----------------------------------------------------------------------------
703 void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
704 throw( IllegalArgumentException, RuntimeException )
706 Guard< Mutex > aGuard( aLock );
707 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
709 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
710 detachAll_Impl( this, nIndex, aList );
711 aIndex.erase( aIt );
714 //-----------------------------------------------------------------------------
715 Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
716 throw( IllegalArgumentException, RuntimeException )
718 Guard< Mutex > aGuard( aLock );
719 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
721 #ifdef DEQUE_OK
722 Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
723 ScriptEventDescriptor * pArray = aSeq.getArray();
725 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
726 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
727 sal_Int32 i = 0;
728 while( aEvtIt != aEvtEnd )
730 pArray[i++] = *aEvtIt;
731 aEvtIt++;
733 return aSeq;
734 #else
735 return (*aIt).aEventList;
736 #endif
739 //-----------------------------------------------------------------------------
740 void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
741 throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException )
743 Guard< Mutex > aGuard( aLock );
744 if( nIndex < 0 || !xObject.is() )
745 throw IllegalArgumentException();
747 if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
749 // alte Dateien lesen
750 if( nVersion == 1 )
752 insertEntry( nIndex );
753 attach( nIndex, xObject, Helper );
754 return;
756 else
757 throw IllegalArgumentException();
760 ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
762 AttachedObject_Impl aTmp;
763 aTmp.xTarget = xObject;
764 aTmp.aHelper = Helper;
765 aCurrentPosition->aObjList.push_back( aTmp );
767 //::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back();
768 AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
769 #ifdef DEQUE_OK
770 rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
771 #else
772 rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.getLength() );
773 #endif
774 Reference< XEventListener > * pArray = rCurObj.aAttachedListenerSeq.getArray();
776 #ifdef DEQUE_OK
777 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
778 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
779 sal_Int32 i = 0;
780 while( aEvtIt != aEvtEnd )
782 Reference< XAllListener > xAll =
783 new AttacherAllListener_Impl( this, (*aEvtIt).ScriptType, (*aEvtIt).ScriptCode );
784 Reference< XEventListener > xAdapter;
787 xAdapter = xAttacher->attachSingleEventListener( rCurObj.xTarget, xAll,
788 rCurObj.aHelper, (*aEvtIt).ScriptType,
789 (*aEvtIt).AddListenerParam, (*aEvtIt).EventMethod );
791 catch( Exception& )
795 pArray[i++] = xAdapter;
796 aEvtIt++;
798 #else
799 sal_Int32 nLen = aCurrentPosition->aEventList.getLength();
800 ScriptEventDescriptor * pEL = aCurrentPosition->aEventList.getArray();
801 for(sal_Int32 i = 0; i < nLen; ++i )
803 Reference< XAllListener > xAll =
804 new AttacherAllListener_Impl( this, pEL[i].ScriptType, pEL[i].ScriptCode );
805 Reference< XEventListener > xAdapter;
808 xAdapter = xAttacher->attachSingleEventListener( rCurObj.xTarget, xAll,
809 rCurObj.aHelper, pEL[i].ListenerType,
810 pEL[i].AddListenerParam, pEL[i].EventMethod );
812 catch( Exception& )
816 pArray[i] = xAdapter;
818 #endif
821 //-----------------------------------------------------------------------------
822 void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
823 throw( IllegalArgumentException, RuntimeException )
825 Guard< Mutex > aGuard( aLock );
826 //return;
827 if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
828 throw IllegalArgumentException();
830 ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
831 ::std::deque< AttachedObject_Impl >::iterator aObjIt = aCurrentPosition->aObjList.begin();
832 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end();
833 while( aObjIt != aObjEnd )
835 if( (*aObjIt).xTarget == xObject )
837 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
838 #ifdef DEQUE_OK
840 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
841 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
842 sal_Int32 i = 0;
843 while( aEvtIt != aEvtEnd )
845 if( pArray[i].is() )
849 xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
850 (*aEvtIt).AddListenerParam, pArray[i] );
852 catch( Exception& )
856 i++;
857 aEvtIt++;
859 #else
860 sal_Int32 nLen = aCurrentPosition->aEventList.getLength();
861 ScriptEventDescriptor * pEL = aCurrentPosition->aEventList.getArray();
862 for( sal_Int32 i = 0; i < nLen; i++ )
864 if( pArray[i].is() )
868 xAttacher->removeListener( (*aObjIt).xTarget, pEL[i].ListenerType,
869 pEL[i].AddListenerParam, pArray[i] );
871 catch( Exception& )
876 #endif
877 aCurrentPosition->aObjList.erase( aObjIt );
878 break;
880 aObjIt++;
884 void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
885 throw( IllegalArgumentException, RuntimeException )
887 Guard< Mutex > aGuard( aLock );
888 aScriptListeners.addInterface( aListener );
891 void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
892 throw( IllegalArgumentException, RuntimeException )
894 Guard< Mutex > aGuard( aLock );
895 aScriptListeners.removeInterface( aListener );
899 // Methoden von XPersistObject
900 OUString SAL_CALL ImplEventAttacherManager::getServiceName(void)
901 throw( RuntimeException )
903 return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.script.EventAttacherManager") );
906 void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
907 throw( IOException, RuntimeException )
909 Guard< Mutex > aGuard( aLock );
910 // Ohne XMarkableStream laeuft nichts
911 Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
912 if( !xMarkStream.is() )
913 return;
915 // Version schreiben
916 OutStream->writeShort( 2 );
918 // Position fuer Laenge merken
919 sal_Int32 nObjLenMark = xMarkStream->createMark();
920 OutStream->writeLong( 0L );
922 OutStream->writeLong( aIndex.size() );
924 // Sequences schreiben
925 ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
926 ::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end();
927 while( aIt != aEnd )
929 #ifdef DEQUE_OK
930 // Laenge der Sequence und alle Descriptoren schreiben
931 OutStream->writeLong( (*aIt).aEventList.size() );
932 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
933 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
934 while( aEvtIt != aEvtEnd )
936 const ScriptEventDescriptor& rDesc = (*aEvtIt);
937 OutStream->writeUTF( rDesc.ListenerType );
938 OutStream->writeUTF( rDesc.EventMethod );
939 OutStream->writeUTF( rDesc.AddListenerParam );
940 OutStream->writeUTF( rDesc.ScriptType );
941 OutStream->writeUTF( rDesc.ScriptCode );
943 aEvtIt++;
945 #else
946 sal_Int32 nLen = (*aIt).aEventList.getLength();
947 // Laenge der Sequence und alle Descriptoren schreiben
948 OutStream->writeLong( nLen );
949 ScriptEventDescriptor * pEL = (*aIt).aEventList.getArray();
950 for( sal_Int32 i = 0; i < nLen; i++ )
952 const ScriptEventDescriptor& rDesc = pEL[i];
953 OutStream->writeUTF( rDesc.ListenerType );
954 OutStream->writeUTF( rDesc.EventMethod );
955 OutStream->writeUTF( rDesc.AddListenerParam );
956 OutStream->writeUTF( rDesc.ScriptType );
957 OutStream->writeUTF( rDesc.ScriptCode );
959 #endif
960 aIt++;
963 // Die jetzt bekannte Laenge eintragen
964 sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
965 xMarkStream->jumpToMark( nObjLenMark );
966 OutStream->writeLong( nObjLen );
967 xMarkStream->jumpToFurthest();
968 xMarkStream->deleteMark( nObjLenMark );
971 void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
972 throw( IOException, RuntimeException )
974 Guard< Mutex > aGuard( aLock );
975 // Ohne XMarkableStream laeuft nichts
976 Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
977 if( !xMarkStream.is() )
978 return;
980 // Version lesen
981 nVersion = InStream->readShort();
983 // Zunaechst kommen die Daten gemaess Version 1,
984 // muss auch bei hoeheren Versionen beibehalten werden
985 sal_Int32 nLen = InStream->readLong();
987 // Position fuer Vergleichszwecke
988 sal_Int32 nObjLenMark = xMarkStream->createMark();
990 // Anzahl der zu lesenden Sequences
991 sal_Int32 nItemCount = InStream->readLong();
993 for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
995 insertEntry( i );
996 // Laenge der Sequence lesen
997 sal_Int32 nSeqLen = InStream->readLong();
999 // Sequence anlegen und Descriptoren lesen
1000 Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
1001 ScriptEventDescriptor* pArray = aSEDSeq.getArray();
1002 for( sal_Int32 j = 0 ; j < nSeqLen ; j++ )
1004 ScriptEventDescriptor& rDesc = pArray[ j ];
1005 rDesc.ListenerType = InStream->readUTF();
1006 rDesc.EventMethod = InStream->readUTF();
1007 rDesc.AddListenerParam = InStream->readUTF();
1008 rDesc.ScriptType = InStream->readUTF();
1009 rDesc.ScriptCode = InStream->readUTF();
1011 registerScriptEvents( i, aSEDSeq );
1014 // Haben wir die angegebene Laenge gelesen?
1015 sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
1016 if( nRealLen != nLen )
1018 // Nur wenn die StreamVersion > 1 ist und noch Daten folgen, kann das
1019 // Ganze richtig sein. Sonst ist etwas voellig daneben gegangen.
1020 if( nRealLen > nLen || nVersion == 1 )
1022 VOS_ENSHURE( sal_False, "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
1024 else
1026 // TODO: Pruefen, ob Zwischen-Speicherung der Daten sinnvoll sein koennte
1028 // Vorerst einfach nur Skippen
1029 sal_Int32 nSkipCount = nLen - nRealLen;
1030 InStream->skipBytes( nSkipCount );
1033 xMarkStream->jumpToFurthest();
1034 xMarkStream->deleteMark( nObjLenMark );
1037 } // namesapce comphelper