CWS-TOOLING: integrate CWS os146
[LibreOffice.git] / comphelper / source / eventattachermgr / eventattachermgr.cxx
blobbf217f75c8dbd8e74b40d4fefb51e83f5158878c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
31 #include <deque>
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>
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;
72 namespace comphelper
75 //-----------------------------------------------------------------------------
76 struct AttachedObject_Impl
78 Reference< XInterface > xTarget;
79 Sequence< Reference< XEventListener > > aAttachedListenerSeq;
80 Any aHelper;
82 bool operator<( const AttachedObject_Impl & ) const;
83 bool operator==( const AttachedObject_Impl & ) const;
86 struct AttacherIndex_Impl
88 #ifdef DEQUE_OK
89 ::std::deque< ScriptEventDescriptor > aEventList;
90 #else
91 Sequence< ScriptEventDescriptor > aEventList;
92 #endif
93 ::std::deque< AttachedObject_Impl > aObjList;
95 bool operator<( const AttacherIndex_Impl & ) const;
96 bool operator==( const AttacherIndex_Impl & ) const;
99 #if 0
100 bool AttachedObject_Impl::operator<( const AttachedObject_Impl & r ) const
102 VOS_ENSHURE( FALSE, "not implemented" );
103 return FALSE;
104 return this < &r;
107 bool AttachedObject_Impl::operator==( const AttachedObject_Impl & r ) const
109 VOS_ENSHURE( FALSE, "not implemented" );
110 return this == &r;
113 bool AttacherIndex_Impl::operator<( const AttacherIndex_Impl & r ) const
115 VOS_ENSHURE( FALSE, "not implemented" );
116 return this < &r;
118 bool AttacherIndex_Impl::operator==( const AttacherIndex_Impl & r ) const
120 VOS_ENSHURE( FALSE, "not implemented" );
121 return this == &r;
123 #endif
125 //-----------------------------------------------------------------------------
126 class ImplEventAttacherManager
127 : public WeakImplHelper2< XEventAttacherManager, XPersistObject >
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();
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 );
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 );
175 private:
176 Reference< XIdlReflection > getReflection() throw( Exception );
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
184 ::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) );
187 //========================================================================
188 //========================================================================
189 //========================================================================
191 // Implementation eines EventAttacher-bezogenen AllListeners, der
192 // nur einzelne Events an einen allgemeinen AllListener weiterleitet
193 class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener >
195 ImplEventAttacherManager* mpManager;
196 Reference< XEventAttacherManager > xManager;
197 OUString aScriptType;
198 OUString aScriptCode;
199 sal_Int16 nVersion;
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_ );
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 );
211 // Methoden von XEventListener
212 virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
215 //========================================================================
216 AttacherAllListener_Impl::AttacherAllListener_Impl
218 ImplEventAttacherManager* pManager_,
219 const OUString & rScriptType_,
220 const OUString & rScriptCode_
222 : mpManager( pManager_ )
223 , xManager( pManager_ )
224 , aScriptType( rScriptType_ )
225 , aScriptCode( rScriptCode_ )
226 , nVersion( 2 )
231 //========================================================================
232 // Methoden von XAllListener
233 void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
234 throw( RuntimeException )
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;
245 // ueber alle Listener iterieren und Events senden
246 OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
247 while( aIt.hasMoreElements() )
248 ((XScriptListener *)aIt.next())->firing( aScriptEvent );
251 //========================================================================
252 // Convert to the standard event return
253 void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
254 throw( CannotConvertException )
256 // no return value? Set to the specified values
257 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
259 switch( rRetType.getTypeClass() )
261 case TypeClass_INTERFACE:
263 rRet <<= Reference< XInterface >();
265 break;
267 case TypeClass_BOOLEAN:
268 rRet <<= sal_True;
269 break;
271 case TypeClass_STRING:
272 rRet <<= OUString();
273 break;
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;
283 default:
284 OSL_ASSERT(false);
285 break;
288 else if( !rRet.getValueType().equals( rRetType ) )
290 if( mpManager->xConverter.is() )
291 rRet = mpManager->xConverter->convertTo( rRet, rRetType );
292 else
293 throw CannotConvertException();
297 //========================================================================
298 // Methoden von XAllListener
299 Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event )
300 throw( InvocationTargetException, RuntimeException )
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;
311 Any aRet;
312 // ueber alle Listener iterieren und Events senden
313 OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
314 while( aIt.hasMoreElements() )
316 aRet = ((XScriptListener *)aIt.next())->approveFiring( aScriptEvent );
319 Reference< XIdlClass > xListenerType = mpManager->getReflection()->
320 forName( Event.ListenerType.getTypeName() );
321 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
322 if( xMeth.is() )
324 Reference< XIdlClass > xRetType = xMeth->getReturnType();
325 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
326 convertToEventReturn( aRet, aRetType );
329 switch( aRet.getValueType().getTypeClass() )
331 case TypeClass_INTERFACE:
333 // Interface not null, return
334 Reference< XInterface > x;
335 aRet >>= x;
336 if( x.is() )
337 return aRet;
339 break;
341 case TypeClass_BOOLEAN:
342 // FALSE -> Return
343 if( !(*(sal_Bool*)aRet.getValue()) )
344 return aRet;
345 break;
347 case TypeClass_STRING:
348 // none empty string -> return
349 if( ((OUString*)aRet.getValue())->getLength() > 0 )
350 return aRet;
351 break;
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;
362 default:
363 OSL_ASSERT(false);
364 break;
367 catch( CannotConvertException& )
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() )
375 Reference< XIdlClass > xRetType = xMeth->getReturnType();
376 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
377 aRet.clear();
378 convertToEventReturn( aRet, aRetType );
382 return aRet;
385 //========================================================================
386 // Methoden von XEventListener
387 void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
388 throw( RuntimeException )
390 // It is up to the container to release the object
394 //========================================================================
395 //========================================================================
396 //========================================================================
398 // Create-Methode fuer EventAttacherManager
399 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
400 const Reference< XMultiServiceFactory > & rSMgr )
401 throw( Exception )
403 return new ImplEventAttacherManager( rIntrospection, rSMgr );
406 // Create-Methode fuer EventAttacherManager
407 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XMultiServiceFactory > & rSMgr )
408 throw( Exception )
410 if ( rSMgr.is() )
412 Reference< XInterface > xIFace( rSMgr->createInstance( OUString::createFromAscii("com.sun.star.beans.Introspection") ) );
413 if ( xIFace.is() )
415 Reference< XIntrospection > xIntrospection( xIFace, UNO_QUERY);
416 return new ImplEventAttacherManager( xIntrospection, rSMgr );
420 return Reference< XEventAttacherManager >();
423 //-----------------------------------------------------------------------------
424 ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
425 const Reference< XMultiServiceFactory > rSMgr )
426 : aScriptListeners( aLock )
427 , mxSMgr( rSMgr )
428 , mxIntrospection( rIntrospection )
430 if ( rSMgr.is() )
432 Reference< XInterface > xIFace( rSMgr->createInstance( OUString::createFromAscii("com.sun.star.script.EventAttacher") ) );
433 if ( xIFace.is() )
435 xAttacher = Reference< XEventAttacher >::query( xIFace );
437 xIFace = rSMgr->createInstance( OUString::createFromAscii("com.sun.star.script.Converter") );
438 if ( xIFace.is() )
440 xConverter = Reference< XTypeConverter >::query( xIFace );
444 Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
445 if( xInit.is() )
447 Sequence< Any > Arguments( 1 );
448 Arguments[0] <<= rIntrospection;
449 xInit->initialize( Arguments );
453 //-----------------------------------------------------------------------------
454 ImplEventAttacherManager::~ImplEventAttacherManager()
458 Reference< XIdlReflection > ImplEventAttacherManager::getReflection() throw( Exception )
460 Guard< Mutex > aGuard( aLock );
461 // Haben wir den Service schon? Sonst anlegen
462 if( !mxCoreReflection.is() )
464 Reference< XInterface > xIFace( mxSMgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection") ) );
465 mxCoreReflection = Reference< XIdlReflection >( xIFace, UNO_QUERY);
467 return mxCoreReflection;
471 //-----------------------------------------------------------------------------
472 ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) )
474 if (_nIndex < 0)
475 throw IllegalArgumentException();
477 ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
478 for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
481 if( aIt == aIndex.end() )
482 throw IllegalArgumentException();
484 return aIt;
487 //-----------------------------------------------------------------------------
488 void detachAll_Impl
490 ImplEventAttacherManager * pMgr,
491 sal_Int32 nIdx,
492 ::std::deque< AttachedObject_Impl > & rList
495 ::std::deque< AttachedObject_Impl >::iterator aObjIt = rList.begin();
496 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = rList.end();
497 while( aObjIt != aObjEnd )
499 pMgr->detach( nIdx, (*aObjIt).xTarget );
500 aObjIt++;
504 //-----------------------------------------------------------------------------
505 void attachAll_Impl
507 ImplEventAttacherManager * pMgr,
508 sal_Int32 nIdx,
509 ::std::deque< AttachedObject_Impl > & rList
512 ::std::deque< AttachedObject_Impl >::iterator aObjIt = rList.begin();
513 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = rList.end();
514 while( aObjIt != aObjEnd )
516 pMgr->attach( nIdx, (*aObjIt).xTarget, (*aObjIt).aHelper );
517 aObjIt++;
521 //-----------------------------------------------------------------------------
522 //*** Methoden von XEventAttacherManager ***
523 void SAL_CALL ImplEventAttacherManager::registerScriptEvent
525 sal_Int32 nIndex,
526 const ScriptEventDescriptor& ScriptEvent
528 throw( IllegalArgumentException, RuntimeException )
530 Guard< Mutex > aGuard( aLock );
532 // Index pruefen und Array anpassen
533 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
535 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
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
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 )
554 // resize
555 sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
556 (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
557 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
559 Reference< XAllListener > xAll =
560 new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
563 pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
564 (*aObjIt).aHelper, ScriptEvent.ListenerType,
565 ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
567 catch( Exception& )
571 aObjIt++;
575 //-----------------------------------------------------------------------------
576 void SAL_CALL ImplEventAttacherManager::registerScriptEvents
578 sal_Int32 nIndex,
579 const Sequence< ScriptEventDescriptor >& ScriptEvents
581 throw( IllegalArgumentException, RuntimeException )
583 Guard< Mutex > aGuard( aLock );
585 // Index pruefen und Array anpassen
586 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
588 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
589 detachAll_Impl( this, nIndex, aList );
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 ] );
596 attachAll_Impl( this, nIndex, aList );
599 //-----------------------------------------------------------------------------
600 void SAL_CALL ImplEventAttacherManager::revokeScriptEvent
602 sal_Int32 nIndex,
603 const OUString& ListenerType,
604 const OUString& EventMethod,
605 const OUString& ToRemoveListenerParam
607 throw( IllegalArgumentException, RuntimeException )
609 Guard< Mutex > aGuard( aLock );
611 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
613 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
614 detachAll_Impl( this, nIndex, aList );
616 OUString aLstType = ListenerType;
617 const sal_Unicode * pLastDot = aLstType.getStr();
618 pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
619 if( pLastDot )
620 aLstType = pLastDot +1;
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 )
627 if( aLstType == (*aEvtIt).ListenerType
628 && EventMethod == (*aEvtIt).EventMethod
629 && ToRemoveListenerParam == (*aEvtIt).AddListenerParam )
631 (*aIt).aEventList.erase( aEvtIt );
632 break;
635 aEvtIt++;
637 #else
638 Sequence< ScriptEventDescriptor >& rEventList = (*aIt).aEventList;
640 ScriptEventDescriptor* pEventList = rEventList.getArray();
641 const ScriptEventDescriptor* pEventListEnd = pEventList + rEventList.getLength();
642 for( ; pEventList < pEventListEnd; ++pEventList )
644 if ( (aLstType == pEventList->ListenerType )
645 && (EventMethod == pEventList->EventMethod )
646 && (ToRemoveListenerParam == pEventList->AddListenerParam)
649 ScriptEventDescriptor* pMoveTo = pEventList;
650 const ScriptEventDescriptor* pMoveFrom = pMoveTo + 1;
651 while (pMoveFrom < pEventListEnd)
653 *pMoveTo++ = *pMoveFrom++;
655 rEventList.realloc( rEventList.getLength() - 1 );
656 break;
659 #endif
660 attachAll_Impl( this, nIndex, aList );
663 //-----------------------------------------------------------------------------
664 void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
665 throw( IllegalArgumentException, RuntimeException )
667 Guard< Mutex > aGuard( aLock );
668 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
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 );
680 //-----------------------------------------------------------------------------
681 void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
682 throw( IllegalArgumentException, RuntimeException )
684 Guard< Mutex > aGuard( aLock );
685 if( nIndex < 0 )
686 throw IllegalArgumentException();
688 // ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
689 // while( nIndex-- )
690 // aIt++;
692 if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
693 aIndex.resize(nIndex+1);
695 AttacherIndex_Impl aTmp;
696 aIndex.insert( aIndex.begin() + nIndex, aTmp );
699 //-----------------------------------------------------------------------------
700 void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
701 throw( IllegalArgumentException, RuntimeException )
703 Guard< Mutex > aGuard( aLock );
704 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
706 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
707 detachAll_Impl( this, nIndex, aList );
708 aIndex.erase( aIt );
711 //-----------------------------------------------------------------------------
712 Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
713 throw( IllegalArgumentException, RuntimeException )
715 Guard< Mutex > aGuard( aLock );
716 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
718 #ifdef DEQUE_OK
719 Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
720 ScriptEventDescriptor * pArray = aSeq.getArray();
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 )
727 pArray[i++] = *aEvtIt;
728 aEvtIt++;
730 return aSeq;
731 #else
732 return (*aIt).aEventList;
733 #endif
736 //-----------------------------------------------------------------------------
737 void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
738 throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException )
740 Guard< Mutex > aGuard( aLock );
741 if( nIndex < 0 || !xObject.is() )
742 throw IllegalArgumentException();
744 if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
746 // alte Dateien lesen
747 if( nVersion == 1 )
749 insertEntry( nIndex );
750 attach( nIndex, xObject, Helper );
751 return;
753 else
754 throw IllegalArgumentException();
757 ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
759 AttachedObject_Impl aTmp;
760 aTmp.xTarget = xObject;
761 aTmp.aHelper = Helper;
762 aCurrentPosition->aObjList.push_back( aTmp );
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();
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 )
779 Reference< XAllListener > xAll =
780 new AttacherAllListener_Impl( this, (*aEvtIt).ScriptType, (*aEvtIt).ScriptCode );
781 Reference< XEventListener > xAdapter;
784 xAdapter = xAttacher->attachSingleEventListener( rCurObj.xTarget, xAll,
785 rCurObj.aHelper, (*aEvtIt).ScriptType,
786 (*aEvtIt).AddListenerParam, (*aEvtIt).EventMethod );
788 catch( Exception& )
792 pArray[i++] = xAdapter;
793 aEvtIt++;
795 #else
796 sal_Int32 nLen = aCurrentPosition->aEventList.getLength();
797 ScriptEventDescriptor * pEL = aCurrentPosition->aEventList.getArray();
798 for(sal_Int32 i = 0; i < nLen; ++i )
800 Reference< XAllListener > xAll =
801 new AttacherAllListener_Impl( this, pEL[i].ScriptType, pEL[i].ScriptCode );
802 Reference< XEventListener > xAdapter;
805 xAdapter = xAttacher->attachSingleEventListener( rCurObj.xTarget, xAll,
806 rCurObj.aHelper, pEL[i].ListenerType,
807 pEL[i].AddListenerParam, pEL[i].EventMethod );
809 catch( Exception& )
813 pArray[i] = xAdapter;
815 #endif
818 //-----------------------------------------------------------------------------
819 void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
820 throw( IllegalArgumentException, RuntimeException )
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();
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 )
832 if( (*aObjIt).xTarget == xObject )
834 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
835 #ifdef DEQUE_OK
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 )
842 if( pArray[i].is() )
846 xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
847 (*aEvtIt).AddListenerParam, pArray[i] );
849 catch( Exception& )
853 i++;
854 aEvtIt++;
856 #else
857 sal_Int32 nLen = aCurrentPosition->aEventList.getLength();
858 ScriptEventDescriptor * pEL = aCurrentPosition->aEventList.getArray();
859 for( sal_Int32 i = 0; i < nLen; i++ )
861 if( pArray[i].is() )
865 xAttacher->removeListener( (*aObjIt).xTarget, pEL[i].ListenerType,
866 pEL[i].AddListenerParam, pArray[i] );
868 catch( Exception& )
873 #endif
874 aCurrentPosition->aObjList.erase( aObjIt );
875 break;
877 aObjIt++;
881 void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
882 throw( IllegalArgumentException, RuntimeException )
884 Guard< Mutex > aGuard( aLock );
885 aScriptListeners.addInterface( aListener );
888 void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
889 throw( IllegalArgumentException, RuntimeException )
891 Guard< Mutex > aGuard( aLock );
892 aScriptListeners.removeInterface( aListener );
896 // Methoden von XPersistObject
897 OUString SAL_CALL ImplEventAttacherManager::getServiceName(void)
898 throw( RuntimeException )
900 return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.script.EventAttacherManager") );
903 void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
904 throw( IOException, RuntimeException )
906 Guard< Mutex > aGuard( aLock );
907 // Ohne XMarkableStream laeuft nichts
908 Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
909 if( !xMarkStream.is() )
910 return;
912 // Version schreiben
913 OutStream->writeShort( 2 );
915 // Position fuer Laenge merken
916 sal_Int32 nObjLenMark = xMarkStream->createMark();
917 OutStream->writeLong( 0L );
919 OutStream->writeLong( aIndex.size() );
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 )
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 )
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 );
940 aEvtIt++;
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++ )
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 );
956 #endif
957 aIt++;
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 );
968 void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
969 throw( IOException, RuntimeException )
971 Guard< Mutex > aGuard( aLock );
972 // Ohne XMarkableStream laeuft nichts
973 Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
974 if( !xMarkStream.is() )
975 return;
977 // Version lesen
978 nVersion = InStream->readShort();
980 // Zunaechst kommen die Daten gemaess Version 1,
981 // muss auch bei hoeheren Versionen beibehalten werden
982 sal_Int32 nLen = InStream->readLong();
984 // Position fuer Vergleichszwecke
985 sal_Int32 nObjLenMark = xMarkStream->createMark();
987 // Anzahl der zu lesenden Sequences
988 sal_Int32 nItemCount = InStream->readLong();
990 for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
992 insertEntry( i );
993 // Laenge der Sequence lesen
994 sal_Int32 nSeqLen = InStream->readLong();
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++ )
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();
1008 registerScriptEvents( i, aSEDSeq );
1011 // Haben wir die angegebene Laenge gelesen?
1012 sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
1013 if( nRealLen != nLen )
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 )
1019 VOS_ENSHURE( sal_False, "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
1021 else
1023 // TODO: Pruefen, ob Zwischen-Speicherung der Daten sinnvoll sein koennte
1025 // Vorerst einfach nur Skippen
1026 sal_Int32 nSkipCount = nLen - nRealLen;
1027 InStream->skipBytes( nSkipCount );
1030 xMarkStream->jumpToFurthest();
1031 xMarkStream->deleteMark( nObjLenMark );
1034 } // namesapce comphelper