Bump version to 4.3-4
[LibreOffice.git] / comphelper / source / eventattachermgr / eventattachermgr.cxx
blobf28d6d383a285a54b047fc8717dbd312fd38712d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/mutex.hxx>
21 #include <osl/diagnose.h>
22 #include <comphelper/eventattachermgr.hxx>
23 #include <comphelper/processfactory.hxx>
24 #include <com/sun/star/beans/theIntrospection.hpp>
25 #include <com/sun/star/io/XObjectInputStream.hpp>
26 #include <com/sun/star/io/XPersistObject.hpp>
27 #include <com/sun/star/io/XObjectOutputStream.hpp>
28 #include <com/sun/star/io/XMarkableStream.hpp>
29 #include <com/sun/star/lang/XInitialization.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/reflection/theCoreReflection.hpp>
32 #include <com/sun/star/reflection/XIdlClass.hpp>
33 #include <com/sun/star/reflection/XIdlReflection.hpp>
34 #include <com/sun/star/reflection/XIdlMethod.hpp>
35 #include <com/sun/star/script/Converter.hpp>
36 #include <com/sun/star/script/XEngineListener.hpp>
37 #include <com/sun/star/script/XEventAttacher2.hpp>
38 #include <com/sun/star/script/XEventAttacherManager.hpp>
39 #include <com/sun/star/script/XScriptListener.hpp>
40 #include <cppuhelper/weak.hxx>
41 #include <cppuhelper/interfacecontainer.hxx>
42 #include <cppuhelper/implbase1.hxx>
43 #include <cppuhelper/implbase2.hxx>
45 #include <deque>
46 #include <algorithm>
47 #include <functional>
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::io;
51 using namespace com::sun::star::lang;
52 using namespace com::sun::star::beans;
53 using namespace com::sun::star::script;
54 using namespace com::sun::star::reflection;
55 using namespace cppu;
56 using namespace osl;
59 namespace comphelper
63 struct AttachedObject_Impl
65 Reference< XInterface > xTarget;
66 Sequence< Reference< XEventListener > > aAttachedListenerSeq;
67 Any aHelper;
70 struct AttacherIndex_Impl
72 ::std::deque< ScriptEventDescriptor > aEventList;
73 ::std::deque< AttachedObject_Impl > aObjList;
77 class ImplEventAttacherManager
78 : public WeakImplHelper2< XEventAttacherManager, XPersistObject >
80 friend class AttacherAllListener_Impl;
81 ::std::deque< AttacherIndex_Impl > aIndex;
82 Mutex aLock;
83 // Container for the ScriptListener
84 OInterfaceContainerHelper aScriptListeners;
85 // Instance of EventAttacher
86 Reference< XEventAttacher2 > xAttacher;
87 Reference< XComponentContext > mxContext;
88 Reference< XIdlReflection > mxCoreReflection;
89 Reference< XIntrospection > mxIntrospection;
90 Reference< XTypeConverter > xConverter;
91 sal_Int16 nVersion;
92 public:
93 ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
94 const Reference< XComponentContext > xContext );
95 virtual ~ImplEventAttacherManager();
97 // Methods of XEventAttacherManager
98 virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent)
99 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
100 virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents)
101 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
102 virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam)
103 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
104 virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index)
105 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
106 virtual void SAL_CALL insertEntry(sal_Int32 Index)
107 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
108 virtual void SAL_CALL removeEntry(sal_Int32 Index)
109 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
110 virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index)
111 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
112 virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper)
113 throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException, std::exception ) SAL_OVERRIDE;
114 virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
115 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
116 virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener)
117 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
118 virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener)
119 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
121 // Methods of XPersistObject
122 virtual OUString SAL_CALL getServiceName(void) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
123 virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream) throw( IOException, RuntimeException, std::exception ) SAL_OVERRIDE;
124 virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) throw( IOException, RuntimeException, std::exception ) SAL_OVERRIDE;
126 private:
127 Reference< XIdlReflection > getReflection() throw( Exception );
129 /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
130 @param _nIndex
131 the index to check
132 @return
133 the iterator pointing to the position indicated by the index
135 ::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) );
143 // Implementation of an EventAttacher-subclass 'AllListeners', which
144 // only passes individual events of the general AllListeners.
145 class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener >
147 ImplEventAttacherManager* mpManager;
148 Reference< XEventAttacherManager > xManager;
149 OUString aScriptType;
150 OUString aScriptCode;
152 void convertToEventReturn( Any & rRet, const Type & rRetType )
153 throw( CannotConvertException );
154 public:
155 AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_,
156 const OUString & rScriptCode_ );
158 // Methods of XAllListener
159 virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
160 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
162 // Methods of XEventListener
163 virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
167 AttacherAllListener_Impl::AttacherAllListener_Impl
169 ImplEventAttacherManager* pManager_,
170 const OUString & rScriptType_,
171 const OUString & rScriptCode_
173 : mpManager( pManager_ )
174 , xManager( pManager_ )
175 , aScriptType( rScriptType_ )
176 , aScriptCode( rScriptCode_ )
182 // Methods of XAllListener
183 void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
184 throw( RuntimeException, std::exception )
186 ScriptEvent aScriptEvent;
187 aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface
188 aScriptEvent.ListenerType = Event.ListenerType;
189 aScriptEvent.MethodName = Event.MethodName;
190 aScriptEvent.Arguments = Event.Arguments;
191 aScriptEvent.Helper = Event.Helper;
192 aScriptEvent.ScriptType = aScriptType;
193 aScriptEvent.ScriptCode = aScriptCode;
195 // Iterate over all listeners and pass events.
196 OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
197 while( aIt.hasMoreElements() )
198 ((XScriptListener *)aIt.next())->firing( aScriptEvent );
202 // Convert to the standard event return
203 void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
204 throw( CannotConvertException )
206 // no return value? Set to the specified values
207 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
209 switch( rRetType.getTypeClass() )
211 case TypeClass_INTERFACE:
213 rRet <<= Reference< XInterface >();
215 break;
217 case TypeClass_BOOLEAN:
218 rRet <<= sal_True;
219 break;
221 case TypeClass_STRING:
222 rRet <<= OUString();
223 break;
225 case TypeClass_FLOAT: rRet <<= float(0); break;
226 case TypeClass_DOUBLE: rRet <<= double(0.0); break;
227 case TypeClass_BYTE: rRet <<= sal_uInt8(0); break;
228 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
229 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
230 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
231 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
233 default:
234 OSL_ASSERT(false);
235 break;
238 else if( !rRet.getValueType().equals( rRetType ) )
240 if( mpManager->xConverter.is() )
241 rRet = mpManager->xConverter->convertTo( rRet, rRetType );
242 else
243 throw CannotConvertException();
248 // Methods of XAllListener
249 Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event )
250 throw( InvocationTargetException, RuntimeException, std::exception )
252 ScriptEvent aScriptEvent;
253 aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface
254 aScriptEvent.ListenerType = Event.ListenerType;
255 aScriptEvent.MethodName = Event.MethodName;
256 aScriptEvent.Arguments = Event.Arguments;
257 aScriptEvent.Helper = Event.Helper;
258 aScriptEvent.ScriptType = aScriptType;
259 aScriptEvent.ScriptCode = aScriptCode;
261 Any aRet;
262 // Iterate over all listeners and pass events.
263 OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
264 while( aIt.hasMoreElements() )
266 aRet = ((XScriptListener *)aIt.next())->approveFiring( aScriptEvent );
269 Reference< XIdlClass > xListenerType = mpManager->getReflection()->
270 forName( Event.ListenerType.getTypeName() );
271 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
272 if( xMeth.is() )
274 Reference< XIdlClass > xRetType = xMeth->getReturnType();
275 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
276 convertToEventReturn( aRet, aRetType );
279 switch( aRet.getValueType().getTypeClass() )
281 case TypeClass_INTERFACE:
283 // Interface not null, return
284 Reference< XInterface > x;
285 aRet >>= x;
286 if( x.is() )
287 return aRet;
289 break;
291 case TypeClass_BOOLEAN:
292 // FALSE -> Return
293 if( !(*(sal_Bool*)aRet.getValue()) )
294 return aRet;
295 break;
297 case TypeClass_STRING:
298 // none empty string -> return
299 if( !((OUString*)aRet.getValue())->isEmpty() )
300 return aRet;
301 break;
303 // none zero number -> return
304 case TypeClass_FLOAT: if( *((float*)aRet.getValue()) ) return aRet; break;
305 case TypeClass_DOUBLE: if( *((double*)aRet.getValue()) ) return aRet; break;
306 case TypeClass_BYTE: if( *((sal_uInt8*)aRet.getValue()) ) return aRet; break;
307 case TypeClass_SHORT: if( *((sal_Int16*)aRet.getValue()) ) return aRet; break;
308 case TypeClass_LONG: if( *((sal_Int32*)aRet.getValue()) ) return aRet; break;
309 case TypeClass_UNSIGNED_SHORT: if( *((sal_uInt16*)aRet.getValue()) ) return aRet; break;
310 case TypeClass_UNSIGNED_LONG: if( *((sal_uInt32*)aRet.getValue()) ) return aRet; break;
312 default:
313 OSL_ASSERT(false);
314 break;
317 catch( CannotConvertException& )
319 // silent ignore conversions errors from a script call
320 Reference< XIdlClass > xListenerType = mpManager->getReflection()->
321 forName( Event.ListenerType.getTypeName() );
322 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
323 if( xMeth.is() )
325 Reference< XIdlClass > xRetType = xMeth->getReturnType();
326 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
327 aRet.clear();
328 convertToEventReturn( aRet, aRetType );
332 return aRet;
336 // Methods of XEventListener
337 void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
338 throw( RuntimeException, std::exception )
340 // It is up to the container to release the object
344 // Constructor method for EventAttacherManager
345 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XComponentContext > & rxContext )
346 throw( Exception )
348 Reference< XIntrospection > xIntrospection = theIntrospection::get( rxContext );
349 return new ImplEventAttacherManager( xIntrospection, rxContext );
353 ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
354 const Reference< XComponentContext > xContext )
355 : aScriptListeners( aLock )
356 , mxContext( xContext )
357 , mxIntrospection( rIntrospection )
358 , nVersion(0)
360 if ( xContext.is() )
362 Reference< XInterface > xIFace( xContext->getServiceManager()->createInstanceWithContext(
363 OUString( "com.sun.star.script.EventAttacher" ), xContext) );
364 if ( xIFace.is() )
366 xAttacher = Reference< XEventAttacher2 >::query( xIFace );
368 xConverter = Converter::create(xContext);
371 Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
372 if( xInit.is() )
374 Sequence< Any > Arguments( 1 );
375 Arguments[0] <<= rIntrospection;
376 xInit->initialize( Arguments );
381 ImplEventAttacherManager::~ImplEventAttacherManager()
385 Reference< XIdlReflection > ImplEventAttacherManager::getReflection() throw( Exception )
387 Guard< Mutex > aGuard( aLock );
388 // Do we already have a service? If not, create one.
389 if( !mxCoreReflection.is() )
391 mxCoreReflection = theCoreReflection::get(mxContext);
393 return mxCoreReflection;
398 ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) )
400 if (_nIndex < 0)
401 throw IllegalArgumentException();
403 ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
404 for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
407 if( aIt == aIndex.end() )
408 throw IllegalArgumentException();
410 return aIt;
413 namespace {
415 class DetachObject : public std::unary_function<AttachedObject_Impl, void>
417 ImplEventAttacherManager& mrMgr;
418 sal_Int32 mnIdx;
419 public:
420 DetachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
421 mrMgr(rMgr), mnIdx(nIdx) {}
423 void operator() (AttachedObject_Impl& rObj)
425 mrMgr.detach(mnIdx, rObj.xTarget);
429 class AttachObject : public std::unary_function<AttachedObject_Impl, void>
431 ImplEventAttacherManager& mrMgr;
432 sal_Int32 mnIdx;
433 public:
434 AttachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
435 mrMgr(rMgr), mnIdx(nIdx) {}
437 void operator() (AttachedObject_Impl& rObj)
439 mrMgr.attach(mnIdx, rObj.xTarget, rObj.aHelper);
446 // Methods of XEventAttacherManager
447 void SAL_CALL ImplEventAttacherManager::registerScriptEvent
449 sal_Int32 nIndex,
450 const ScriptEventDescriptor& ScriptEvent
452 throw( IllegalArgumentException, RuntimeException, std::exception )
454 Guard< Mutex > aGuard( aLock );
456 // Examine the index and apply the array
457 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
459 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
461 ScriptEventDescriptor aEvt = ScriptEvent;
462 sal_Int32 nLastDot = aEvt.ListenerType.lastIndexOf('.');
463 if (nLastDot != -1)
464 aEvt.ListenerType = aEvt.ListenerType.copy(nLastDot+1);
465 (*aIt).aEventList.push_back( aEvt );
467 // register new new Event
468 ::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.begin();
469 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end();
470 while( aObjIt != aObjEnd )
472 // resize
473 sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
474 (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
475 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
477 Reference< XAllListener > xAll =
478 new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
481 pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
482 (*aObjIt).aHelper, ScriptEvent.ListenerType,
483 ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
485 catch( Exception& )
489 ++aObjIt;
494 void SAL_CALL ImplEventAttacherManager::registerScriptEvents
496 sal_Int32 nIndex,
497 const Sequence< ScriptEventDescriptor >& ScriptEvents
499 throw( IllegalArgumentException, RuntimeException, std::exception )
501 Guard< Mutex > aGuard( aLock );
503 // Examine the index and apply the array
504 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
506 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
507 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
509 const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
510 sal_Int32 nLen = ScriptEvents.getLength();
511 for( sal_Int32 i = 0 ; i < nLen ; i++ )
512 registerScriptEvent( nIndex, pArray[ i ] );
514 ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
518 void SAL_CALL ImplEventAttacherManager::revokeScriptEvent
520 sal_Int32 nIndex,
521 const OUString& ListenerType,
522 const OUString& EventMethod,
523 const OUString& ToRemoveListenerParam
525 throw( IllegalArgumentException, RuntimeException, std::exception )
527 Guard< Mutex > aGuard( aLock );
529 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
531 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
532 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
534 OUString aLstType = ListenerType;
535 sal_Int32 nLastDot = aLstType.lastIndexOf('.');
536 if (nLastDot != -1)
537 aLstType = aLstType.copy(nLastDot+1);
539 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
540 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
541 while( aEvtIt != aEvtEnd )
543 if( aLstType == (*aEvtIt).ListenerType
544 && EventMethod == (*aEvtIt).EventMethod
545 && ToRemoveListenerParam == (*aEvtIt).AddListenerParam )
547 (*aIt).aEventList.erase( aEvtIt );
548 break;
551 ++aEvtIt;
553 ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
557 void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
558 throw( IllegalArgumentException, RuntimeException, std::exception )
560 Guard< Mutex > aGuard( aLock );
561 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
563 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
564 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
565 (*aIt).aEventList.clear();
566 ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
570 void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
571 throw( IllegalArgumentException, RuntimeException, std::exception )
573 Guard< Mutex > aGuard( aLock );
574 if( nIndex < 0 )
575 throw IllegalArgumentException();
577 if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
578 aIndex.resize(nIndex+1);
580 AttacherIndex_Impl aTmp;
581 aIndex.insert( aIndex.begin() + nIndex, aTmp );
585 void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
586 throw( IllegalArgumentException, RuntimeException, std::exception )
588 Guard< Mutex > aGuard( aLock );
589 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
591 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
592 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
593 aIndex.erase( aIt );
597 Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
598 throw( IllegalArgumentException, RuntimeException, std::exception )
600 Guard< Mutex > aGuard( aLock );
601 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
603 Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
604 ScriptEventDescriptor * pArray = aSeq.getArray();
606 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
607 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
608 sal_Int32 i = 0;
609 while( aEvtIt != aEvtEnd )
611 pArray[i++] = *aEvtIt;
612 ++aEvtIt;
614 return aSeq;
618 void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
619 throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException, std::exception )
621 Guard< Mutex > aGuard( aLock );
622 if( nIndex < 0 || !xObject.is() )
623 throw IllegalArgumentException();
625 if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
627 // read older files
628 if( nVersion == 1 )
630 insertEntry( nIndex );
631 attach( nIndex, xObject, Helper );
632 return;
634 else
635 throw IllegalArgumentException();
638 ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
640 AttachedObject_Impl aTmp;
641 aTmp.xTarget = xObject;
642 aTmp.aHelper = Helper;
643 aCurrentPosition->aObjList.push_back( aTmp );
645 //::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back();
646 AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
647 rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
649 if (aCurrentPosition->aEventList.empty())
650 return;
652 Sequence<com::sun::star::script::EventListener> aEvents(aCurrentPosition->aEventList.size());
653 std::deque<ScriptEventDescriptor>::iterator itr = aCurrentPosition->aEventList.begin();
654 std::deque<ScriptEventDescriptor>::iterator itrEnd = aCurrentPosition->aEventList.end();
655 ::com::sun::star::script::EventListener* p = aEvents.getArray();
656 size_t i = 0;
657 for (; itr != itrEnd; ++itr)
659 com::sun::star::script::EventListener aListener;
660 aListener.AllListener =
661 new AttacherAllListener_Impl(this, itr->ScriptType, itr->ScriptCode);
662 aListener.Helper = rCurObj.aHelper;
663 aListener.ListenerType = itr->ListenerType;
664 aListener.EventMethod = itr->EventMethod;
665 aListener.AddListenerParam = itr->AddListenerParam;
666 p[i++] = aListener;
671 rCurObj.aAttachedListenerSeq =
672 xAttacher->attachMultipleEventListeners(rCurObj.xTarget, aEvents);
674 catch (const Exception&)
676 // Fail gracefully.
681 void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
682 throw( IllegalArgumentException, RuntimeException, std::exception )
684 Guard< Mutex > aGuard( aLock );
685 //return;
686 if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
687 throw IllegalArgumentException();
689 ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
690 ::std::deque< AttachedObject_Impl >::iterator aObjIt = aCurrentPosition->aObjList.begin();
691 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end();
692 while( aObjIt != aObjEnd )
694 if( (*aObjIt).xTarget == xObject )
696 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
698 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
699 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
700 sal_Int32 i = 0;
701 while( aEvtIt != aEvtEnd )
703 if( pArray[i].is() )
707 xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
708 (*aEvtIt).AddListenerParam, pArray[i] );
710 catch( Exception& )
714 i++;
715 ++aEvtIt;
717 aCurrentPosition->aObjList.erase( aObjIt );
718 break;
720 ++aObjIt;
724 void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
725 throw( IllegalArgumentException, RuntimeException, std::exception )
727 Guard< Mutex > aGuard( aLock );
728 aScriptListeners.addInterface( aListener );
731 void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
732 throw( IllegalArgumentException, RuntimeException, std::exception )
734 Guard< Mutex > aGuard( aLock );
735 aScriptListeners.removeInterface( aListener );
739 // Methods of XPersistObject
740 OUString SAL_CALL ImplEventAttacherManager::getServiceName(void)
741 throw( RuntimeException, std::exception )
743 return OUString( "com.sun.star.uno.script.EventAttacherManager" );
746 void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
747 throw( IOException, RuntimeException, std::exception )
749 Guard< Mutex > aGuard( aLock );
750 // Don't run without XMarkableStream
751 Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
752 if( !xMarkStream.is() )
753 return;
755 // Write out the version
756 OutStream->writeShort( 2 );
758 // Remember position for length
759 sal_Int32 nObjLenMark = xMarkStream->createMark();
760 OutStream->writeLong( 0L );
762 OutStream->writeLong( aIndex.size() );
764 // Write out sequences
765 ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
766 ::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end();
767 while( aIt != aEnd )
769 // Write out the length of the sequence and all descriptions
770 OutStream->writeLong( (*aIt).aEventList.size() );
771 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
772 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
773 while( aEvtIt != aEvtEnd )
775 const ScriptEventDescriptor& rDesc = (*aEvtIt);
776 OutStream->writeUTF( rDesc.ListenerType );
777 OutStream->writeUTF( rDesc.EventMethod );
778 OutStream->writeUTF( rDesc.AddListenerParam );
779 OutStream->writeUTF( rDesc.ScriptType );
780 OutStream->writeUTF( rDesc.ScriptCode );
782 ++aEvtIt;
784 ++aIt;
787 // The length is now known
788 sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
789 xMarkStream->jumpToMark( nObjLenMark );
790 OutStream->writeLong( nObjLen );
791 xMarkStream->jumpToFurthest();
792 xMarkStream->deleteMark( nObjLenMark );
795 void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
796 throw( IOException, RuntimeException, std::exception )
798 Guard< Mutex > aGuard( aLock );
799 // Don't run without XMarkableStream
800 Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
801 if( !xMarkStream.is() )
802 return;
804 // Read in the version
805 nVersion = InStream->readShort();
807 // At first there's the data according to version 1 --
808 // this part needs to be kept in later versions.
809 sal_Int32 nLen = InStream->readLong();
811 // Position for comparative purposes
812 sal_Int32 nObjLenMark = xMarkStream->createMark();
814 // Number of read sequences
815 sal_Int32 nItemCount = InStream->readLong();
817 for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
819 insertEntry( i );
820 // Read the length of the sequence
821 sal_Int32 nSeqLen = InStream->readLong();
823 // Display the sequences and read the descriptions
824 Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
825 ScriptEventDescriptor* pArray = aSEDSeq.getArray();
826 for( sal_Int32 j = 0 ; j < nSeqLen ; j++ )
828 ScriptEventDescriptor& rDesc = pArray[ j ];
829 rDesc.ListenerType = InStream->readUTF();
830 rDesc.EventMethod = InStream->readUTF();
831 rDesc.AddListenerParam = InStream->readUTF();
832 rDesc.ScriptType = InStream->readUTF();
833 rDesc.ScriptCode = InStream->readUTF();
835 registerScriptEvents( i, aSEDSeq );
838 // Have we read the specified length?
839 sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
840 if( nRealLen != nLen )
842 // Only if the StreamVersion is > 1 and the date still follows, can
843 // this be true. Otherwise, something is completely gone.
844 if( nRealLen > nLen || nVersion == 1 )
846 OSL_FAIL( "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
848 else
849 { // TODO: Examine if caching the dates would be useful
850 // But for now, it's easier to skip it.
851 sal_Int32 nSkipCount = nLen - nRealLen;
852 InStream->skipBytes( nSkipCount );
855 xMarkStream->jumpToFurthest();
856 xMarkStream->deleteMark( nObjLenMark );
859 } // namesapce comphelper
862 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */