1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
;
63 struct AttachedObject_Impl
65 Reference
< XInterface
> xTarget
;
66 Sequence
< Reference
< XEventListener
> > aAttachedListenerSeq
;
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
;
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
;
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
;
127 Reference
< XIdlReflection
> getReflection() throw( Exception
);
129 /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
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
);
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
>();
217 case TypeClass_BOOLEAN
:
221 case TypeClass_STRING
:
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;
238 else if( !rRet
.getValueType().equals( rRetType
) )
240 if( mpManager
->xConverter
.is() )
241 rRet
= mpManager
->xConverter
->convertTo( rRet
, rRetType
);
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
;
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
);
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
;
291 case TypeClass_BOOLEAN
:
293 if( !(*(sal_Bool
*)aRet
.getValue()) )
297 case TypeClass_STRING
:
298 // none empty string -> return
299 if( !((OUString
*)aRet
.getValue())->isEmpty() )
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;
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
);
325 Reference
< XIdlClass
> xRetType
= xMeth
->getReturnType();
326 Type
aRetType(xRetType
->getTypeClass(), xRetType
->getName());
328 convertToEventReturn( aRet
, aRetType
);
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
)
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
)
362 Reference
< XInterface
> xIFace( xContext
->getServiceManager()->createInstanceWithContext(
363 OUString( "com.sun.star.script.EventAttacher" ), xContext
) );
366 xAttacher
= Reference
< XEventAttacher2
>::query( xIFace
);
368 xConverter
= Converter::create(xContext
);
371 Reference
< XInitialization
> xInit( xAttacher
, UNO_QUERY
);
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
) )
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();
415 class DetachObject
: public std::unary_function
<AttachedObject_Impl
, void>
417 ImplEventAttacherManager
& mrMgr
;
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
;
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
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('.');
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
)
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
);
494 void SAL_CALL
ImplEventAttacherManager::registerScriptEvents
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
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('.');
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
);
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
);
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
));
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();
609 while( aEvtIt
!= aEvtEnd
)
611 pArray
[i
++] = *aEvtIt
;
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() )
630 insertEntry( nIndex
);
631 attach( nIndex
, xObject
, Helper
);
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())
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();
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
;
671 rCurObj
.aAttachedListenerSeq
=
672 xAttacher
->attachMultipleEventListeners(rCurObj
.xTarget
, aEvents
);
674 catch (const Exception
&)
681 void SAL_CALL
ImplEventAttacherManager::detach(sal_Int32 nIndex
, const Reference
< XInterface
>& xObject
)
682 throw( IllegalArgumentException
, RuntimeException
, std::exception
)
684 Guard
< Mutex
> aGuard( aLock
);
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();
701 while( aEvtIt
!= aEvtEnd
)
707 xAttacher
->removeListener( (*aObjIt
).xTarget
, (*aEvtIt
).ListenerType
,
708 (*aEvtIt
).AddListenerParam
, pArray
[i
] );
717 aCurrentPosition
->aObjList
.erase( 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() )
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();
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
);
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() )
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
++ )
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" );
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: */