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