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 .
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>
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
;
66 //-----------------------------------------------------------------------------
67 struct AttachedObject_Impl
69 Reference
< XInterface
> xTarget
;
70 Sequence
< Reference
< XEventListener
> > aAttachedListenerSeq
;
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
;
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
;
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
);
137 Reference
< XIdlReflection
> getReflection() throw( Exception
);
139 /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
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
);
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
>();
227 case TypeClass_BOOLEAN
:
231 case TypeClass_STRING
:
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;
248 else if( !rRet
.getValueType().equals( rRetType
) )
250 if( mpManager
->xConverter
.is() )
251 rRet
= mpManager
->xConverter
->convertTo( rRet
, rRetType
);
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
;
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
);
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
;
301 case TypeClass_BOOLEAN
:
303 if( !(*(sal_Bool
*)aRet
.getValue()) )
307 case TypeClass_STRING
:
308 // none empty string -> return
309 if( !((OUString
*)aRet
.getValue())->isEmpty() )
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;
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
);
335 Reference
< XIdlClass
> xRetType
= xMeth
->getReturnType();
336 Type
aRetType(xRetType
->getTypeClass(), xRetType
->getName());
338 convertToEventReturn( aRet
, aRetType
);
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
)
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
)
371 Reference
< XInterface
> xIFace( xContext
->getServiceManager()->createInstanceWithContext(
372 OUString( "com.sun.star.script.EventAttacher" ), xContext
) );
375 xAttacher
= Reference
< XEventAttacher2
>::query( xIFace
);
377 xConverter
= Converter::create(xContext
);
380 Reference
< XInitialization
> xInit( xAttacher
, UNO_QUERY
);
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
) )
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();
424 class DetachObject
: public std::unary_function
<AttachedObject_Impl
, void>
426 ImplEventAttacherManager
& mrMgr
;
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
;
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
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
, '.' );
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
)
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
);
503 //-----------------------------------------------------------------------------
504 void SAL_CALL
ImplEventAttacherManager::registerScriptEvents
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
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
, '.' );
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
);
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
);
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
));
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();
620 while( aEvtIt
!= aEvtEnd
)
622 pArray
[i
++] = *aEvtIt
;
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() )
641 insertEntry( nIndex
);
642 attach( nIndex
, xObject
, Helper
);
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())
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();
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
;
682 rCurObj
.aAttachedListenerSeq
=
683 xAttacher
->attachMultipleEventListeners(rCurObj
.xTarget
, aEvents
);
685 catch (const Exception
&)
691 //-----------------------------------------------------------------------------
692 void SAL_CALL
ImplEventAttacherManager::detach(sal_Int32 nIndex
, const Reference
< XInterface
>& xObject
)
693 throw( IllegalArgumentException
, RuntimeException
)
695 Guard
< Mutex
> aGuard( aLock
);
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();
712 while( aEvtIt
!= aEvtEnd
)
718 xAttacher
->removeListener( (*aObjIt
).xTarget
, (*aEvtIt
).ListenerType
,
719 (*aEvtIt
).AddListenerParam
, pArray
[i
] );
728 aCurrentPosition
->aObjList
.erase( 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() )
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();
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
);
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() )
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
++ )
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" );
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: */