update credits
[LibreOffice.git] / comphelper / source / eventattachermgr / eventattachermgr.cxx
blob512e6fb786f38ab781437a565ddbd672123656dd
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 .
21 #if defined( UNX )
22 #include <wchar.h>
23 #endif
24 #include <osl/mutex.hxx>
25 #include <osl/diagnose.h>
26 #include <comphelper/eventattachermgr.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <com/sun/star/beans/Introspection.hpp>
29 #include <com/sun/star/io/XObjectInputStream.hpp>
30 #include <com/sun/star/io/XPersistObject.hpp>
31 #include <com/sun/star/io/XObjectOutputStream.hpp>
32 #include <com/sun/star/io/XMarkableStream.hpp>
33 #include <com/sun/star/lang/XInitialization.hpp>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/reflection/theCoreReflection.hpp>
36 #include <com/sun/star/reflection/XIdlClass.hpp>
37 #include <com/sun/star/reflection/XIdlReflection.hpp>
38 #include <com/sun/star/reflection/XIdlMethod.hpp>
39 #include <com/sun/star/script/Converter.hpp>
40 #include <com/sun/star/script/XEngineListener.hpp>
41 #include <com/sun/star/script/XEventAttacher2.hpp>
42 #include <com/sun/star/script/XEventAttacherManager.hpp>
43 #include <com/sun/star/script/XScriptListener.hpp>
44 #include <cppuhelper/weak.hxx>
45 #include <cppuhelper/interfacecontainer.hxx>
46 #include <cppuhelper/implbase1.hxx>
47 #include <cppuhelper/implbase2.hxx>
49 #include <deque>
50 #include <algorithm>
51 #include <functional>
53 using namespace com::sun::star::uno;
54 using namespace com::sun::star::io;
55 using namespace com::sun::star::lang;
56 using namespace com::sun::star::beans;
57 using namespace com::sun::star::script;
58 using namespace com::sun::star::reflection;
59 using namespace cppu;
60 using namespace osl;
63 namespace comphelper
66 //-----------------------------------------------------------------------------
67 struct AttachedObject_Impl
69 Reference< XInterface > xTarget;
70 Sequence< Reference< XEventListener > > aAttachedListenerSeq;
71 Any aHelper;
73 bool operator<( const AttachedObject_Impl & ) const;
74 bool operator==( const AttachedObject_Impl & ) const;
77 struct AttacherIndex_Impl
79 ::std::deque< ScriptEventDescriptor > aEventList;
80 ::std::deque< AttachedObject_Impl > aObjList;
82 bool operator<( const AttacherIndex_Impl & ) const;
83 bool operator==( const AttacherIndex_Impl & ) const;
86 //-----------------------------------------------------------------------------
87 class ImplEventAttacherManager
88 : public WeakImplHelper2< XEventAttacherManager, XPersistObject >
90 friend class AttacherAllListener_Impl;
91 ::std::deque< AttacherIndex_Impl > aIndex;
92 Mutex aLock;
93 // Container for the ScriptListener
94 OInterfaceContainerHelper aScriptListeners;
95 // Instance of EventAttacher
96 Reference< XEventAttacher2 > xAttacher;
97 Reference< XComponentContext > mxContext;
98 Reference< XIdlReflection > mxCoreReflection;
99 Reference< XIntrospection > mxIntrospection;
100 Reference< XTypeConverter > xConverter;
101 sal_Int16 nVersion;
102 public:
103 ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
104 const Reference< XComponentContext > xContext );
105 ~ImplEventAttacherManager();
107 // Methods of XEventAttacherManager
108 virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent)
109 throw( IllegalArgumentException, RuntimeException );
110 virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents)
111 throw( IllegalArgumentException, RuntimeException );
112 virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam)
113 throw( IllegalArgumentException, RuntimeException );
114 virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index)
115 throw( IllegalArgumentException, RuntimeException );
116 virtual void SAL_CALL insertEntry(sal_Int32 Index)
117 throw( IllegalArgumentException, RuntimeException );
118 virtual void SAL_CALL removeEntry(sal_Int32 Index)
119 throw( IllegalArgumentException, RuntimeException );
120 virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index)
121 throw( IllegalArgumentException, RuntimeException );
122 virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper)
123 throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException );
124 virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
125 throw( IllegalArgumentException, RuntimeException );
126 virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener)
127 throw( IllegalArgumentException, RuntimeException );
128 virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener)
129 throw( IllegalArgumentException, RuntimeException );
131 // Methods of XPersistObject
132 virtual OUString SAL_CALL getServiceName(void) throw( RuntimeException );
133 virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream) throw( IOException, RuntimeException );
134 virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) throw( IOException, RuntimeException );
136 private:
137 Reference< XIdlReflection > getReflection() throw( Exception );
139 /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
140 @param _nIndex
141 the index to check
142 @return
143 the iterator pointing to the position indicated by the index
145 ::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) );
148 //========================================================================
149 //========================================================================
150 //========================================================================
153 // Implementation of an EventAttacher-subclass 'AllListeners', which
154 // only passes individual events of the general AllListeners.
155 class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener >
157 ImplEventAttacherManager* mpManager;
158 Reference< XEventAttacherManager > xManager;
159 OUString aScriptType;
160 OUString aScriptCode;
162 void convertToEventReturn( Any & rRet, const Type & rRetType )
163 throw( CannotConvertException );
164 public:
165 AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_,
166 const OUString & rScriptCode_ );
168 // Methods of XAllListener
169 virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException );
170 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException );
172 // Methods of XEventListener
173 virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
176 //========================================================================
177 AttacherAllListener_Impl::AttacherAllListener_Impl
179 ImplEventAttacherManager* pManager_,
180 const OUString & rScriptType_,
181 const OUString & rScriptCode_
183 : mpManager( pManager_ )
184 , xManager( pManager_ )
185 , aScriptType( rScriptType_ )
186 , aScriptCode( rScriptCode_ )
191 //========================================================================
192 // Methods of XAllListener
193 void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
194 throw( RuntimeException )
196 ScriptEvent aScriptEvent;
197 aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface
198 aScriptEvent.ListenerType = Event.ListenerType;
199 aScriptEvent.MethodName = Event.MethodName;
200 aScriptEvent.Arguments = Event.Arguments;
201 aScriptEvent.Helper = Event.Helper;
202 aScriptEvent.ScriptType = aScriptType;
203 aScriptEvent.ScriptCode = aScriptCode;
205 // Iterate over all listeners and pass events.
206 OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
207 while( aIt.hasMoreElements() )
208 ((XScriptListener *)aIt.next())->firing( aScriptEvent );
211 //========================================================================
212 // Convert to the standard event return
213 void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
214 throw( CannotConvertException )
216 // no return value? Set to the specified values
217 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
219 switch( rRetType.getTypeClass() )
221 case TypeClass_INTERFACE:
223 rRet <<= Reference< XInterface >();
225 break;
227 case TypeClass_BOOLEAN:
228 rRet <<= sal_True;
229 break;
231 case TypeClass_STRING:
232 rRet <<= OUString();
233 break;
235 case TypeClass_FLOAT: rRet <<= float(0); break;
236 case TypeClass_DOUBLE: rRet <<= double(0.0); break;
237 case TypeClass_BYTE: rRet <<= sal_uInt8(0); break;
238 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
239 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
240 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
241 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
243 default:
244 OSL_ASSERT(false);
245 break;
248 else if( !rRet.getValueType().equals( rRetType ) )
250 if( mpManager->xConverter.is() )
251 rRet = mpManager->xConverter->convertTo( rRet, rRetType );
252 else
253 throw CannotConvertException();
257 //========================================================================
258 // Methods of XAllListener
259 Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event )
260 throw( InvocationTargetException, RuntimeException )
262 ScriptEvent aScriptEvent;
263 aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface
264 aScriptEvent.ListenerType = Event.ListenerType;
265 aScriptEvent.MethodName = Event.MethodName;
266 aScriptEvent.Arguments = Event.Arguments;
267 aScriptEvent.Helper = Event.Helper;
268 aScriptEvent.ScriptType = aScriptType;
269 aScriptEvent.ScriptCode = aScriptCode;
271 Any aRet;
272 // Iterate over all listeners and pass events.
273 OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
274 while( aIt.hasMoreElements() )
276 aRet = ((XScriptListener *)aIt.next())->approveFiring( aScriptEvent );
279 Reference< XIdlClass > xListenerType = mpManager->getReflection()->
280 forName( Event.ListenerType.getTypeName() );
281 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
282 if( xMeth.is() )
284 Reference< XIdlClass > xRetType = xMeth->getReturnType();
285 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
286 convertToEventReturn( aRet, aRetType );
289 switch( aRet.getValueType().getTypeClass() )
291 case TypeClass_INTERFACE:
293 // Interface not null, return
294 Reference< XInterface > x;
295 aRet >>= x;
296 if( x.is() )
297 return aRet;
299 break;
301 case TypeClass_BOOLEAN:
302 // FALSE -> Return
303 if( !(*(sal_Bool*)aRet.getValue()) )
304 return aRet;
305 break;
307 case TypeClass_STRING:
308 // none empty string -> return
309 if( !((OUString*)aRet.getValue())->isEmpty() )
310 return aRet;
311 break;
313 // none zero number -> return
314 case TypeClass_FLOAT: if( *((float*)aRet.getValue()) ) return aRet; break;
315 case TypeClass_DOUBLE: if( *((double*)aRet.getValue()) ) return aRet; break;
316 case TypeClass_BYTE: if( *((sal_uInt8*)aRet.getValue()) ) return aRet; break;
317 case TypeClass_SHORT: if( *((sal_Int16*)aRet.getValue()) ) return aRet; break;
318 case TypeClass_LONG: if( *((sal_Int32*)aRet.getValue()) ) return aRet; break;
319 case TypeClass_UNSIGNED_SHORT: if( *((sal_uInt16*)aRet.getValue()) ) return aRet; break;
320 case TypeClass_UNSIGNED_LONG: if( *((sal_uInt32*)aRet.getValue()) ) return aRet; break;
322 default:
323 OSL_ASSERT(false);
324 break;
327 catch( CannotConvertException& )
329 // silent ignore conversions errors from a script call
330 Reference< XIdlClass > xListenerType = mpManager->getReflection()->
331 forName( Event.ListenerType.getTypeName() );
332 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
333 if( xMeth.is() )
335 Reference< XIdlClass > xRetType = xMeth->getReturnType();
336 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
337 aRet.clear();
338 convertToEventReturn( aRet, aRetType );
342 return aRet;
345 //========================================================================
346 // Methods of XEventListener
347 void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
348 throw( RuntimeException )
350 // It is up to the container to release the object
354 // Constructor method for EventAttacherManager
355 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XComponentContext > & rxContext )
356 throw( Exception )
358 Reference< XIntrospection > xIntrospection = Introspection::create( rxContext );
359 return new ImplEventAttacherManager( xIntrospection, rxContext );
362 //-----------------------------------------------------------------------------
363 ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
364 const Reference< XComponentContext > xContext )
365 : aScriptListeners( aLock )
366 , mxContext( xContext )
367 , mxIntrospection( rIntrospection )
369 if ( xContext.is() )
371 Reference< XInterface > xIFace( xContext->getServiceManager()->createInstanceWithContext(
372 OUString( "com.sun.star.script.EventAttacher" ), xContext) );
373 if ( xIFace.is() )
375 xAttacher = Reference< XEventAttacher2 >::query( xIFace );
377 xConverter = Converter::create(xContext);
380 Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
381 if( xInit.is() )
383 Sequence< Any > Arguments( 1 );
384 Arguments[0] <<= rIntrospection;
385 xInit->initialize( Arguments );
389 //-----------------------------------------------------------------------------
390 ImplEventAttacherManager::~ImplEventAttacherManager()
394 Reference< XIdlReflection > ImplEventAttacherManager::getReflection() throw( Exception )
396 Guard< Mutex > aGuard( aLock );
397 // Do we already have a service? If not, create one.
398 if( !mxCoreReflection.is() )
400 mxCoreReflection = theCoreReflection::get(mxContext);
402 return mxCoreReflection;
406 //-----------------------------------------------------------------------------
407 ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) )
409 if (_nIndex < 0)
410 throw IllegalArgumentException();
412 ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
413 for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
416 if( aIt == aIndex.end() )
417 throw IllegalArgumentException();
419 return aIt;
422 namespace {
424 class DetachObject : public std::unary_function<AttachedObject_Impl, void>
426 ImplEventAttacherManager& mrMgr;
427 sal_Int32 mnIdx;
428 public:
429 DetachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
430 mrMgr(rMgr), mnIdx(nIdx) {}
432 void operator() (AttachedObject_Impl& rObj)
434 mrMgr.detach(mnIdx, rObj.xTarget);
438 class AttachObject : public std::unary_function<AttachedObject_Impl, void>
440 ImplEventAttacherManager& mrMgr;
441 sal_Int32 mnIdx;
442 public:
443 AttachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
444 mrMgr(rMgr), mnIdx(nIdx) {}
446 void operator() (AttachedObject_Impl& rObj)
448 mrMgr.attach(mnIdx, rObj.xTarget, rObj.aHelper);
454 //-----------------------------------------------------------------------------
455 // Methods of XEventAttacherManager
456 void SAL_CALL ImplEventAttacherManager::registerScriptEvent
458 sal_Int32 nIndex,
459 const ScriptEventDescriptor& ScriptEvent
461 throw( IllegalArgumentException, RuntimeException )
463 Guard< Mutex > aGuard( aLock );
465 // Examine the index and apply the array
466 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
468 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
470 ScriptEventDescriptor aEvt = ScriptEvent;
471 const sal_Unicode* pLastDot = aEvt.ListenerType.getStr();
472 pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
473 if( pLastDot )
474 aEvt.ListenerType = pLastDot +1;
475 (*aIt).aEventList.push_back( aEvt );
477 // register new new Event
478 ::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.begin();
479 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end();
480 while( aObjIt != aObjEnd )
482 // resize
483 sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
484 (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
485 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
487 Reference< XAllListener > xAll =
488 new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
491 pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
492 (*aObjIt).aHelper, ScriptEvent.ListenerType,
493 ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
495 catch( Exception& )
499 ++aObjIt;
503 //-----------------------------------------------------------------------------
504 void SAL_CALL ImplEventAttacherManager::registerScriptEvents
506 sal_Int32 nIndex,
507 const Sequence< ScriptEventDescriptor >& ScriptEvents
509 throw( IllegalArgumentException, RuntimeException )
511 Guard< Mutex > aGuard( aLock );
513 // Examine the index and apply the array
514 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
516 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
517 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
519 const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
520 sal_Int32 nLen = ScriptEvents.getLength();
521 for( sal_Int32 i = 0 ; i < nLen ; i++ )
522 registerScriptEvent( nIndex, pArray[ i ] );
524 ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
527 //-----------------------------------------------------------------------------
528 void SAL_CALL ImplEventAttacherManager::revokeScriptEvent
530 sal_Int32 nIndex,
531 const OUString& ListenerType,
532 const OUString& EventMethod,
533 const OUString& ToRemoveListenerParam
535 throw( IllegalArgumentException, RuntimeException )
537 Guard< Mutex > aGuard( aLock );
539 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
541 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
542 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
544 OUString aLstType = ListenerType;
545 const sal_Unicode * pLastDot = aLstType.getStr();
546 pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
547 if( pLastDot )
548 aLstType = pLastDot +1;
550 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
551 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
552 while( aEvtIt != aEvtEnd )
554 if( aLstType == (*aEvtIt).ListenerType
555 && EventMethod == (*aEvtIt).EventMethod
556 && ToRemoveListenerParam == (*aEvtIt).AddListenerParam )
558 (*aIt).aEventList.erase( aEvtIt );
559 break;
562 ++aEvtIt;
564 ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
567 //-----------------------------------------------------------------------------
568 void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
569 throw( IllegalArgumentException, RuntimeException )
571 Guard< Mutex > aGuard( aLock );
572 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
574 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
575 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
576 (*aIt).aEventList.clear();
577 ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
580 //-----------------------------------------------------------------------------
581 void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
582 throw( IllegalArgumentException, RuntimeException )
584 Guard< Mutex > aGuard( aLock );
585 if( nIndex < 0 )
586 throw IllegalArgumentException();
588 if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
589 aIndex.resize(nIndex+1);
591 AttacherIndex_Impl aTmp;
592 aIndex.insert( aIndex.begin() + nIndex, aTmp );
595 //-----------------------------------------------------------------------------
596 void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
597 throw( IllegalArgumentException, RuntimeException )
599 Guard< Mutex > aGuard( aLock );
600 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
602 ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
603 ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
604 aIndex.erase( aIt );
607 //-----------------------------------------------------------------------------
608 Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
609 throw( IllegalArgumentException, RuntimeException )
611 Guard< Mutex > aGuard( aLock );
612 ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
614 Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
615 ScriptEventDescriptor * pArray = aSeq.getArray();
617 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
618 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
619 sal_Int32 i = 0;
620 while( aEvtIt != aEvtEnd )
622 pArray[i++] = *aEvtIt;
623 ++aEvtIt;
625 return aSeq;
628 //-----------------------------------------------------------------------------
629 void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
630 throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException )
632 Guard< Mutex > aGuard( aLock );
633 if( nIndex < 0 || !xObject.is() )
634 throw IllegalArgumentException();
636 if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
638 // read older files
639 if( nVersion == 1 )
641 insertEntry( nIndex );
642 attach( nIndex, xObject, Helper );
643 return;
645 else
646 throw IllegalArgumentException();
649 ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
651 AttachedObject_Impl aTmp;
652 aTmp.xTarget = xObject;
653 aTmp.aHelper = Helper;
654 aCurrentPosition->aObjList.push_back( aTmp );
656 //::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back();
657 AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
658 rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
660 if (aCurrentPosition->aEventList.empty())
661 return;
663 Sequence<com::sun::star::script::EventListener> aEvents(aCurrentPosition->aEventList.size());
664 std::deque<ScriptEventDescriptor>::iterator itr = aCurrentPosition->aEventList.begin();
665 std::deque<ScriptEventDescriptor>::iterator itrEnd = aCurrentPosition->aEventList.end();
666 ::com::sun::star::script::EventListener* p = aEvents.getArray();
667 size_t i = 0;
668 for (; itr != itrEnd; ++itr)
670 com::sun::star::script::EventListener aListener;
671 aListener.AllListener =
672 new AttacherAllListener_Impl(this, itr->ScriptType, itr->ScriptCode);
673 aListener.Helper = rCurObj.aHelper;
674 aListener.ListenerType = itr->ListenerType;
675 aListener.EventMethod = itr->EventMethod;
676 aListener.AddListenerParam = itr->AddListenerParam;
677 p[i++] = aListener;
682 rCurObj.aAttachedListenerSeq =
683 xAttacher->attachMultipleEventListeners(rCurObj.xTarget, aEvents);
685 catch (const Exception&)
687 // Fail gracefully.
691 //-----------------------------------------------------------------------------
692 void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
693 throw( IllegalArgumentException, RuntimeException )
695 Guard< Mutex > aGuard( aLock );
696 //return;
697 if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
698 throw IllegalArgumentException();
700 ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
701 ::std::deque< AttachedObject_Impl >::iterator aObjIt = aCurrentPosition->aObjList.begin();
702 ::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end();
703 while( aObjIt != aObjEnd )
705 if( (*aObjIt).xTarget == xObject )
707 Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
709 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
710 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
711 sal_Int32 i = 0;
712 while( aEvtIt != aEvtEnd )
714 if( pArray[i].is() )
718 xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
719 (*aEvtIt).AddListenerParam, pArray[i] );
721 catch( Exception& )
725 i++;
726 ++aEvtIt;
728 aCurrentPosition->aObjList.erase( aObjIt );
729 break;
731 ++aObjIt;
735 void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
736 throw( IllegalArgumentException, RuntimeException )
738 Guard< Mutex > aGuard( aLock );
739 aScriptListeners.addInterface( aListener );
742 void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
743 throw( IllegalArgumentException, RuntimeException )
745 Guard< Mutex > aGuard( aLock );
746 aScriptListeners.removeInterface( aListener );
750 // Methods of XPersistObject
751 OUString SAL_CALL ImplEventAttacherManager::getServiceName(void)
752 throw( RuntimeException )
754 return OUString( "com.sun.star.uno.script.EventAttacherManager" );
757 void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
758 throw( IOException, RuntimeException )
760 Guard< Mutex > aGuard( aLock );
761 // Don't run without XMarkableStream
762 Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
763 if( !xMarkStream.is() )
764 return;
766 // Write out the version
767 OutStream->writeShort( 2 );
769 // Remember position for length
770 sal_Int32 nObjLenMark = xMarkStream->createMark();
771 OutStream->writeLong( 0L );
773 OutStream->writeLong( aIndex.size() );
775 // Write out sequences
776 ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
777 ::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end();
778 while( aIt != aEnd )
780 // Write out the length of the sequence and all descriptions
781 OutStream->writeLong( (*aIt).aEventList.size() );
782 ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
783 ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
784 while( aEvtIt != aEvtEnd )
786 const ScriptEventDescriptor& rDesc = (*aEvtIt);
787 OutStream->writeUTF( rDesc.ListenerType );
788 OutStream->writeUTF( rDesc.EventMethod );
789 OutStream->writeUTF( rDesc.AddListenerParam );
790 OutStream->writeUTF( rDesc.ScriptType );
791 OutStream->writeUTF( rDesc.ScriptCode );
793 ++aEvtIt;
795 ++aIt;
798 // The length is now known
799 sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
800 xMarkStream->jumpToMark( nObjLenMark );
801 OutStream->writeLong( nObjLen );
802 xMarkStream->jumpToFurthest();
803 xMarkStream->deleteMark( nObjLenMark );
806 void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
807 throw( IOException, RuntimeException )
809 Guard< Mutex > aGuard( aLock );
810 // Don't run without XMarkableStream
811 Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
812 if( !xMarkStream.is() )
813 return;
815 // Read in the version
816 nVersion = InStream->readShort();
818 // At first there's the data according to version 1 --
819 // this part needs to be kept in later versions.
820 sal_Int32 nLen = InStream->readLong();
822 // Position for comparative purposes
823 sal_Int32 nObjLenMark = xMarkStream->createMark();
825 // Number of read sequences
826 sal_Int32 nItemCount = InStream->readLong();
828 for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
830 insertEntry( i );
831 // Read the length of the sequence
832 sal_Int32 nSeqLen = InStream->readLong();
834 // Display the sequences and read the descriptions
835 Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
836 ScriptEventDescriptor* pArray = aSEDSeq.getArray();
837 for( sal_Int32 j = 0 ; j < nSeqLen ; j++ )
839 ScriptEventDescriptor& rDesc = pArray[ j ];
840 rDesc.ListenerType = InStream->readUTF();
841 rDesc.EventMethod = InStream->readUTF();
842 rDesc.AddListenerParam = InStream->readUTF();
843 rDesc.ScriptType = InStream->readUTF();
844 rDesc.ScriptCode = InStream->readUTF();
846 registerScriptEvents( i, aSEDSeq );
849 // Have we read the specified length?
850 sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
851 if( nRealLen != nLen )
853 // Only if the StreamVersion is > 1 and the date still follows, can
854 // this be true. Otherwise, something is completely gone.
855 if( nRealLen > nLen || nVersion == 1 )
857 OSL_FAIL( "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
859 else
860 { // TODO: Examine if caching the dates would be useful
861 // But for now, it's easier to skip it.
862 sal_Int32 nSkipCount = nLen - nRealLen;
863 InStream->skipBytes( nSkipCount );
866 xMarkStream->jumpToFurthest();
867 xMarkStream->deleteMark( nObjLenMark );
870 } // namesapce comphelper
873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */