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/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>
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
;
64 struct AttachedObject_Impl
66 Reference
< XInterface
> xTarget
;
67 Sequence
< Reference
< XEventListener
> > aAttachedListenerSeq
;
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
;
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
;
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
;
128 Reference
< XIdlReflection
> getReflection() throw( Exception
);
130 /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
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
);
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
>();
218 case TypeClass_BOOLEAN
:
222 case TypeClass_STRING
:
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;
239 else if( !rRet
.getValueType().equals( rRetType
) )
241 if( mpManager
->xConverter
.is() )
242 rRet
= mpManager
->xConverter
->convertTo( rRet
, rRetType
);
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
;
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
);
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( !(*static_cast<sal_Bool
const *>(aRet
.getValue())) )
297 case TypeClass_STRING
:
298 // none empty string -> return
299 if( !(static_cast<OUString
const *>(aRet
.getValue()))->isEmpty() )
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;
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
);
325 Reference
< XIdlClass
> xRetType
= xMeth
->getReturnType();
326 Type
aRetType(xRetType
->getTypeClass(), xRetType
->getName());
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
));
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
)
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
)
369 Reference
< XInterface
> xIFace( rContext
->getServiceManager()->createInstanceWithContext(
370 OUString( "com.sun.star.script.EventAttacher" ), rContext
) );
373 xAttacher
= Reference
< XEventAttacher2
>::query( xIFace
);
375 xConverter
= Converter::create(rContext
);
378 Reference
< XInitialization
> xInit( xAttacher
, UNO_QUERY
);
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
)
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();
422 class DetachObject
: public std::unary_function
<AttachedObject_Impl
, void>
424 ImplEventAttacherManager
& mrMgr
;
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
;
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
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('.');
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
)
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
);
501 void SAL_CALL
ImplEventAttacherManager::registerScriptEvents
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
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('.');
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
);
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
);
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
));
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();
616 while( aEvtIt
!= aEvtEnd
)
618 pArray
[i
++] = *aEvtIt
;
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() )
637 insertEntry( nIndex
);
638 attach( nIndex
, xObject
, Helper
);
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())
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();
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
;
678 rCurObj
.aAttachedListenerSeq
=
679 xAttacher
->attachMultipleEventListeners(rCurObj
.xTarget
, aEvents
);
681 catch (const Exception
&)
688 void SAL_CALL
ImplEventAttacherManager::detach(sal_Int32 nIndex
, const Reference
< XInterface
>& xObject
)
689 throw( IllegalArgumentException
, RuntimeException
, std::exception
)
691 Guard
< Mutex
> aGuard( aLock
);
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();
708 while( aEvtIt
!= aEvtEnd
)
714 xAttacher
->removeListener( (*aObjIt
).xTarget
, (*aEvtIt
).ListenerType
,
715 (*aEvtIt
).AddListenerParam
, pArray
[i
] );
724 aCurrentPosition
->aObjList
.erase( 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() )
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();
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
);
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() )
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
++ )
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" );
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: */