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 
1032 
1033