Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #if defined( UNX )
22 : #include <wchar.h>
23 : #endif
24 : #include <osl/mutex.hxx>
25 : #include <osl/diagnose.h>
26 : #include <comphelper/eventattachermgr.hxx>
27 : #include <comphelper/processfactory.hxx>
28 : #include <com/sun/star/beans/Introspection.hpp>
29 : #include <com/sun/star/io/XObjectInputStream.hpp>
30 : #include <com/sun/star/io/XPersistObject.hpp>
31 : #include <com/sun/star/io/XObjectOutputStream.hpp>
32 : #include <com/sun/star/io/XMarkableStream.hpp>
33 : #include <com/sun/star/lang/XInitialization.hpp>
34 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 : #include <com/sun/star/reflection/theCoreReflection.hpp>
36 : #include <com/sun/star/reflection/XIdlClass.hpp>
37 : #include <com/sun/star/reflection/XIdlReflection.hpp>
38 : #include <com/sun/star/reflection/XIdlMethod.hpp>
39 : #include <com/sun/star/script/Converter.hpp>
40 : #include <com/sun/star/script/XEngineListener.hpp>
41 : #include <com/sun/star/script/XEventAttacher2.hpp>
42 : #include <com/sun/star/script/XEventAttacherManager.hpp>
43 : #include <com/sun/star/script/XScriptListener.hpp>
44 : #include <cppuhelper/weak.hxx>
45 : #include <cppuhelper/interfacecontainer.hxx>
46 : #include <cppuhelper/implbase1.hxx>
47 : #include <cppuhelper/implbase2.hxx>
48 :
49 : #include <deque>
50 : #include <algorithm>
51 : #include <functional>
52 :
53 : using namespace com::sun::star::uno;
54 : using namespace com::sun::star::io;
55 : using namespace com::sun::star::lang;
56 : using namespace com::sun::star::beans;
57 : using namespace com::sun::star::script;
58 : using namespace com::sun::star::reflection;
59 : using namespace cppu;
60 : using namespace osl;
61 :
62 :
63 : namespace comphelper
64 : {
65 :
66 : //-----------------------------------------------------------------------------
67 4119 : struct AttachedObject_Impl
68 : {
69 : Reference< XInterface > xTarget;
70 : Sequence< Reference< XEventListener > > aAttachedListenerSeq;
71 : Any aHelper;
72 :
73 : bool operator<( const AttachedObject_Impl & ) const;
74 : bool operator==( const AttachedObject_Impl & ) const;
75 : };
76 :
77 3407 : struct AttacherIndex_Impl
78 : {
79 : ::std::deque< ScriptEventDescriptor > aEventList;
80 : ::std::deque< AttachedObject_Impl > aObjList;
81 :
82 : bool operator<( const AttacherIndex_Impl & ) const;
83 : bool operator==( const AttacherIndex_Impl & ) const;
84 : };
85 :
86 : //-----------------------------------------------------------------------------
87 : class ImplEventAttacherManager
88 : : public WeakImplHelper2< XEventAttacherManager, XPersistObject >
89 : {
90 : friend class AttacherAllListener_Impl;
91 : ::std::deque< AttacherIndex_Impl > aIndex;
92 : Mutex aLock;
93 : // Container for the ScriptListener
94 : OInterfaceContainerHelper aScriptListeners;
95 : // Instance of EventAttacher
96 : Reference< XEventAttacher2 > xAttacher;
97 : Reference< XComponentContext > mxContext;
98 : Reference< XIdlReflection > mxCoreReflection;
99 : Reference< XIntrospection > mxIntrospection;
100 : Reference< XTypeConverter > xConverter;
101 : sal_Int16 nVersion;
102 : public:
103 : ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
104 : const Reference< XComponentContext > xContext );
105 : ~ImplEventAttacherManager();
106 :
107 : // Methods of XEventAttacherManager
108 : virtual void SAL_CALL registerScriptEvent(sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent)
109 : throw( IllegalArgumentException, RuntimeException );
110 : virtual void SAL_CALL registerScriptEvents(sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents)
111 : throw( IllegalArgumentException, RuntimeException );
112 : virtual void SAL_CALL revokeScriptEvent(sal_Int32 Index, const OUString& ListenerType, const OUString& EventMethod, const OUString& removeListenerParam)
113 : throw( IllegalArgumentException, RuntimeException );
114 : virtual void SAL_CALL revokeScriptEvents(sal_Int32 Index)
115 : throw( IllegalArgumentException, RuntimeException );
116 : virtual void SAL_CALL insertEntry(sal_Int32 Index)
117 : throw( IllegalArgumentException, RuntimeException );
118 : virtual void SAL_CALL removeEntry(sal_Int32 Index)
119 : throw( IllegalArgumentException, RuntimeException );
120 : virtual Sequence< ScriptEventDescriptor > SAL_CALL getScriptEvents(sal_Int32 Index)
121 : throw( IllegalArgumentException, RuntimeException );
122 : virtual void SAL_CALL attach(sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper)
123 : throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException );
124 : virtual void SAL_CALL detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
125 : throw( IllegalArgumentException, RuntimeException );
126 : virtual void SAL_CALL addScriptListener(const Reference< XScriptListener >& aListener)
127 : throw( IllegalArgumentException, RuntimeException );
128 : virtual void SAL_CALL removeScriptListener(const Reference< XScriptListener >& Listener)
129 : throw( IllegalArgumentException, RuntimeException );
130 :
131 : // Methods of XPersistObject
132 : virtual OUString SAL_CALL getServiceName(void) throw( RuntimeException );
133 : virtual void SAL_CALL write(const Reference< XObjectOutputStream >& OutStream) throw( IOException, RuntimeException );
134 : virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) throw( IOException, RuntimeException );
135 :
136 : private:
137 : Reference< XIdlReflection > getReflection() throw( Exception );
138 :
139 : /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not
140 : @param _nIndex
141 : the index to check
142 : @return
143 : the iterator pointing to the position indicated by the index
144 : */
145 : ::std::deque<AttacherIndex_Impl>::iterator implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) );
146 : };
147 :
148 : //========================================================================
149 : //========================================================================
150 : //========================================================================
151 :
152 :
153 : // Implementation of an EventAttacher-subclass 'AllListeners', which
154 : // only passes individual events of the general AllListeners.
155 78 : class AttacherAllListener_Impl : public WeakImplHelper1< XAllListener >
156 : {
157 : ImplEventAttacherManager* mpManager;
158 : Reference< XEventAttacherManager > xManager;
159 : OUString aScriptType;
160 : OUString aScriptCode;
161 :
162 : void convertToEventReturn( Any & rRet, const Type & rRetType )
163 : throw( CannotConvertException );
164 : public:
165 : AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_,
166 : const OUString & rScriptCode_ );
167 :
168 : // Methods of XAllListener
169 : virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException );
170 : virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException );
171 :
172 : // Methods of XEventListener
173 : virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
174 : };
175 :
176 : //========================================================================
177 39 : AttacherAllListener_Impl::AttacherAllListener_Impl
178 : (
179 : ImplEventAttacherManager* pManager_,
180 : const OUString & rScriptType_,
181 : const OUString & rScriptCode_
182 : )
183 : : mpManager( pManager_ )
184 : , xManager( pManager_ )
185 : , aScriptType( rScriptType_ )
186 39 : , aScriptCode( rScriptCode_ )
187 : {
188 39 : }
189 :
190 :
191 : //========================================================================
192 : // Methods of XAllListener
193 1 : void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
194 : throw( RuntimeException )
195 : {
196 1 : ScriptEvent aScriptEvent;
197 1 : aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface
198 1 : aScriptEvent.ListenerType = Event.ListenerType;
199 1 : aScriptEvent.MethodName = Event.MethodName;
200 1 : aScriptEvent.Arguments = Event.Arguments;
201 1 : aScriptEvent.Helper = Event.Helper;
202 1 : aScriptEvent.ScriptType = aScriptType;
203 1 : aScriptEvent.ScriptCode = aScriptCode;
204 :
205 : // Iterate over all listeners and pass events.
206 2 : OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
207 4 : while( aIt.hasMoreElements() )
208 3 : ((XScriptListener *)aIt.next())->firing( aScriptEvent );
209 1 : }
210 :
211 : //========================================================================
212 : // Convert to the standard event return
213 0 : void AttacherAllListener_Impl::convertToEventReturn( Any & rRet, const Type & rRetType )
214 : throw( CannotConvertException )
215 : {
216 : // no return value? Set to the specified values
217 0 : if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
218 : {
219 0 : switch( rRetType.getTypeClass() )
220 : {
221 : case TypeClass_INTERFACE:
222 : {
223 0 : rRet <<= Reference< XInterface >();
224 : }
225 0 : break;
226 :
227 : case TypeClass_BOOLEAN:
228 0 : rRet <<= sal_True;
229 0 : break;
230 :
231 : case TypeClass_STRING:
232 0 : rRet <<= OUString();
233 0 : break;
234 :
235 0 : case TypeClass_FLOAT: rRet <<= float(0); break;
236 0 : case TypeClass_DOUBLE: rRet <<= double(0.0); break;
237 0 : case TypeClass_BYTE: rRet <<= sal_uInt8(0); break;
238 0 : case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
239 0 : case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
240 0 : case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
241 0 : case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
242 :
243 : default:
244 : OSL_ASSERT(false);
245 0 : break;
246 : }
247 : }
248 0 : else if( !rRet.getValueType().equals( rRetType ) )
249 : {
250 0 : if( mpManager->xConverter.is() )
251 0 : rRet = mpManager->xConverter->convertTo( rRet, rRetType );
252 : else
253 0 : throw CannotConvertException();
254 : }
255 0 : }
256 :
257 : //========================================================================
258 : // Methods of XAllListener
259 0 : Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Event )
260 : throw( InvocationTargetException, RuntimeException )
261 : {
262 0 : ScriptEvent aScriptEvent;
263 0 : aScriptEvent.Source = (OWeakObject *)mpManager; // get correct XInterface
264 0 : aScriptEvent.ListenerType = Event.ListenerType;
265 0 : aScriptEvent.MethodName = Event.MethodName;
266 0 : aScriptEvent.Arguments = Event.Arguments;
267 0 : aScriptEvent.Helper = Event.Helper;
268 0 : aScriptEvent.ScriptType = aScriptType;
269 0 : aScriptEvent.ScriptCode = aScriptCode;
270 :
271 0 : Any aRet;
272 : // Iterate over all listeners and pass events.
273 0 : OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
274 0 : while( aIt.hasMoreElements() )
275 : {
276 0 : aRet = ((XScriptListener *)aIt.next())->approveFiring( aScriptEvent );
277 : try
278 : {
279 0 : Reference< XIdlClass > xListenerType = mpManager->getReflection()->
280 0 : forName( Event.ListenerType.getTypeName() );
281 0 : Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
282 0 : if( xMeth.is() )
283 : {
284 0 : Reference< XIdlClass > xRetType = xMeth->getReturnType();
285 0 : Type aRetType(xRetType->getTypeClass(), xRetType->getName());
286 0 : convertToEventReturn( aRet, aRetType );
287 : }
288 :
289 0 : switch( aRet.getValueType().getTypeClass() )
290 : {
291 : case TypeClass_INTERFACE:
292 : {
293 : // Interface not null, return
294 0 : Reference< XInterface > x;
295 0 : aRet >>= x;
296 0 : if( x.is() )
297 0 : return aRet;
298 : }
299 0 : break;
300 :
301 : case TypeClass_BOOLEAN:
302 : // FALSE -> Return
303 0 : if( !(*(sal_Bool*)aRet.getValue()) )
304 0 : return aRet;
305 0 : break;
306 :
307 : case TypeClass_STRING:
308 : // none empty string -> return
309 0 : if( !((OUString*)aRet.getValue())->isEmpty() )
310 0 : return aRet;
311 0 : break;
312 :
313 : // none zero number -> return
314 0 : case TypeClass_FLOAT: if( *((float*)aRet.getValue()) ) return aRet; break;
315 0 : case TypeClass_DOUBLE: if( *((double*)aRet.getValue()) ) return aRet; break;
316 0 : case TypeClass_BYTE: if( *((sal_uInt8*)aRet.getValue()) ) return aRet; break;
317 0 : case TypeClass_SHORT: if( *((sal_Int16*)aRet.getValue()) ) return aRet; break;
318 0 : case TypeClass_LONG: if( *((sal_Int32*)aRet.getValue()) ) return aRet; break;
319 0 : case TypeClass_UNSIGNED_SHORT: if( *((sal_uInt16*)aRet.getValue()) ) return aRet; break;
320 0 : case TypeClass_UNSIGNED_LONG: if( *((sal_uInt32*)aRet.getValue()) ) return aRet; break;
321 :
322 : default:
323 : OSL_ASSERT(false);
324 0 : break;
325 0 : }
326 : }
327 0 : catch( CannotConvertException& )
328 : {
329 : // silent ignore conversions errors from a script call
330 0 : Reference< XIdlClass > xListenerType = mpManager->getReflection()->
331 0 : forName( Event.ListenerType.getTypeName() );
332 0 : Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
333 0 : if( xMeth.is() )
334 : {
335 0 : Reference< XIdlClass > xRetType = xMeth->getReturnType();
336 0 : Type aRetType(xRetType->getTypeClass(), xRetType->getName());
337 0 : aRet.clear();
338 0 : convertToEventReturn( aRet, aRetType );
339 0 : }
340 : }
341 : }
342 0 : return aRet;
343 : }
344 :
345 : //========================================================================
346 : // Methods of XEventListener
347 0 : void SAL_CALL AttacherAllListener_Impl::disposing(const EventObject& )
348 : throw( RuntimeException )
349 : {
350 : // It is up to the container to release the object
351 0 : }
352 :
353 :
354 : // Constructor method for EventAttacherManager
355 394 : Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XComponentContext > & rxContext )
356 : throw( Exception )
357 : {
358 394 : Reference< XIntrospection > xIntrospection = Introspection::create( rxContext );
359 394 : return new ImplEventAttacherManager( xIntrospection, rxContext );
360 : }
361 :
362 : //-----------------------------------------------------------------------------
363 394 : ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
364 : const Reference< XComponentContext > xContext )
365 : : aScriptListeners( aLock )
366 : , mxContext( xContext )
367 394 : , mxIntrospection( rIntrospection )
368 : {
369 394 : if ( xContext.is() )
370 : {
371 788 : Reference< XInterface > xIFace( xContext->getServiceManager()->createInstanceWithContext(
372 394 : OUString( "com.sun.star.script.EventAttacher" ), xContext) );
373 394 : if ( xIFace.is() )
374 : {
375 341 : xAttacher = Reference< XEventAttacher2 >::query( xIFace );
376 : }
377 394 : xConverter = Converter::create(xContext);
378 : }
379 :
380 394 : Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
381 394 : if( xInit.is() )
382 : {
383 341 : Sequence< Any > Arguments( 1 );
384 341 : Arguments[0] <<= rIntrospection;
385 341 : xInit->initialize( Arguments );
386 394 : }
387 394 : }
388 :
389 : //-----------------------------------------------------------------------------
390 776 : ImplEventAttacherManager::~ImplEventAttacherManager()
391 : {
392 776 : }
393 :
394 0 : Reference< XIdlReflection > ImplEventAttacherManager::getReflection() throw( Exception )
395 : {
396 0 : Guard< Mutex > aGuard( aLock );
397 : // Do we already have a service? If not, create one.
398 0 : if( !mxCoreReflection.is() )
399 : {
400 0 : mxCoreReflection = theCoreReflection::get(mxContext);
401 : }
402 0 : return mxCoreReflection;
403 : }
404 :
405 :
406 : //-----------------------------------------------------------------------------
407 776 : ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex ) SAL_THROW ( ( IllegalArgumentException ) )
408 : {
409 776 : if (_nIndex < 0)
410 0 : throw IllegalArgumentException();
411 :
412 776 : ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
413 776 : for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
414 : ;
415 :
416 776 : if( aIt == aIndex.end() )
417 0 : throw IllegalArgumentException();
418 :
419 776 : return aIt;
420 : }
421 :
422 : namespace {
423 :
424 : class DetachObject : public std::unary_function<AttachedObject_Impl, void>
425 : {
426 : ImplEventAttacherManager& mrMgr;
427 : sal_Int32 mnIdx;
428 : public:
429 741 : DetachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
430 741 : mrMgr(rMgr), mnIdx(nIdx) {}
431 :
432 259 : void operator() (AttachedObject_Impl& rObj)
433 : {
434 259 : mrMgr.detach(mnIdx, rObj.xTarget);
435 259 : }
436 : };
437 :
438 : class AttachObject : public std::unary_function<AttachedObject_Impl, void>
439 : {
440 : ImplEventAttacherManager& mrMgr;
441 : sal_Int32 mnIdx;
442 : public:
443 250 : AttachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
444 250 : mrMgr(rMgr), mnIdx(nIdx) {}
445 :
446 244 : void operator() (AttachedObject_Impl& rObj)
447 : {
448 244 : mrMgr.attach(mnIdx, rObj.xTarget, rObj.aHelper);
449 244 : }
450 : };
451 :
452 : }
453 :
454 : //-----------------------------------------------------------------------------
455 : // Methods of XEventAttacherManager
456 22 : void SAL_CALL ImplEventAttacherManager::registerScriptEvent
457 : (
458 : sal_Int32 nIndex,
459 : const ScriptEventDescriptor& ScriptEvent
460 : )
461 : throw( IllegalArgumentException, RuntimeException )
462 : {
463 22 : Guard< Mutex > aGuard( aLock );
464 :
465 : // Examine the index and apply the array
466 22 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
467 :
468 44 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
469 :
470 44 : ScriptEventDescriptor aEvt = ScriptEvent;
471 22 : const sal_Unicode* pLastDot = aEvt.ListenerType.getStr();
472 22 : pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
473 22 : if( pLastDot )
474 22 : aEvt.ListenerType = pLastDot +1;
475 22 : (*aIt).aEventList.push_back( aEvt );
476 :
477 : // register new new Event
478 22 : ::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.begin();
479 22 : ::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end();
480 46 : while( aObjIt != aObjEnd )
481 : {
482 : // resize
483 2 : sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
484 2 : (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
485 2 : Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
486 :
487 : Reference< XAllListener > xAll =
488 2 : new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
489 : try
490 : {
491 8 : pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
492 2 : (*aObjIt).aHelper, ScriptEvent.ListenerType,
493 4 : ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
494 : }
495 0 : catch( Exception& )
496 : {
497 : }
498 :
499 2 : ++aObjIt;
500 24 : }
501 22 : }
502 :
503 : //-----------------------------------------------------------------------------
504 246 : void SAL_CALL ImplEventAttacherManager::registerScriptEvents
505 : (
506 : sal_Int32 nIndex,
507 : const Sequence< ScriptEventDescriptor >& ScriptEvents
508 : )
509 : throw( IllegalArgumentException, RuntimeException )
510 : {
511 246 : Guard< Mutex > aGuard( aLock );
512 :
513 : // Examine the index and apply the array
514 246 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
515 :
516 492 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
517 246 : ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
518 :
519 246 : const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
520 246 : sal_Int32 nLen = ScriptEvents.getLength();
521 265 : for( sal_Int32 i = 0 ; i < nLen ; i++ )
522 19 : registerScriptEvent( nIndex, pArray[ i ] );
523 :
524 492 : ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
525 246 : }
526 :
527 : //-----------------------------------------------------------------------------
528 1 : void SAL_CALL ImplEventAttacherManager::revokeScriptEvent
529 : (
530 : sal_Int32 nIndex,
531 : const OUString& ListenerType,
532 : const OUString& EventMethod,
533 : const OUString& ToRemoveListenerParam
534 : )
535 : throw( IllegalArgumentException, RuntimeException )
536 : {
537 1 : Guard< Mutex > aGuard( aLock );
538 :
539 1 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
540 :
541 2 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
542 1 : ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
543 :
544 2 : OUString aLstType = ListenerType;
545 1 : const sal_Unicode * pLastDot = aLstType.getStr();
546 1 : pLastDot += rtl_ustr_lastIndexOfChar( pLastDot, '.' );
547 1 : if( pLastDot )
548 1 : aLstType = pLastDot +1;
549 :
550 1 : ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
551 1 : ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
552 2 : while( aEvtIt != aEvtEnd )
553 : {
554 2 : if( aLstType == (*aEvtIt).ListenerType
555 1 : && EventMethod == (*aEvtIt).EventMethod
556 2 : && ToRemoveListenerParam == (*aEvtIt).AddListenerParam )
557 : {
558 1 : (*aIt).aEventList.erase( aEvtIt );
559 1 : break;
560 : }
561 :
562 0 : ++aEvtIt;
563 : }
564 2 : ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
565 1 : }
566 :
567 : //-----------------------------------------------------------------------------
568 3 : void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
569 : throw( IllegalArgumentException, RuntimeException )
570 : {
571 3 : Guard< Mutex > aGuard( aLock );
572 3 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
573 :
574 6 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
575 3 : ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
576 3 : (*aIt).aEventList.clear();
577 6 : ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
578 3 : }
579 :
580 : //-----------------------------------------------------------------------------
581 514 : void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
582 : throw( IllegalArgumentException, RuntimeException )
583 : {
584 514 : Guard< Mutex > aGuard( aLock );
585 514 : if( nIndex < 0 )
586 0 : throw IllegalArgumentException();
587 :
588 514 : if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
589 323 : aIndex.resize(nIndex+1);
590 :
591 1028 : AttacherIndex_Impl aTmp;
592 1028 : aIndex.insert( aIndex.begin() + nIndex, aTmp );
593 514 : }
594 :
595 : //-----------------------------------------------------------------------------
596 491 : void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
597 : throw( IllegalArgumentException, RuntimeException )
598 : {
599 491 : Guard< Mutex > aGuard( aLock );
600 491 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
601 :
602 982 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
603 491 : ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
604 982 : aIndex.erase( aIt );
605 491 : }
606 :
607 : //-----------------------------------------------------------------------------
608 13 : Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
609 : throw( IllegalArgumentException, RuntimeException )
610 : {
611 13 : Guard< Mutex > aGuard( aLock );
612 13 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
613 :
614 13 : Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
615 13 : ScriptEventDescriptor * pArray = aSeq.getArray();
616 :
617 13 : ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
618 13 : ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
619 13 : sal_Int32 i = 0;
620 32 : while( aEvtIt != aEvtEnd )
621 : {
622 6 : pArray[i++] = *aEvtIt;
623 6 : ++aEvtIt;
624 : }
625 13 : return aSeq;
626 : }
627 :
628 : //-----------------------------------------------------------------------------
629 899 : void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
630 : throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException )
631 : {
632 899 : Guard< Mutex > aGuard( aLock );
633 899 : if( nIndex < 0 || !xObject.is() )
634 0 : throw IllegalArgumentException();
635 :
636 899 : if( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
637 : {
638 : // read older files
639 0 : if( nVersion == 1 )
640 : {
641 0 : insertEntry( nIndex );
642 0 : attach( nIndex, xObject, Helper );
643 0 : return;
644 : }
645 : else
646 0 : throw IllegalArgumentException();
647 : }
648 :
649 899 : ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
650 :
651 916 : AttachedObject_Impl aTmp;
652 899 : aTmp.xTarget = xObject;
653 899 : aTmp.aHelper = Helper;
654 899 : aCurrentPosition->aObjList.push_back( aTmp );
655 :
656 : //::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back();
657 899 : AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
658 899 : rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
659 :
660 899 : if (aCurrentPosition->aEventList.empty())
661 882 : return;
662 :
663 34 : Sequence<com::sun::star::script::EventListener> aEvents(aCurrentPosition->aEventList.size());
664 17 : std::deque<ScriptEventDescriptor>::iterator itr = aCurrentPosition->aEventList.begin();
665 17 : std::deque<ScriptEventDescriptor>::iterator itrEnd = aCurrentPosition->aEventList.end();
666 17 : ::com::sun::star::script::EventListener* p = aEvents.getArray();
667 17 : size_t i = 0;
668 54 : for (; itr != itrEnd; ++itr)
669 : {
670 37 : com::sun::star::script::EventListener aListener;
671 111 : aListener.AllListener =
672 148 : new AttacherAllListener_Impl(this, itr->ScriptType, itr->ScriptCode);
673 37 : aListener.Helper = rCurObj.aHelper;
674 37 : aListener.ListenerType = itr->ListenerType;
675 37 : aListener.EventMethod = itr->EventMethod;
676 37 : aListener.AddListenerParam = itr->AddListenerParam;
677 37 : p[i++] = aListener;
678 37 : }
679 :
680 : try
681 : {
682 34 : rCurObj.aAttachedListenerSeq =
683 34 : xAttacher->attachMultipleEventListeners(rCurObj.xTarget, aEvents);
684 : }
685 0 : catch (const Exception&)
686 : {
687 : // Fail gracefully.
688 17 : }
689 : }
690 :
691 : //-----------------------------------------------------------------------------
692 892 : void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
693 : throw( IllegalArgumentException, RuntimeException )
694 : {
695 892 : Guard< Mutex > aGuard( aLock );
696 : //return;
697 892 : if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
698 0 : throw IllegalArgumentException();
699 :
700 892 : ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
701 892 : ::std::deque< AttachedObject_Impl >::iterator aObjIt = aCurrentPosition->aObjList.begin();
702 892 : ::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end();
703 1949 : while( aObjIt != aObjEnd )
704 : {
705 1042 : if( (*aObjIt).xTarget == xObject )
706 : {
707 877 : Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
708 :
709 877 : ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
710 877 : ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
711 877 : sal_Int32 i = 0;
712 1793 : while( aEvtIt != aEvtEnd )
713 : {
714 39 : if( pArray[i].is() )
715 : {
716 : try
717 : {
718 57 : xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
719 57 : (*aEvtIt).AddListenerParam, pArray[i] );
720 : }
721 0 : catch( Exception& )
722 : {
723 : }
724 : }
725 39 : i++;
726 39 : ++aEvtIt;
727 : }
728 877 : aCurrentPosition->aObjList.erase( aObjIt );
729 877 : break;
730 : }
731 165 : ++aObjIt;
732 892 : }
733 892 : }
734 :
735 757 : void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
736 : throw( IllegalArgumentException, RuntimeException )
737 : {
738 757 : Guard< Mutex > aGuard( aLock );
739 757 : aScriptListeners.addInterface( aListener );
740 757 : }
741 :
742 753 : void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
743 : throw( IllegalArgumentException, RuntimeException )
744 : {
745 753 : Guard< Mutex > aGuard( aLock );
746 753 : aScriptListeners.removeInterface( aListener );
747 753 : }
748 :
749 :
750 : // Methods of XPersistObject
751 0 : OUString SAL_CALL ImplEventAttacherManager::getServiceName(void)
752 : throw( RuntimeException )
753 : {
754 0 : return OUString( "com.sun.star.uno.script.EventAttacherManager" );
755 : }
756 :
757 1 : void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
758 : throw( IOException, RuntimeException )
759 : {
760 1 : Guard< Mutex > aGuard( aLock );
761 : // Don't run without XMarkableStream
762 2 : Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
763 1 : if( !xMarkStream.is() )
764 1 : return;
765 :
766 : // Write out the version
767 1 : OutStream->writeShort( 2 );
768 :
769 : // Remember position for length
770 1 : sal_Int32 nObjLenMark = xMarkStream->createMark();
771 1 : OutStream->writeLong( 0L );
772 :
773 1 : OutStream->writeLong( aIndex.size() );
774 :
775 : // Write out sequences
776 1 : ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
777 1 : ::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end();
778 5 : while( aIt != aEnd )
779 : {
780 : // Write out the length of the sequence and all descriptions
781 3 : OutStream->writeLong( (*aIt).aEventList.size() );
782 3 : ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
783 3 : ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
784 6 : while( aEvtIt != aEvtEnd )
785 : {
786 0 : const ScriptEventDescriptor& rDesc = (*aEvtIt);
787 0 : OutStream->writeUTF( rDesc.ListenerType );
788 0 : OutStream->writeUTF( rDesc.EventMethod );
789 0 : OutStream->writeUTF( rDesc.AddListenerParam );
790 0 : OutStream->writeUTF( rDesc.ScriptType );
791 0 : OutStream->writeUTF( rDesc.ScriptCode );
792 :
793 0 : ++aEvtIt;
794 : }
795 3 : ++aIt;
796 : }
797 :
798 : // The length is now known
799 1 : sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
800 1 : xMarkStream->jumpToMark( nObjLenMark );
801 1 : OutStream->writeLong( nObjLen );
802 1 : xMarkStream->jumpToFurthest();
803 2 : xMarkStream->deleteMark( nObjLenMark );
804 : }
805 :
806 1 : void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
807 : throw( IOException, RuntimeException )
808 : {
809 1 : Guard< Mutex > aGuard( aLock );
810 : // Don't run without XMarkableStream
811 2 : Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
812 1 : if( !xMarkStream.is() )
813 1 : return;
814 :
815 : // Read in the version
816 1 : nVersion = InStream->readShort();
817 :
818 : // At first there's the data according to version 1 --
819 : // this part needs to be kept in later versions.
820 1 : sal_Int32 nLen = InStream->readLong();
821 :
822 : // Position for comparative purposes
823 1 : sal_Int32 nObjLenMark = xMarkStream->createMark();
824 :
825 : // Number of read sequences
826 1 : sal_Int32 nItemCount = InStream->readLong();
827 :
828 4 : for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
829 : {
830 3 : insertEntry( i );
831 : // Read the length of the sequence
832 3 : sal_Int32 nSeqLen = InStream->readLong();
833 :
834 : // Display the sequences and read the descriptions
835 3 : Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
836 3 : ScriptEventDescriptor* pArray = aSEDSeq.getArray();
837 3 : for( sal_Int32 j = 0 ; j < nSeqLen ; j++ )
838 : {
839 0 : ScriptEventDescriptor& rDesc = pArray[ j ];
840 0 : rDesc.ListenerType = InStream->readUTF();
841 0 : rDesc.EventMethod = InStream->readUTF();
842 0 : rDesc.AddListenerParam = InStream->readUTF();
843 0 : rDesc.ScriptType = InStream->readUTF();
844 0 : rDesc.ScriptCode = InStream->readUTF();
845 : }
846 3 : registerScriptEvents( i, aSEDSeq );
847 3 : }
848 :
849 : // Have we read the specified length?
850 1 : sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
851 1 : if( nRealLen != nLen )
852 : {
853 : // Only if the StreamVersion is > 1 and the date still follows, can
854 : // this be true. Otherwise, something is completely gone.
855 0 : if( nRealLen > nLen || nVersion == 1 )
856 : {
857 : OSL_FAIL( "ImplEventAttacherManager::read(): Fatal Error, wrong object length" );
858 : }
859 : else
860 : { // TODO: Examine if caching the dates would be useful
861 : // But for now, it's easier to skip it.
862 0 : sal_Int32 nSkipCount = nLen - nRealLen;
863 0 : InStream->skipBytes( nSkipCount );
864 : }
865 : }
866 1 : xMarkStream->jumpToFurthest();
867 2 : xMarkStream->deleteMark( nObjLenMark );
868 : }
869 :
870 : } // namesapce comphelper
871 :
872 :
873 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|