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