xref: /trunk/main/comphelper/source/eventattachermgr/eventattachermgr.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_comphelper.hxx"
26 
27 #include <deque>
28 
29 #if defined( OS2 ) || defined( UNX )
30 #include <wchar.h>
31 #endif
32 #include <osl/mutex.hxx>
33 #ifndef _VOS_DIAGNOSE_HXX_
34 #include <vos/diagnose.hxx>
35 #endif
36 #include <vos/macros.hxx>
37 #include <comphelper/eventattachermgr.hxx>
38 #include <com/sun/star/beans/XIntrospection.hpp>
39 #include <com/sun/star/io/XObjectInputStream.hpp>
40 #include <com/sun/star/io/XPersistObject.hpp>
41 #include <com/sun/star/io/XObjectOutputStream.hpp>
42 #include <com/sun/star/io/XMarkableStream.hpp>
43 #include <com/sun/star/lang/XInitialization.hpp>
44 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45 #include <com/sun/star/reflection/XIdlClass.hpp>
46 #include <com/sun/star/reflection/XIdlReflection.hpp>
47 #include <com/sun/star/reflection/XIdlMethod.hpp>
48 #include <com/sun/star/script/XTypeConverter.hpp>
49 #include <com/sun/star/script/XEngineListener.hpp>
50 #include <com/sun/star/script/XEventAttacher.hpp>
51 #include <com/sun/star/script/XEventAttacherManager.hpp>
52 #include <com/sun/star/script/XScriptListener.hpp>
53 #include <cppuhelper/weak.hxx>
54 #include <cppuhelper/interfacecontainer.hxx>
55 #include <cppuhelper/implbase1.hxx>
56 #include <cppuhelper/implbase2.hxx>
57 
58 using namespace com::sun::star::uno;
59 using namespace com::sun::star::io;
60 using namespace com::sun::star::lang;
61 using namespace com::sun::star::beans;
62 using namespace com::sun::star::script;
63 using namespace com::sun::star::reflection;
64 using namespace cppu;
65 using namespace osl;
66 using namespace rtl;
67 
68 namespace comphelper
69 {
70 
71 //-----------------------------------------------------------------------------
72 struct AttachedObject_Impl
73 {
74     Reference< XInterface >                 xTarget;
75     Sequence< Reference< XEventListener > > aAttachedListenerSeq;
76     Any                                     aHelper;
77 
78     bool operator<( const AttachedObject_Impl & ) const;
79     bool operator==( const AttachedObject_Impl & ) const;
80 };
81 
82 struct AttacherIndex_Impl
83 {
84 #ifdef DEQUE_OK
85     ::std::deque< ScriptEventDescriptor > aEventList;
86 #else
87     Sequence< ScriptEventDescriptor > aEventList;
88 #endif
89     ::std::deque< AttachedObject_Impl > aObjList;
90 
91     bool operator<( const AttacherIndex_Impl & ) const;
92     bool operator==( const AttacherIndex_Impl & ) const;
93 };
94 
95 #if 0
96 bool AttachedObject_Impl::operator<( const AttachedObject_Impl & r ) const
97 {
98     VOS_ENSHURE( FALSE, "not implemented" );
99     return FALSE;
100     return this < &r;
101 }
102 
103 bool AttachedObject_Impl::operator==( const AttachedObject_Impl & r ) const
104 {
105     VOS_ENSHURE( FALSE, "not implemented" );
106     return this == &r;
107 }
108 
109 bool AttacherIndex_Impl::operator<( const AttacherIndex_Impl & r ) const
110 {
111     VOS_ENSHURE( FALSE, "not implemented" );
112     return this < &r;
113 }
114 bool AttacherIndex_Impl::operator==( const AttacherIndex_Impl & r ) const
115 {
116     VOS_ENSHURE( FALSE, "not implemented" );
117     return this == &r;
118 }
119 #endif
120 
121 //-----------------------------------------------------------------------------
122 class ImplEventAttacherManager
123     : public WeakImplHelper2< XEventAttacherManager, XPersistObject >
124 {
125     friend class AttacherAllListener_Impl;
126     ::std::deque< AttacherIndex_Impl >  aIndex;
127     Mutex aLock;
128     // Container fuer die ScriptListener
129     OInterfaceContainerHelper           aScriptListeners;
130     // EventAttacher-Instanz
131     Reference< XEventAttacher >         xAttacher;
132     Reference< XMultiServiceFactory >   mxSMgr;
133     Reference< XIdlReflection >         mxCoreReflection;
134     Reference< XIntrospection >         mxIntrospection;
135     Reference< XTypeConverter >         xConverter;
136     sal_Int16                           nVersion;
137 public:
138     ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
139                               const Reference< XMultiServiceFactory > rSMgr );
140     ~ImplEventAttacherManager();
141 
142     // Methoden von XEventAttacherManager
143     virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent);
144     virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents);
145     virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam);
146     virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index);
147     virtual void SAL_CALL insertEntry(sal_Int32 Index);
148     virtual void SAL_CALL removeEntry(sal_Int32 Index);
149     virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index);
150     virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper);
151     virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject);
152     virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener);
153     virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener);
154 
155     // Methoden von XPersistObject
156     virtual OUString SAL_CALL getServiceName(void);
157     virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream);
158     virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream);
159 
160 private:
161     Reference< XIdlReflection > getReflection();
162 
163     /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
164     @param _nIndex
165         the index to check
166     @return
167         the iterator pointing to the position indicated by the index
168     */
169     ::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex );
170 };
171 
172 //========================================================================
173 //========================================================================
174 //========================================================================
175 
176 // Implementation eines EventAttacher-bezogenen AllListeners, der
177 // nur einzelne Events an einen allgemeinen AllListener weiterleitet
178 class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener >
179 {
180     ImplEventAttacherManager*           mpManager;
181     Reference< XEventAttacherManager >  xManager;
182     OUString                            aScriptType;
183     OUString                            aScriptCode;
184     sal_Int16                           nVersion;
185 
186     void convertToEventReturn( Any & rRet, const Type & rRetType );
187 public:
188     AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_,
189                                 const OUString & rScriptCode_ );
190 
191     // Methoden von XAllListener
192     virtual void SAL_CALL firing(const AllEventObject& Event);
193     virtual Any SAL_CALL approveFiring(const AllEventObject& Event);
194 
195     // Methoden von XEventListener
196     virtual void SAL_CALL disposing(const EventObject& Source);
197 };
198 
199 //========================================================================
AttacherAllListener_Impl(ImplEventAttacherManager * pManager_,const OUString & rScriptType_,const OUString & rScriptCode_)200 AttacherAllListener_Impl::AttacherAllListener_Impl
201 (
202     ImplEventAttacherManager*   pManager_,
203     const OUString &            rScriptType_,
204     const OUString &            rScriptCode_
205 )
206     : mpManager( pManager_ )
207     , xManager( pManager_ )
208     , aScriptType( rScriptType_ )
209     , aScriptCode( rScriptCode_ )
210     , nVersion( 2 )
211 {
212 }
213 
214 
215 //========================================================================
216 // Methoden von XAllListener
firing(const AllEventObject & Event)217 void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
218 {
219     ScriptEvent aScriptEvent;
220     aScriptEvent.Source         = (OWeakObject *)mpManager; // get correct XInterface
221     aScriptEvent.ListenerType   = Event.ListenerType;
222     aScriptEvent.MethodName     = Event.MethodName;
223     aScriptEvent.Arguments      = Event.Arguments;
224     aScriptEvent.Helper         = Event.Helper;
225     aScriptEvent.ScriptType     = aScriptType;
226     aScriptEvent.ScriptCode     = aScriptCode;
227 
228     // ueber alle Listener iterieren und Events senden
229     OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
230     while( aIt.hasMoreElements() )
231         ((XScriptListener *)aIt.next())->firing( aScriptEvent );
232 }
233 
234 //========================================================================
235 // Convert to the standard event return
convertToEventReturn(Any & rRet,const Type & rRetType)236 void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
237 {
238     // no return value? Set to the specified values
239     if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
240     {
241         switch( rRetType.getTypeClass() )
242         {
243             case TypeClass_INTERFACE:
244                 {
245                 rRet <<= Reference< XInterface >();
246                 }
247                 break;
248 
249             case TypeClass_BOOLEAN:
250                 rRet <<= sal_True;
251                 break;
252 
253             case TypeClass_STRING:
254                 rRet <<= OUString();
255                 break;
256 
257             case TypeClass_FLOAT:           rRet <<= float(0);          break;
258             case TypeClass_DOUBLE:          rRet <<= double(0.0);       break;
259             case TypeClass_BYTE:            rRet <<= sal_uInt8(0);      break;
260             case TypeClass_SHORT:           rRet <<= sal_Int16( 0 );    break;
261             case TypeClass_LONG:            rRet <<= sal_Int32( 0 );    break;
262             case TypeClass_UNSIGNED_SHORT:  rRet <<= sal_uInt16( 0 );   break;
263             case TypeClass_UNSIGNED_LONG:   rRet <<= sal_uInt32( 0 );   break;
264 
265             default:
266                 OSL_ASSERT(false);
267                 break;
268         }
269     }
270     else if( !rRet.getValueType().equals( rRetType ) )
271     {
272         if( mpManager->xConverter.is() )
273             rRet = mpManager->xConverter->convertTo( rRet, rRetType );
274         else
275             throw CannotConvertException();
276     }
277 }
278 
279 //========================================================================
280 // Methoden von XAllListener
approveFiring(const AllEventObject & Event)281 Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event )
282 {
283     ScriptEvent aScriptEvent;
284     aScriptEvent.Source         = (OWeakObject *)mpManager; // get correct XInterface
285     aScriptEvent.ListenerType   = Event.ListenerType;
286     aScriptEvent.MethodName     = Event.MethodName;
287     aScriptEvent.Arguments      = Event.Arguments;
288     aScriptEvent.Helper         = Event.Helper;
289     aScriptEvent.ScriptType     = aScriptType;
290     aScriptEvent.ScriptCode     = aScriptCode;
291 
292     Any aRet;
293     // ueber alle Listener iterieren und Events senden
294     OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
295     while( aIt.hasMoreElements() )
296     {
297         aRet = ((XScriptListener *)aIt.next())->approveFiring( aScriptEvent );
298         try
299         {
300             Reference< XIdlClass > xListenerType = mpManager->getReflection()->
301                         forName( Event.ListenerType.getTypeName() );
302             Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
303             if( xMeth.is() )
304             {
305                 Reference< XIdlClass > xRetType = xMeth->getReturnType();
306                 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
307                 convertToEventReturn( aRet, aRetType );
308             }
309 
310             switch( aRet.getValueType().getTypeClass() )
311             {
312                 case TypeClass_INTERFACE:
313                     {
314                     // Interface not null, return
315                     Reference< XInterface > x;
316                     aRet >>= x;
317                     if( x.is() )
318                         return aRet;
319                     }
320                     break;
321 
322                 case TypeClass_BOOLEAN:
323                     // FALSE -> Return
324                     if( !(*(sal_Bool*)aRet.getValue()) )
325                         return aRet;
326                     break;
327 
328                 case TypeClass_STRING:
329                     // none empty string -> return
330                     if( ((OUString*)aRet.getValue())->isEmpty() == false )
331                         return aRet;
332                     break;
333 
334                     // none zero number -> return
335                 case TypeClass_FLOAT:           if( *((float*)aRet.getValue()) )        return aRet; break;
336                 case TypeClass_DOUBLE:          if( *((double*)aRet.getValue()) )       return aRet; break;
337                 case TypeClass_BYTE:            if( *((sal_uInt8*)aRet.getValue()) )    return aRet; break;
338                 case TypeClass_SHORT:           if( *((sal_Int16*)aRet.getValue()) )    return aRet; break;
339                 case TypeClass_LONG:            if( *((sal_Int32*)aRet.getValue()) )    return aRet; break;
340                 case TypeClass_UNSIGNED_SHORT:  if( *((sal_uInt16*)aRet.getValue()) )   return aRet; break;
341                 case TypeClass_UNSIGNED_LONG:   if( *((sal_uInt32*)aRet.getValue()) )   return aRet; break;
342 
343                 default:
344                     OSL_ASSERT(false);
345                     break;
346             }
347         }
348         catch( CannotConvertException& )
349         {
350             // silent ignore conversions errors from a script call
351             Reference< XIdlClass > xListenerType = mpManager->getReflection()->
352                         forName( Event.ListenerType.getTypeName() );
353             Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
354             if( xMeth.is() )
355             {
356                 Reference< XIdlClass > xRetType = xMeth->getReturnType();
357                 Type aRetType(xRetType->getTypeClass(), xRetType->getName());
358                 aRet.clear();
359                 convertToEventReturn( aRet, aRetType );
360             }
361         }
362     }
363     return aRet;
364 }
365 
366 //========================================================================
367 // Methoden von XEventListener
disposing(const EventObject &)368 void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
369 {
370     // It is up to the container to release the object
371 }
372 
373 
374 //========================================================================
375 //========================================================================
376 //========================================================================
377 
378 // Create-Methode fuer EventAttacherManager
createEventAttacherManager(const Reference<XIntrospection> & rIntrospection,const Reference<XMultiServiceFactory> & rSMgr)379 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
380                                                                const Reference< XMultiServiceFactory > & rSMgr )
381 {
382     return new ImplEventAttacherManager( rIntrospection, rSMgr );
383 }
384 
385 // Create-Methode fuer EventAttacherManager
createEventAttacherManager(const Reference<XMultiServiceFactory> & rSMgr)386 Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XMultiServiceFactory > & rSMgr )
387 {
388     if ( rSMgr.is() )
389     {
390         Reference< XInterface > xIFace( rSMgr->createInstance( OUString::createFromAscii("com.sun.star.beans.Introspection") ) );
391         if ( xIFace.is() )
392         {
393             Reference< XIntrospection > xIntrospection( xIFace, UNO_QUERY);
394             return new ImplEventAttacherManager( xIntrospection, rSMgr );
395         }
396     }
397 
398     return Reference< XEventAttacherManager >();
399 }
400 
401 //-----------------------------------------------------------------------------
ImplEventAttacherManager(const Reference<XIntrospection> & rIntrospection,const Reference<XMultiServiceFactory> rSMgr)402 ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
403                                                     const Reference< XMultiServiceFactory > rSMgr )
404     : aScriptListeners( aLock )
405     , mxSMgr( rSMgr )
406     , mxIntrospection( rIntrospection )
407 {
408     if ( rSMgr.is() )
409     {
410         Reference< XInterface > xIFace( rSMgr->createInstance( OUString::createFromAscii("com.sun.star.script.EventAttacher") ) );
411         if ( xIFace.is() )
412         {
413             xAttacher = Reference< XEventAttacher >::query( xIFace );
414         }
415         xIFace = rSMgr->createInstance( OUString::createFromAscii("com.sun.star.script.Converter") );
416         if ( xIFace.is() )
417         {
418             xConverter = Reference< XTypeConverter >::query( xIFace );
419         }
420     }
421 
422     Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
423     if( xInit.is() )
424     {
425         Sequence< Any > Arguments( 1 );
426         Arguments[0] <<= rIntrospection;
427         xInit->initialize( Arguments );
428     }
429 }
430 
431 //-----------------------------------------------------------------------------
~ImplEventAttacherManager()432 ImplEventAttacherManager::~ImplEventAttacherManager()
433 {
434 }
435 
getReflection()436 Reference< XIdlReflection > ImplEventAttacherManager::getReflection()
437 {
438     Guard< Mutex > aGuard( aLock );
439     // Haben wir den Service schon? Sonst anlegen
440     if( !mxCoreReflection.is() )
441     {
442         Reference< XInterface > xIFace( mxSMgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection") ) );
443         mxCoreReflection = Reference< XIdlReflection >( xIFace, UNO_QUERY);
444     }
445     return mxCoreReflection;
446 }
447 
448 
449 //-----------------------------------------------------------------------------
implCheckIndex(sal_Int32 _nIndex)450 ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex )
451 {
452     if (_nIndex < 0)
453         throw IllegalArgumentException();
454 
455     ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
456     for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
457         ;
458 
459     if( aIt == aIndex.end() )
460         throw IllegalArgumentException();
461 
462     return aIt;
463 }
464 
465 //-----------------------------------------------------------------------------
detachAll_Impl(ImplEventAttacherManager * pMgr,sal_Int32 nIdx,::std::deque<AttachedObject_Impl> & rList)466 void detachAll_Impl
467 (
468     ImplEventAttacherManager * pMgr,
469     sal_Int32 nIdx,
470     ::std::deque< AttachedObject_Impl > & rList
471 )
472 {
473     ::std::deque< AttachedObject_Impl >::iterator aObjIt =  rList.begin();
474     ::std::deque< AttachedObject_Impl >::iterator aObjEnd = rList.end();
475     while( aObjIt != aObjEnd )
476     {
477         pMgr->detach( nIdx, (*aObjIt).xTarget );
478         aObjIt++;
479     }
480 }
481 
482 //-----------------------------------------------------------------------------
attachAll_Impl(ImplEventAttacherManager * pMgr,sal_Int32 nIdx,::std::deque<AttachedObject_Impl> & rList)483 void attachAll_Impl
484 (
485     ImplEventAttacherManager * pMgr,
486     sal_Int32 nIdx,
487     ::std::deque< AttachedObject_Impl > & rList
488 )
489 {
490     ::std::deque< AttachedObject_Impl >::iterator aObjIt =  rList.begin();
491     ::std::deque< AttachedObject_Impl >::iterator aObjEnd = rList.end();
492     while( aObjIt != aObjEnd )
493     {
494         pMgr->attach( nIdx, (*aObjIt).xTarget, (*aObjIt).aHelper );
495         aObjIt++;
496     }
497 }
498 
499 //-----------------------------------------------------------------------------
500 //*** Methoden von XEventAttacherManager ***
registerScriptEvent(sal_Int32 nIndex,const ScriptEventDescriptor & ScriptEvent)501 void SAL_CALL ImplEventAttacherManager::registerScriptEvent
502 (
503     sal_Int32 nIndex,
504     const ScriptEventDescriptor& ScriptEvent
505 )
506 {
507     Guard< Mutex > aGuard( aLock );
508 
509     // Index pruefen und Array anpassen
510     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
511 
512     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
513 
514     ScriptEventDescriptor aEvt = ScriptEvent;
515     const sal_Unicode* pLastDot = aEvt.ListenerType.getStr();
516     pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
517     if( pLastDot )
518         aEvt.ListenerType = pLastDot +1;
519 #ifdef DEQUE_OK
520     (*aIt).aEventList.push_back( aEvt );
521 #else
522     (*aIt).aEventList.realloc( (*aIt).aEventList.getLength() +1 );
523     (*aIt).aEventList.getArray()[(*aIt).aEventList.getLength() -1] = aEvt;
524 #endif
525 
526     // register new new Event
527     ::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.begin();
528     ::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end();
529     while( aObjIt != aObjEnd )
530     {
531         // resize
532         sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
533         (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
534         Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
535 
536         Reference< XAllListener > xAll =
537             new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
538         try
539         {
540         pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
541                         (*aObjIt).aHelper, ScriptEvent.ListenerType,
542                         ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
543         }
544         catch( Exception& )
545         {
546         }
547 
548         aObjIt++;
549     }
550 }
551 
552 //-----------------------------------------------------------------------------
registerScriptEvents(sal_Int32 nIndex,const Sequence<ScriptEventDescriptor> & ScriptEvents)553 void SAL_CALL ImplEventAttacherManager::registerScriptEvents
554 (
555     sal_Int32 nIndex,
556     const Sequence< ScriptEventDescriptor >& ScriptEvents
557 )
558 {
559     Guard< Mutex > aGuard( aLock );
560 
561     // Index pruefen und Array anpassen
562     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
563 
564     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
565     detachAll_Impl( this, nIndex, aList );
566 
567     const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
568     sal_Int32 nLen = ScriptEvents.getLength();
569     for( sal_Int32 i = 0 ; i < nLen ; i++ )
570         registerScriptEvent( nIndex, pArray[ i ] );
571 
572     attachAll_Impl( this, nIndex, aList );
573 }
574 
575 //-----------------------------------------------------------------------------
revokeScriptEvent(sal_Int32 nIndex,const OUString & ListenerType,const OUString & EventMethod,const OUString & ToRemoveListenerParam)576 void SAL_CALL ImplEventAttacherManager::revokeScriptEvent
577 (
578     sal_Int32 nIndex,
579     const OUString& ListenerType,
580     const OUString& EventMethod,
581     const OUString& ToRemoveListenerParam
582 )
583 {
584     Guard< Mutex > aGuard( aLock );
585 
586     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
587 
588     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
589     detachAll_Impl( this, nIndex, aList );
590 
591     OUString aLstType = ListenerType;
592     const sal_Unicode * pLastDot = aLstType.getStr();
593     pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
594     if( pLastDot )
595         aLstType = pLastDot +1;
596 
597 #ifdef DEQUE_OK
598     ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
599     ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
600     while( aEvtIt != aEvtEnd )
601     {
602         if( aLstType                == (*aEvtIt).ListenerType
603             && EventMethod          == (*aEvtIt).EventMethod
604             && ToRemoveListenerParam    == (*aEvtIt).AddListenerParam )
605         {
606             (*aIt).aEventList.erase( aEvtIt );
607             break;
608         }
609 
610         aEvtIt++;
611     }
612 #else
613     Sequence< ScriptEventDescriptor >& rEventList = (*aIt).aEventList;
614 
615             ScriptEventDescriptor* pEventList = rEventList.getArray();
616     const   ScriptEventDescriptor* pEventListEnd = pEventList + rEventList.getLength();
617     for( ; pEventList < pEventListEnd; ++pEventList )
618     {
619         if  (   (aLstType               == pEventList->ListenerType )
620             &&  (EventMethod            == pEventList->EventMethod      )
621             &&  (ToRemoveListenerParam  == pEventList->AddListenerParam)
622             )
623         {
624             ScriptEventDescriptor* pMoveTo = pEventList;
625             const ScriptEventDescriptor* pMoveFrom = pMoveTo + 1;
626             while (pMoveFrom < pEventListEnd)
627             {
628                 *pMoveTo++ = *pMoveFrom++;
629             }
630             rEventList.realloc( rEventList.getLength() - 1 );
631             break;
632         }
633     }
634 #endif
635     attachAll_Impl( this, nIndex, aList );
636 }
637 
638 //-----------------------------------------------------------------------------
revokeScriptEvents(sal_Int32 nIndex)639 void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
640 {
641     Guard< Mutex > aGuard( aLock );
642     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
643 
644     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
645     detachAll_Impl( this, nIndex, aList );
646 #ifdef DEQUE_OK
647     (*aIt).aEventList = ::std::deque< ScriptEventDescriptor >();
648 #else
649     (*aIt).aEventList.realloc( 0 );
650 #endif
651     attachAll_Impl( this, nIndex, aList );
652 }
653 
654 //-----------------------------------------------------------------------------
insertEntry(sal_Int32 nIndex)655 void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
656 {
657     Guard< Mutex > aGuard( aLock );
658     if( nIndex < 0 )
659         throw IllegalArgumentException();
660 
661 //  ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
662 //  while( nIndex-- )
663 //      aIt++;
664 
665     if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
666         aIndex.resize(nIndex+1);
667 
668     AttacherIndex_Impl aTmp;
669     aIndex.insert( aIndex.begin() + nIndex, aTmp );
670 }
671 
672 //-----------------------------------------------------------------------------
removeEntry(sal_Int32 nIndex)673 void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
674 {
675     Guard< Mutex > aGuard( aLock );
676     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
677 
678     ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
679     detachAll_Impl( this, nIndex, aList );
680     aIndex.erase( aIt );
681 }
682 
683 //-----------------------------------------------------------------------------
getScriptEvents(sal_Int32 nIndex)684 Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
685 {
686     Guard< Mutex > aGuard( aLock );
687     ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
688 
689 #ifdef DEQUE_OK
690     Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
691     ScriptEventDescriptor * pArray = aSeq.getArray();
692 
693     ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
694     ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
695     sal_Int32 i = 0;
696     while( aEvtIt != aEvtEnd )
697     {
698         pArray[i++] = *aEvtIt;
699         aEvtIt++;
700     }
701     return aSeq;
702 #else
703     return (*aIt).aEventList;
704 #endif
705 }
706 
707 //-----------------------------------------------------------------------------
attach(sal_Int32 nIndex,const Reference<XInterface> & xObject,const Any & Helper)708 void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
709 {
710     Guard< Mutex > aGuard( aLock );
711     if( nIndex < 0 || !xObject.is() )
712         throw IllegalArgumentException();
713 
714     if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
715     {
716         // alte Dateien lesen
717         if( nVersion == 1 )
718         {
719             insertEntry( nIndex );
720             attach( nIndex, xObject, Helper );
721             return;
722         }
723         else
724             throw IllegalArgumentException();
725     }
726 
727     ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
728 
729     AttachedObject_Impl aTmp;
730     aTmp.xTarget = xObject;
731     aTmp.aHelper = Helper;
732     aCurrentPosition->aObjList.push_back( aTmp );
733 
734     //::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back();
735     AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
736 #ifdef DEQUE_OK
737     rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
738 #else
739     rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.getLength() );
740 #endif
741     Reference< XEventListener > * pArray = rCurObj.aAttachedListenerSeq.getArray();
742 
743 #ifdef DEQUE_OK
744     ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
745     ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
746     sal_Int32 i = 0;
747     while( aEvtIt != aEvtEnd )
748     {
749         Reference< XAllListener > xAll =
750             new AttacherAllListener_Impl( this, (*aEvtIt).ScriptType, (*aEvtIt).ScriptCode );
751         Reference< XEventListener > xAdapter;
752         try
753         {
754         xAdapter = xAttacher->attachSingleEventListener( rCurObj.xTarget, xAll,
755                         rCurObj.aHelper, (*aEvtIt).ScriptType,
756                         (*aEvtIt).AddListenerParam, (*aEvtIt).EventMethod );
757         }
758         catch( Exception& )
759         {
760         }
761 
762         pArray[i++] = xAdapter;
763         aEvtIt++;
764     }
765 #else
766     sal_Int32 nLen = aCurrentPosition->aEventList.getLength();
767     ScriptEventDescriptor * pEL = aCurrentPosition->aEventList.getArray();
768     for(sal_Int32 i = 0; i < nLen; ++i )
769     {
770         Reference< XAllListener > xAll =
771             new AttacherAllListener_Impl( this, pEL[i].ScriptType, pEL[i].ScriptCode );
772         Reference< XEventListener > xAdapter;
773         try
774         {
775         xAdapter = xAttacher->attachSingleEventListener( rCurObj.xTarget, xAll,
776                         rCurObj.aHelper, pEL[i].ListenerType,
777                         pEL[i].AddListenerParam, pEL[i].EventMethod );
778         }
779         catch( Exception& )
780         {
781         }
782 
783         pArray[i] = xAdapter;
784     }
785 #endif
786 }
787 
788 //-----------------------------------------------------------------------------
detach(sal_Int32 nIndex,const Reference<XInterface> & xObject)789 void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
790 {
791     Guard< Mutex > aGuard( aLock );
792     //return;
793     if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
794         throw IllegalArgumentException();
795 
796     ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
797     ::std::deque< AttachedObject_Impl >::iterator aObjIt = aCurrentPosition->aObjList.begin();
798     ::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end();
799     while( aObjIt != aObjEnd )
800     {
801         if( (*aObjIt).xTarget == xObject )
802         {
803             Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
804 #ifdef DEQUE_OK
805 
806             ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
807             ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
808             sal_Int32 i = 0;
809             while( aEvtIt != aEvtEnd )
810             {
811                 if( pArray[i].is() )
812                 {
813                     try
814                     {
815                     xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
816                                                 (*aEvtIt).AddListenerParam, pArray[i] );
817                     }
818                     catch( Exception& )
819                     {
820                     }
821                 }
822                 i++;
823                 aEvtIt++;
824             }
825 #else
826             sal_Int32 nLen = aCurrentPosition->aEventList.getLength();
827             ScriptEventDescriptor * pEL = aCurrentPosition->aEventList.getArray();
828             for( sal_Int32 i = 0; i < nLen; i++ )
829             {
830                 if( pArray[i].is() )
831                 {
832                     try
833                     {
834                     xAttacher->removeListener( (*aObjIt).xTarget, pEL[i].ListenerType,
835                                                 pEL[i].AddListenerParam, pArray[i] );
836                     }
837                     catch( Exception& )
838                     {
839                     }
840                 }
841             }
842 #endif
843             aCurrentPosition->aObjList.erase( aObjIt );
844             break;
845         }
846         aObjIt++;
847     }
848 }
849 
addScriptListener(const Reference<XScriptListener> & aListener)850 void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
851 {
852     Guard< Mutex > aGuard( aLock );
853     aScriptListeners.addInterface( aListener );
854 }
855 
removeScriptListener(const Reference<XScriptListener> & aListener)856 void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
857 {
858     Guard< Mutex > aGuard( aLock );
859     aScriptListeners.removeInterface( aListener );
860 }
861 
862 
863 // Methoden von XPersistObject
getServiceName(void)864 OUString SAL_CALL ImplEventAttacherManager::getServiceName(void)
865 {
866     return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.script.EventAttacherManager") );
867 }
868 
write(const Reference<XObjectOutputStream> & OutStream)869 void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
870 {
871     Guard< Mutex > aGuard( aLock );
872     // Ohne XMarkableStream laeuft nichts
873     Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
874     if( !xMarkStream.is() )
875         return;
876 
877     // Version schreiben
878     OutStream->writeShort( 2 );
879 
880     // Position fuer Laenge merken
881     sal_Int32 nObjLenMark = xMarkStream->createMark();
882     OutStream->writeLong( 0L );
883 
884     OutStream->writeLong( aIndex.size() );
885 
886     // Sequences schreiben
887     ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
888     ::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end();
889     while( aIt != aEnd )
890     {
891 #ifdef DEQUE_OK
892         // Laenge der Sequence und alle Descriptoren schreiben
893         OutStream->writeLong( (*aIt).aEventList.size() );
894         ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
895         ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
896         while( aEvtIt != aEvtEnd )
897         {
898             const ScriptEventDescriptor& rDesc = (*aEvtIt);
899             OutStream->writeUTF( rDesc.ListenerType );
900             OutStream->writeUTF( rDesc.EventMethod );
901             OutStream->writeUTF( rDesc.AddListenerParam );
902             OutStream->writeUTF( rDesc.ScriptType );
903             OutStream->writeUTF( rDesc.ScriptCode );
904 
905             aEvtIt++;
906         }
907 #else
908         sal_Int32 nLen = (*aIt).aEventList.getLength();
909         // Laenge der Sequence und alle Descriptoren schreiben
910         OutStream->writeLong( nLen );
911         ScriptEventDescriptor * pEL = (*aIt).aEventList.getArray();
912         for( sal_Int32 i = 0; i < nLen; i++ )
913         {
914             const ScriptEventDescriptor& rDesc = pEL[i];
915             OutStream->writeUTF( rDesc.ListenerType );
916             OutStream->writeUTF( rDesc.EventMethod );
917             OutStream->writeUTF( rDesc.AddListenerParam );
918             OutStream->writeUTF( rDesc.ScriptType );
919             OutStream->writeUTF( rDesc.ScriptCode );
920         }
921 #endif
922         aIt++;
923     }
924 
925     // Die jetzt bekannte Laenge eintragen
926     sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
927     xMarkStream->jumpToMark( nObjLenMark );
928     OutStream->writeLong( nObjLen );
929     xMarkStream->jumpToFurthest();
930     xMarkStream->deleteMark( nObjLenMark );
931 }
932 
read(const Reference<XObjectInputStream> & InStream)933 void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
934 {
935     Guard< Mutex > aGuard( aLock );
936     // Ohne XMarkableStream laeuft nichts
937     Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
938     if( !xMarkStream.is() )
939         return;
940 
941     // Version lesen
942     nVersion = InStream->readShort();
943 
944     // Zunaechst kommen die Daten gemaess Version 1,
945     // muss auch bei hoeheren Versionen beibehalten werden
946     sal_Int32 nLen = InStream->readLong();
947 
948     // Position fuer Vergleichszwecke
949     sal_Int32 nObjLenMark = xMarkStream->createMark();
950 
951     // Anzahl der zu lesenden Sequences
952     sal_Int32 nItemCount = InStream->readLong();
953 
954     for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
955     {
956         insertEntry( i );
957         // Laenge der Sequence lesen
958         sal_Int32 nSeqLen = InStream->readLong();
959 
960         // Sequence anlegen und Descriptoren lesen
961         Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
962         ScriptEventDescriptor* pArray = aSEDSeq.getArray();
963         for( sal_Int32 j = 0 ; j < nSeqLen ; j++ )
964         {
965             ScriptEventDescriptor& rDesc = pArray[ j ];
966             rDesc.ListenerType = InStream->readUTF();
967             rDesc.EventMethod = InStream->readUTF();
968             rDesc.AddListenerParam = InStream->readUTF();
969             rDesc.ScriptType = InStream->readUTF();
970             rDesc.ScriptCode = InStream->readUTF();
971         }
972         registerScriptEvents( i, aSEDSeq );
973     }
974 
975     // Haben wir die angegebene Laenge gelesen?
976     sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
977     if( nRealLen != nLen )
978     {
979         // Nur wenn die StreamVersion > 1 ist und noch Daten folgen, kann das
980         // Ganze richtig sein. Sonst ist etwas voellig daneben gegangen.
981         if( nRealLen > nLen || nVersion == 1 )
982         {
983             VOS_ENSHURE( sal_False, "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
984         }
985         else
986         {
987             // TODO: Pruefen, ob Zwischen-Speicherung der Daten sinnvoll sein koennte
988 
989             // Vorerst einfach nur Skippen
990             sal_Int32 nSkipCount = nLen - nRealLen;
991             InStream->skipBytes( nSkipCount );
992         }
993     }
994     xMarkStream->jumpToFurthest();
995     xMarkStream->deleteMark( nObjLenMark );
996 }
997 
998 } // namespace comphelper
999