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