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