bump product version to 5.0.4.1
[LibreOffice.git] / comphelper / source / eventattachermgr / eventattachermgr.cxx
blob279f18d0ce6e92ac5cab80f85a3249907c3db593
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/WrappedTargetRuntimeException.hpp>
30 #include <com/sun/star/lang/XInitialization.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/reflection/theCoreReflection.hpp>
33 #include <com/sun/star/reflection/XIdlClass.hpp>
34 #include <com/sun/star/reflection/XIdlReflection.hpp>
35 #include <com/sun/star/reflection/XIdlMethod.hpp>
36 #include <com/sun/star/script/Converter.hpp>
37 #include <com/sun/star/script/XEngineListener.hpp>
38 #include <com/sun/star/script/XEventAttacher2.hpp>
39 #include <com/sun/star/script/XEventAttacherManager.hpp>
40 #include <com/sun/star/script/XScriptListener.hpp>
41 #include <cppuhelper/weak.hxx>
42 #include <cppuhelper/interfacecontainer.hxx>
43 #include <cppuhelper/implbase1.hxx>
44 #include <cppuhelper/implbase2.hxx>
46 #include <deque>
47 #include <algorithm>
48 #include <functional>
50 using namespace com::sun::star::uno;
51 using namespace com::sun::star::io;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::beans;
54 using namespace com::sun::star::script;
55 using namespace com::sun::star::reflection;
56 using namespace cppu;
57 using namespace osl;
60 namespace comphelper
64 struct AttachedObject_Impl
66 Reference< XInterface > xTarget;
67 Sequence< Reference< XEventListener > > aAttachedListenerSeq;
68 Any aHelper;
71 struct AttacherIndex_Impl
73 ::std::deque< ScriptEventDescriptor > aEventList;
74 ::std::deque< AttachedObject_Impl > aObjList;
78 class ImplEventAttacherManager
79 : public WeakImplHelper2< XEventAttacherManager, XPersistObject >
81 friend class AttacherAllListener_Impl;
82 ::std::deque< AttacherIndex_Impl > aIndex;
83 Mutex aLock;
84 // Container for the ScriptListener
85 OInterfaceContainerHelper aScriptListeners;
86 // Instance of EventAttacher
87 Reference< XEventAttacher2 > xAttacher;
88 Reference< XComponentContext > mxContext;
89 Reference< XIdlReflection > mxCoreReflection;
90 Reference< XIntrospection > mxIntrospection;
91 Reference< XTypeConverter > xConverter;
92 sal_Int16 nVersion;
93 public:
94 ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
95 const Reference< XComponentContext >& rContext );
96 virtual ~ImplEventAttacherManager();
98 // Methods of XEventAttacherManager
99 virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent)
100 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
101 virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents)
102 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
103 virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam)
104 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
105 virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index)
106 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
107 virtual void SAL_CALL insertEntry(sal_Int32 Index)
108 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
109 virtual void SAL_CALL removeEntry(sal_Int32 Index)
110 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
111 virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index)
112 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
113 virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper)
114 throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException, std::exception ) SAL_OVERRIDE;
115 virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
116 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
117 virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener)
118 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
119 virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener)
120 throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
122 // Methods of XPersistObject
123 virtual OUString SAL_CALL getServiceName() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
124 virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream) throw( IOException, RuntimeException, std::exception ) SAL_OVERRIDE;
125 virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) throw( IOException, RuntimeException, std::exception ) SAL_OVERRIDE;
127 private:
128 Reference< XIdlReflection > getReflection() throw( Exception );
130 /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
131 @param _nIndex
132 the index to check
133 @return
134 the iterator pointing to the position indicated by the index
136 ::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex );
144 // Implementation of an EventAttacher-subclass 'AllListeners', which
145 // only passes individual events of the general AllListeners.
146 class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener >
148 ImplEventAttacherManager* mpManager;
149 Reference< XEventAttacherManager > xManager;
150 OUString aScriptType;
151 OUString aScriptCode;
153 void convertToEventReturn( Any & rRet, const Type & rRetType )
154 throw( CannotConvertException );
155 public:
156 AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_,
157 const OUString & rScriptCode_ );
159 // Methods of XAllListener
160 virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
161 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
163 // Methods of XEventListener
164 virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
168 AttacherAllListener_Impl::AttacherAllListener_Impl
170 ImplEventAttacherManager* pManager_,
171 const OUString & rScriptType_,
172 const OUString & rScriptCode_
174 : mpManager( pManager_ )
175 , xManager( pManager_ )
176 , aScriptType( rScriptType_ )
177 , aScriptCode( rScriptCode_ )
183 // Methods of XAllListener
184 void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
185 throw( RuntimeException, std::exception )
187 ScriptEvent aScriptEvent;
188 aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface
189 aScriptEvent.ListenerType = Event.ListenerType;
190 aScriptEvent.MethodName = Event.MethodName;
191 aScriptEvent.Arguments = Event.Arguments;
192 aScriptEvent.Helper = Event.Helper;
193 aScriptEvent.ScriptType = aScriptType;
194 aScriptEvent.ScriptCode = aScriptCode;
196 // Iterate over all listeners and pass events.
197 OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
198 while( aIt.hasMoreElements() )
199 static_cast<XScriptListener *>(aIt.next())->firing( aScriptEvent );
203 // Convert to the standard event return
204 void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
205 throw( CannotConvertException )
207 // no return value? Set to the specified values
208 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
210 switch( rRetType.getTypeClass() )
212 case TypeClass_INTERFACE:
214 rRet <<= Reference< XInterface >();
216 break;
218 case TypeClass_BOOLEAN:
219 rRet <<= sal_True;
220 break;
222 case TypeClass_STRING:
223 rRet <<= OUString();
224 break;
226 case TypeClass_FLOAT: rRet <<= float(0); break;
227 case TypeClass_DOUBLE: rRet <<= double(0.0); break;
228 case TypeClass_BYTE: rRet <<= sal_uInt8(0); break;
229 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
230 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
231 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
232 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
234 default:
235 OSL_ASSERT(false);
236 break;
239 else if( !rRet.getValueType().equals( rRetType ) )
241 if( mpManager->xConverter.is() )
242 rRet = mpManager->xConverter->convertTo( rRet, rRetType );
243 else
244 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 = static_cast<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( !(*static_cast<sal_Bool const *>(aRet.getValue())) )
294 return aRet;
295 break;
297 case TypeClass_STRING:
298 // none empty string -> return
299 if( !(static_cast<OUString const *>(aRet.getValue()))->isEmpty() )
300 return aRet;
301 break;
303 // none zero number -> return
304 case TypeClass_FLOAT: if( *static_cast<float const *>(aRet.getValue()) ) return aRet; break;
305 case TypeClass_DOUBLE: if( *static_cast<double const *>(aRet.getValue()) ) return aRet; break;
306 case TypeClass_BYTE: if( *static_cast<sal_uInt8 const *>(aRet.getValue()) ) return aRet; break;
307 case TypeClass_SHORT: if( *static_cast<sal_Int16 const *>(aRet.getValue()) ) return aRet; break;
308 case TypeClass_LONG: if( *static_cast<sal_Int32 const *>(aRet.getValue()) ) return aRet; break;
309 case TypeClass_UNSIGNED_SHORT: if( *static_cast<sal_uInt16 const *>(aRet.getValue()) ) return aRet; break;
310 case TypeClass_UNSIGNED_LONG: if( *static_cast<sal_uInt32 const *>(aRet.getValue()) ) return aRet; break;
312 default:
313 OSL_ASSERT(false);
314 break;
317 catch (const 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();
330 convertToEventReturn( aRet, aRetType );
332 catch (const CannotConvertException& e)
334 throw css::lang::WrappedTargetRuntimeException(
335 "wrapped CannotConvertException " + e.Message,
336 css::uno::Reference<css::uno::XInterface>(), makeAny(e));
341 return aRet;
344 // Methods of XEventListener
345 void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
346 throw( RuntimeException, std::exception )
348 // It is up to the container to release the object
351 // Constructor method for EventAttacherManager
352 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XComponentContext > & rxContext )
353 throw( Exception )
355 Reference< XIntrospection > xIntrospection = theIntrospection::get( rxContext );
356 return new ImplEventAttacherManager( xIntrospection, rxContext );
360 ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
361 const Reference< XComponentContext >& rContext )
362 : aScriptListeners( aLock )
363 , mxContext( rContext )
364 , mxIntrospection( rIntrospection )
365 , nVersion(0)
367 if ( rContext.is() )
369 Reference< XInterface > xIFace( rContext->getServiceManager()->createInstanceWithContext(
370 OUString( "com.sun.star.script.EventAttacher" ), rContext) );
371 if ( xIFace.is() )
373 xAttacher = Reference< XEventAttacher2 >::query( xIFace );
375 xConverter = Converter::create(rContext);
378 Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
379 if( xInit.is() )
381 Sequence< Any > Arguments( 1 );
382 Arguments[0] <<= rIntrospection;
383 xInit->initialize( Arguments );
388 ImplEventAttacherManager::~ImplEventAttacherManager()
392 Reference< XIdlReflection > ImplEventAttacherManager::getReflection() throw( Exception )
394 Guard< Mutex > aGuard( aLock );
395 // Do we already have a service? If not, create one.
396 if( !mxCoreReflection.is() )
398 mxCoreReflection = theCoreReflection::get(mxContext);
400 return mxCoreReflection;
405 ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex )
407 if (_nIndex < 0)
408 throw IllegalArgumentException();
410 ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
411 for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
414 if( aIt == aIndex.end() )
415 throw IllegalArgumentException();
417 return aIt;
420 namespace {
422 class DetachObject : public std::unary_function<AttachedObject_Impl, void>
424 ImplEventAttacherManager& mrMgr;
425 sal_Int32 mnIdx;
426 public:
427 DetachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
428 mrMgr(rMgr), mnIdx(nIdx) {}
430 void operator() (AttachedObject_Impl& rObj)
432 mrMgr.detach(mnIdx, rObj.xTarget);
436 class AttachObject : public std::unary_function<AttachedObject_Impl, void>
438 ImplEventAttacherManager& mrMgr;
439 sal_Int32 mnIdx;
440 public:
441 AttachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
442 mrMgr(rMgr), mnIdx(nIdx) {}
444 void operator() (AttachedObject_Impl& rObj)
446 mrMgr.attach(mnIdx, rObj.xTarget, rObj.aHelper);
453 // Methods of XEventAttacherManager
454 void SAL_CALL ImplEventAttacherManager::registerScriptEvent
456 sal_Int32 nIndex,
457 const ScriptEventDescriptor& ScriptEvent
459 throw( IllegalArgumentException, RuntimeException, std::exception )
461 Guard< Mutex > aGuard( aLock );
463 // Examine the index and apply the array
464 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
466 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
468 ScriptEventDescriptor aEvt = ScriptEvent;
469 sal_Int32 nLastDot = aEvt.ListenerType.lastIndexOf('.');
470 if (nLastDot != -1)
471 aEvt.ListenerType = aEvt.ListenerType.copy(nLastDot+1);
472 (*aIt).aEventList.push_back( aEvt );
474 // register new new Event
475 ::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.begin();
476 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end();
477 while( aObjIt != aObjEnd )
479 // resize
480 sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
481 (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
482 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
484 Reference< XAllListener > xAll =
485 new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
488 pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
489 (*aObjIt).aHelper, ScriptEvent.ListenerType,
490 ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
492 catch( Exception& )
496 ++aObjIt;
501 void SAL_CALL ImplEventAttacherManager::registerScriptEvents
503 sal_Int32 nIndex,
504 const Sequence< ScriptEventDescriptor >& ScriptEvents
506 throw( IllegalArgumentException, RuntimeException, std::exception )
508 Guard< Mutex > aGuard( aLock );
510 // Examine the index and apply the array
511 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
513 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
514 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
516 const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
517 sal_Int32 nLen = ScriptEvents.getLength();
518 for( sal_Int32 i = 0 ; i < nLen ; i++ )
519 registerScriptEvent( nIndex, pArray[ i ] );
521 ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
525 void SAL_CALL ImplEventAttacherManager::revokeScriptEvent
527 sal_Int32 nIndex,
528 const OUString& ListenerType,
529 const OUString& EventMethod,
530 const OUString& ToRemoveListenerParam
532 throw( IllegalArgumentException, RuntimeException, std::exception )
534 Guard< Mutex > aGuard( aLock );
536 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
538 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
539 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
541 OUString aLstType = ListenerType;
542 sal_Int32 nLastDot = aLstType.lastIndexOf('.');
543 if (nLastDot != -1)
544 aLstType = aLstType.copy(nLastDot+1);
546 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
547 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
548 while( aEvtIt != aEvtEnd )
550 if( aLstType == (*aEvtIt).ListenerType
551 && EventMethod == (*aEvtIt).EventMethod
552 && ToRemoveListenerParam == (*aEvtIt).AddListenerParam )
554 (*aIt).aEventList.erase( aEvtIt );
555 break;
558 ++aEvtIt;
560 ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
564 void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
565 throw( IllegalArgumentException, RuntimeException, std::exception )
567 Guard< Mutex > aGuard( aLock );
568 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
570 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
571 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
572 (*aIt).aEventList.clear();
573 ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
577 void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
578 throw( IllegalArgumentException, RuntimeException, std::exception )
580 Guard< Mutex > aGuard( aLock );
581 if( nIndex < 0 )
582 throw IllegalArgumentException();
584 if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
585 aIndex.resize(nIndex+1);
587 AttacherIndex_Impl aTmp;
588 aIndex.insert( aIndex.begin() + nIndex, aTmp );
592 void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
593 throw( IllegalArgumentException, RuntimeException, std::exception )
595 Guard< Mutex > aGuard( aLock );
596 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
598 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
599 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
600 aIndex.erase( aIt );
604 Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
605 throw( IllegalArgumentException, RuntimeException, std::exception )
607 Guard< Mutex > aGuard( aLock );
608 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
610 Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
611 ScriptEventDescriptor * pArray = aSeq.getArray();
613 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
614 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
615 sal_Int32 i = 0;
616 while( aEvtIt != aEvtEnd )
618 pArray[i++] = *aEvtIt;
619 ++aEvtIt;
621 return aSeq;
625 void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
626 throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException, std::exception )
628 Guard< Mutex > aGuard( aLock );
629 if( nIndex < 0 || !xObject.is() )
630 throw IllegalArgumentException();
632 if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
634 // read older files
635 if( nVersion == 1 )
637 insertEntry( nIndex );
638 attach( nIndex, xObject, Helper );
639 return;
641 else
642 throw IllegalArgumentException();
645 ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
647 AttachedObject_Impl aTmp;
648 aTmp.xTarget = xObject;
649 aTmp.aHelper = Helper;
650 aCurrentPosition->aObjList.push_back( aTmp );
652 //::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back();
653 AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
654 rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
656 if (aCurrentPosition->aEventList.empty())
657 return;
659 Sequence<com::sun::star::script::EventListener> aEvents(aCurrentPosition->aEventList.size());
660 std::deque<ScriptEventDescriptor>::iterator itr = aCurrentPosition->aEventList.begin();
661 std::deque<ScriptEventDescriptor>::iterator itrEnd = aCurrentPosition->aEventList.end();
662 ::com::sun::star::script::EventListener* p = aEvents.getArray();
663 size_t i = 0;
664 for (; itr != itrEnd; ++itr)
666 com::sun::star::script::EventListener aListener;
667 aListener.AllListener =
668 new AttacherAllListener_Impl(this, itr->ScriptType, itr->ScriptCode);
669 aListener.Helper = rCurObj.aHelper;
670 aListener.ListenerType = itr->ListenerType;
671 aListener.EventMethod = itr->EventMethod;
672 aListener.AddListenerParam = itr->AddListenerParam;
673 p[i++] = aListener;
678 rCurObj.aAttachedListenerSeq =
679 xAttacher->attachMultipleEventListeners(rCurObj.xTarget, aEvents);
681 catch (const Exception&)
683 // Fail gracefully.
688 void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
689 throw( IllegalArgumentException, RuntimeException, std::exception )
691 Guard< Mutex > aGuard( aLock );
692 //return;
693 if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
694 throw IllegalArgumentException();
696 ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
697 ::std::deque< AttachedObject_Impl >::iterator aObjIt = aCurrentPosition->aObjList.begin();
698 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end();
699 while( aObjIt != aObjEnd )
701 if( (*aObjIt).xTarget == xObject )
703 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
705 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
706 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
707 sal_Int32 i = 0;
708 while( aEvtIt != aEvtEnd )
710 if( pArray[i].is() )
714 xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
715 (*aEvtIt).AddListenerParam, pArray[i] );
717 catch( Exception& )
721 i++;
722 ++aEvtIt;
724 aCurrentPosition->aObjList.erase( aObjIt );
725 break;
727 ++aObjIt;
731 void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
732 throw( IllegalArgumentException, RuntimeException, std::exception )
734 Guard< Mutex > aGuard( aLock );
735 aScriptListeners.addInterface( aListener );
738 void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
739 throw( IllegalArgumentException, RuntimeException, std::exception )
741 Guard< Mutex > aGuard( aLock );
742 aScriptListeners.removeInterface( aListener );
746 // Methods of XPersistObject
747 OUString SAL_CALL ImplEventAttacherManager::getServiceName()
748 throw( RuntimeException, std::exception )
750 return OUString( "com.sun.star.uno.script.EventAttacherManager" );
753 void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
754 throw( IOException, RuntimeException, std::exception )
756 Guard< Mutex > aGuard( aLock );
757 // Don't run without XMarkableStream
758 Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
759 if( !xMarkStream.is() )
760 return;
762 // Write out the version
763 OutStream->writeShort( 2 );
765 // Remember position for length
766 sal_Int32 nObjLenMark = xMarkStream->createMark();
767 OutStream->writeLong( 0L );
769 OutStream->writeLong( aIndex.size() );
771 // Write out sequences
772 ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
773 ::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end();
774 while( aIt != aEnd )
776 // Write out the length of the sequence and all descriptions
777 OutStream->writeLong( (*aIt).aEventList.size() );
778 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
779 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
780 while( aEvtIt != aEvtEnd )
782 const ScriptEventDescriptor& rDesc = (*aEvtIt);
783 OutStream->writeUTF( rDesc.ListenerType );
784 OutStream->writeUTF( rDesc.EventMethod );
785 OutStream->writeUTF( rDesc.AddListenerParam );
786 OutStream->writeUTF( rDesc.ScriptType );
787 OutStream->writeUTF( rDesc.ScriptCode );
789 ++aEvtIt;
791 ++aIt;
794 // The length is now known
795 sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
796 xMarkStream->jumpToMark( nObjLenMark );
797 OutStream->writeLong( nObjLen );
798 xMarkStream->jumpToFurthest();
799 xMarkStream->deleteMark( nObjLenMark );
802 void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
803 throw( IOException, RuntimeException, std::exception )
805 Guard< Mutex > aGuard( aLock );
806 // Don't run without XMarkableStream
807 Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
808 if( !xMarkStream.is() )
809 return;
811 // Read in the version
812 nVersion = InStream->readShort();
814 // At first there's the data according to version 1 --
815 // this part needs to be kept in later versions.
816 sal_Int32 nLen = InStream->readLong();
818 // Position for comparative purposes
819 sal_Int32 nObjLenMark = xMarkStream->createMark();
821 // Number of read sequences
822 sal_Int32 nItemCount = InStream->readLong();
824 for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
826 insertEntry( i );
827 // Read the length of the sequence
828 sal_Int32 nSeqLen = InStream->readLong();
830 // Display the sequences and read the descriptions
831 Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
832 ScriptEventDescriptor* pArray = aSEDSeq.getArray();
833 for( sal_Int32 j = 0 ; j < nSeqLen ; j++ )
835 ScriptEventDescriptor& rDesc = pArray[ j ];
836 rDesc.ListenerType = InStream->readUTF();
837 rDesc.EventMethod = InStream->readUTF();
838 rDesc.AddListenerParam = InStream->readUTF();
839 rDesc.ScriptType = InStream->readUTF();
840 rDesc.ScriptCode = InStream->readUTF();
842 registerScriptEvents( i, aSEDSeq );
845 // Have we read the specified length?
846 sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
847 if( nRealLen != nLen )
849 // Only if the StreamVersion is > 1 and the date still follows, can
850 // this be true. Otherwise, something is completely gone.
851 if( nRealLen > nLen || nVersion == 1 )
853 OSL_FAIL( "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
855 else
856 { // TODO: Examine if caching the dates would be useful
857 // But for now, it's easier to skip it.
858 sal_Int32 nSkipCount = nLen - nRealLen;
859 InStream->skipBytes( nSkipCount );
862 xMarkStream->jumpToFurthest();
863 xMarkStream->deleteMark( nObjLenMark );
866 } // namesapce comphelper
869 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */