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 4677 : struct AttachedObject_Impl
65 : {
66 : Reference< XInterface > xTarget;
67 : Sequence< Reference< XEventListener > > aAttachedListenerSeq;
68 : Any aHelper;
69 : };
70 :
71 3730 : 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 >& rContext );
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() 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 82 : 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 41 : 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 41 : , aScriptCode( rScriptCode_ )
178 : {
179 41 : }
180 :
181 :
182 :
183 : // Methods of XAllListener
184 1 : void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
185 : throw( RuntimeException, std::exception )
186 : {
187 1 : ScriptEvent aScriptEvent;
188 1 : aScriptEvent.Source = static_cast<OWeakObject *>(mpManager); // get correct XInterface
189 1 : aScriptEvent.ListenerType = Event.ListenerType;
190 1 : aScriptEvent.MethodName = Event.MethodName;
191 1 : aScriptEvent.Arguments = Event.Arguments;
192 1 : aScriptEvent.Helper = Event.Helper;
193 1 : aScriptEvent.ScriptType = aScriptType;
194 1 : aScriptEvent.ScriptCode = aScriptCode;
195 :
196 : // Iterate over all listeners and pass events.
197 2 : OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
198 4 : while( aIt.hasMoreElements() )
199 3 : static_cast<XScriptListener *>(aIt.next())->firing( aScriptEvent );
200 1 : }
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 = static_cast<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( !(*static_cast<sal_Bool const *>(aRet.getValue())) )
294 0 : return aRet;
295 0 : break;
296 :
297 : case TypeClass_STRING:
298 : // none empty string -> return
299 0 : if( !(static_cast<OUString const *>(aRet.getValue()))->isEmpty() )
300 0 : return aRet;
301 0 : break;
302 :
303 : // none zero number -> return
304 0 : case TypeClass_FLOAT: if( *static_cast<float const *>(aRet.getValue()) ) return aRet; break;
305 0 : case TypeClass_DOUBLE: if( *static_cast<double const *>(aRet.getValue()) ) return aRet; break;
306 0 : case TypeClass_BYTE: if( *static_cast<sal_uInt8 const *>(aRet.getValue()) ) return aRet; break;
307 0 : case TypeClass_SHORT: if( *static_cast<sal_Int16 const *>(aRet.getValue()) ) return aRet; break;
308 0 : case TypeClass_LONG: if( *static_cast<sal_Int32 const *>(aRet.getValue()) ) return aRet; break;
309 0 : case TypeClass_UNSIGNED_SHORT: if( *static_cast<sal_uInt16 const *>(aRet.getValue()) ) return aRet; break;
310 0 : case TypeClass_UNSIGNED_LONG: if( *static_cast<sal_uInt32 const *>(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 609 : Reference< XEventAttacherManager > createEventAttacherManager( const Reference< XComponentContext > & rxContext )
353 : throw( Exception )
354 : {
355 609 : Reference< XIntrospection > xIntrospection = theIntrospection::get( rxContext );
356 609 : return new ImplEventAttacherManager( xIntrospection, rxContext );
357 : }
358 :
359 :
360 609 : ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection,
361 : const Reference< XComponentContext >& rContext )
362 : : aScriptListeners( aLock )
363 : , mxContext( rContext )
364 : , mxIntrospection( rIntrospection )
365 609 : , nVersion(0)
366 : {
367 609 : if ( rContext.is() )
368 : {
369 1218 : Reference< XInterface > xIFace( rContext->getServiceManager()->createInstanceWithContext(
370 609 : OUString( "com.sun.star.script.EventAttacher" ), rContext) );
371 609 : if ( xIFace.is() )
372 : {
373 420 : xAttacher = Reference< XEventAttacher2 >::query( xIFace );
374 : }
375 609 : xConverter = Converter::create(rContext);
376 : }
377 :
378 609 : Reference< XInitialization > xInit( xAttacher, UNO_QUERY );
379 609 : if( xInit.is() )
380 : {
381 420 : Sequence< Any > Arguments( 1 );
382 420 : Arguments[0] <<= rIntrospection;
383 420 : xInit->initialize( Arguments );
384 609 : }
385 609 : }
386 :
387 :
388 1208 : ImplEventAttacherManager::~ImplEventAttacherManager()
389 : {
390 1208 : }
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 904 : ::std::deque<AttacherIndex_Impl>::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex )
406 : {
407 904 : if (_nIndex < 0)
408 0 : throw IllegalArgumentException();
409 :
410 904 : ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
411 904 : for ( sal_Int32 i = 0; (i < _nIndex) && (aIt != aIndex.end()); ++i, ++aIt )
412 : ;
413 :
414 904 : if( aIt == aIndex.end() )
415 0 : throw IllegalArgumentException();
416 :
417 904 : 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 829 : DetachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
428 829 : mrMgr(rMgr), mnIdx(nIdx) {}
429 :
430 282 : void operator() (AttachedObject_Impl& rObj)
431 : {
432 282 : mrMgr.detach(mnIdx, rObj.xTarget);
433 282 : }
434 : };
435 :
436 : class AttachObject : public std::unary_function<AttachedObject_Impl, void>
437 : {
438 : ImplEventAttacherManager& mrMgr;
439 : sal_Int32 mnIdx;
440 : public:
441 273 : AttachObject(ImplEventAttacherManager& rMgr, sal_Int32 nIdx) :
442 273 : mrMgr(rMgr), mnIdx(nIdx) {}
443 :
444 267 : void operator() (AttachedObject_Impl& rObj)
445 : {
446 267 : mrMgr.attach(mnIdx, rObj.xTarget, rObj.aHelper);
447 267 : }
448 : };
449 :
450 : }
451 :
452 :
453 : // Methods of XEventAttacherManager
454 23 : void SAL_CALL ImplEventAttacherManager::registerScriptEvent
455 : (
456 : sal_Int32 nIndex,
457 : const ScriptEventDescriptor& ScriptEvent
458 : )
459 : throw( IllegalArgumentException, RuntimeException, std::exception )
460 : {
461 23 : Guard< Mutex > aGuard( aLock );
462 :
463 : // Examine the index and apply the array
464 23 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
465 :
466 46 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
467 :
468 46 : ScriptEventDescriptor aEvt = ScriptEvent;
469 23 : sal_Int32 nLastDot = aEvt.ListenerType.lastIndexOf('.');
470 23 : if (nLastDot != -1)
471 10 : aEvt.ListenerType = aEvt.ListenerType.copy(nLastDot+1);
472 23 : (*aIt).aEventList.push_back( aEvt );
473 :
474 : // register new new Event
475 23 : ::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.begin();
476 23 : ::std::deque< AttachedObject_Impl >::iterator aObjEnd = (*aIt).aObjList.end();
477 48 : while( aObjIt != aObjEnd )
478 : {
479 : // resize
480 2 : sal_Int32 nPos = (*aObjIt).aAttachedListenerSeq.getLength();
481 2 : (*aObjIt).aAttachedListenerSeq.realloc( nPos + 1 );
482 2 : Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
483 :
484 : Reference< XAllListener > xAll =
485 2 : new AttacherAllListener_Impl( this, ScriptEvent.ScriptType, ScriptEvent.ScriptCode );
486 : try
487 : {
488 8 : pArray[nPos] = xAttacher->attachSingleEventListener( (*aObjIt).xTarget, xAll,
489 2 : (*aObjIt).aHelper, ScriptEvent.ListenerType,
490 4 : ScriptEvent.AddListenerParam, ScriptEvent.EventMethod );
491 : }
492 0 : catch( Exception& )
493 : {
494 : }
495 :
496 2 : ++aObjIt;
497 25 : }
498 23 : }
499 :
500 :
501 269 : void SAL_CALL ImplEventAttacherManager::registerScriptEvents
502 : (
503 : sal_Int32 nIndex,
504 : const Sequence< ScriptEventDescriptor >& ScriptEvents
505 : )
506 : throw( IllegalArgumentException, RuntimeException, std::exception )
507 : {
508 269 : Guard< Mutex > aGuard( aLock );
509 :
510 : // Examine the index and apply the array
511 269 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
512 :
513 538 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
514 269 : ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
515 :
516 269 : const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray();
517 269 : sal_Int32 nLen = ScriptEvents.getLength();
518 289 : for( sal_Int32 i = 0 ; i < nLen ; i++ )
519 20 : registerScriptEvent( nIndex, pArray[ i ] );
520 :
521 538 : ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
522 269 : }
523 :
524 :
525 1 : 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 1 : Guard< Mutex > aGuard( aLock );
535 :
536 1 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
537 :
538 2 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
539 1 : ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
540 :
541 2 : OUString aLstType = ListenerType;
542 1 : sal_Int32 nLastDot = aLstType.lastIndexOf('.');
543 1 : if (nLastDot != -1)
544 0 : aLstType = aLstType.copy(nLastDot+1);
545 :
546 1 : ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
547 1 : ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
548 2 : while( aEvtIt != aEvtEnd )
549 : {
550 2 : if( aLstType == (*aEvtIt).ListenerType
551 1 : && EventMethod == (*aEvtIt).EventMethod
552 2 : && ToRemoveListenerParam == (*aEvtIt).AddListenerParam )
553 : {
554 1 : (*aIt).aEventList.erase( aEvtIt );
555 1 : break;
556 : }
557 :
558 0 : ++aEvtIt;
559 : }
560 2 : ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
561 1 : }
562 :
563 :
564 3 : void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex )
565 : throw( IllegalArgumentException, RuntimeException, std::exception )
566 : {
567 3 : Guard< Mutex > aGuard( aLock );
568 3 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
569 :
570 6 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
571 3 : ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
572 3 : (*aIt).aEventList.clear();
573 6 : ::std::for_each(aList.begin(), aList.end(), AttachObject(*this, nIndex));
574 3 : }
575 :
576 :
577 579 : void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex)
578 : throw( IllegalArgumentException, RuntimeException, std::exception )
579 : {
580 579 : Guard< Mutex > aGuard( aLock );
581 579 : if( nIndex < 0 )
582 0 : throw IllegalArgumentException();
583 :
584 579 : if ( static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() )
585 368 : aIndex.resize(nIndex+1);
586 :
587 1158 : AttacherIndex_Impl aTmp;
588 1158 : aIndex.insert( aIndex.begin() + nIndex, aTmp );
589 579 : }
590 :
591 :
592 556 : void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex)
593 : throw( IllegalArgumentException, RuntimeException, std::exception )
594 : {
595 556 : Guard< Mutex > aGuard( aLock );
596 556 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
597 :
598 1112 : ::std::deque< AttachedObject_Impl > aList = (*aIt).aObjList;
599 556 : ::std::for_each(aList.begin(), aList.end(), DetachObject(*this, nIndex));
600 1112 : aIndex.erase( aIt );
601 556 : }
602 :
603 :
604 52 : Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex)
605 : throw( IllegalArgumentException, RuntimeException, std::exception )
606 : {
607 52 : Guard< Mutex > aGuard( aLock );
608 52 : ::std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex );
609 :
610 52 : Sequence< ScriptEventDescriptor > aSeq( (*aIt).aEventList.size() );
611 52 : ScriptEventDescriptor * pArray = aSeq.getArray();
612 :
613 52 : ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
614 52 : ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
615 52 : sal_Int32 i = 0;
616 110 : while( aEvtIt != aEvtEnd )
617 : {
618 6 : pArray[i++] = *aEvtIt;
619 6 : ++aEvtIt;
620 : }
621 52 : return aSeq;
622 : }
623 :
624 :
625 1027 : void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper)
626 : throw( IllegalArgumentException, ServiceNotRegisteredException, RuntimeException, std::exception )
627 : {
628 1027 : Guard< Mutex > aGuard( aLock );
629 1027 : if( nIndex < 0 || !xObject.is() )
630 0 : throw IllegalArgumentException();
631 :
632 1027 : 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 1027 : ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
646 :
647 1046 : AttachedObject_Impl aTmp;
648 1027 : aTmp.xTarget = xObject;
649 1027 : aTmp.aHelper = Helper;
650 1027 : aCurrentPosition->aObjList.push_back( aTmp );
651 :
652 : //::std::deque< AttachedObject_Impl >::iterator aObjIt = (*aIt).aObjList.back();
653 1027 : AttachedObject_Impl & rCurObj = aCurrentPosition->aObjList.back();
654 1027 : rCurObj.aAttachedListenerSeq = Sequence< Reference< XEventListener > >( aCurrentPosition->aEventList.size() );
655 :
656 1027 : if (aCurrentPosition->aEventList.empty())
657 1008 : return;
658 :
659 38 : Sequence<com::sun::star::script::EventListener> aEvents(aCurrentPosition->aEventList.size());
660 19 : std::deque<ScriptEventDescriptor>::iterator itr = aCurrentPosition->aEventList.begin();
661 19 : std::deque<ScriptEventDescriptor>::iterator itrEnd = aCurrentPosition->aEventList.end();
662 19 : ::com::sun::star::script::EventListener* p = aEvents.getArray();
663 19 : size_t i = 0;
664 58 : for (; itr != itrEnd; ++itr)
665 : {
666 39 : com::sun::star::script::EventListener aListener;
667 117 : aListener.AllListener =
668 156 : new AttacherAllListener_Impl(this, itr->ScriptType, itr->ScriptCode);
669 39 : aListener.Helper = rCurObj.aHelper;
670 39 : aListener.ListenerType = itr->ListenerType;
671 39 : aListener.EventMethod = itr->EventMethod;
672 39 : aListener.AddListenerParam = itr->AddListenerParam;
673 39 : p[i++] = aListener;
674 39 : }
675 :
676 : try
677 : {
678 38 : rCurObj.aAttachedListenerSeq =
679 38 : xAttacher->attachMultipleEventListeners(rCurObj.xTarget, aEvents);
680 : }
681 0 : catch (const Exception&)
682 : {
683 : // Fail gracefully.
684 19 : }
685 : }
686 :
687 :
688 1020 : void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject)
689 : throw( IllegalArgumentException, RuntimeException, std::exception )
690 : {
691 1020 : Guard< Mutex > aGuard( aLock );
692 : //return;
693 1020 : if( nIndex < 0 || static_cast< ::std::deque< AttacherIndex_Impl >::size_type>(nIndex) >= aIndex.size() || !xObject.is() )
694 0 : throw IllegalArgumentException();
695 :
696 1020 : ::std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex;
697 1020 : ::std::deque< AttachedObject_Impl >::iterator aObjIt = aCurrentPosition->aObjList.begin();
698 1020 : ::std::deque< AttachedObject_Impl >::iterator aObjEnd = aCurrentPosition->aObjList.end();
699 2242 : while( aObjIt != aObjEnd )
700 : {
701 1207 : if( (*aObjIt).xTarget == xObject )
702 : {
703 1005 : Reference< XEventListener > * pArray = (*aObjIt).aAttachedListenerSeq.getArray();
704 :
705 1005 : ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = aCurrentPosition->aEventList.begin();
706 1005 : ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = aCurrentPosition->aEventList.end();
707 1005 : sal_Int32 i = 0;
708 2051 : while( aEvtIt != aEvtEnd )
709 : {
710 41 : if( pArray[i].is() )
711 : {
712 : try
713 : {
714 60 : xAttacher->removeListener( (*aObjIt).xTarget, (*aEvtIt).ListenerType,
715 60 : (*aEvtIt).AddListenerParam, pArray[i] );
716 : }
717 0 : catch( Exception& )
718 : {
719 : }
720 : }
721 41 : i++;
722 41 : ++aEvtIt;
723 : }
724 1005 : aCurrentPosition->aObjList.erase( aObjIt );
725 1005 : break;
726 : }
727 202 : ++aObjIt;
728 1020 : }
729 1020 : }
730 :
731 1185 : void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener)
732 : throw( IllegalArgumentException, RuntimeException, std::exception )
733 : {
734 1185 : Guard< Mutex > aGuard( aLock );
735 1185 : aScriptListeners.addInterface( aListener );
736 1185 : }
737 :
738 1181 : void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener)
739 : throw( IllegalArgumentException, RuntimeException, std::exception )
740 : {
741 1181 : Guard< Mutex > aGuard( aLock );
742 1181 : aScriptListeners.removeInterface( aListener );
743 1181 : }
744 :
745 :
746 : // Methods of XPersistObject
747 0 : OUString SAL_CALL ImplEventAttacherManager::getServiceName()
748 : throw( RuntimeException, std::exception )
749 : {
750 0 : return OUString( "com.sun.star.uno.script.EventAttacherManager" );
751 : }
752 :
753 1 : void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream)
754 : throw( IOException, RuntimeException, std::exception )
755 : {
756 1 : Guard< Mutex > aGuard( aLock );
757 : // Don't run without XMarkableStream
758 2 : Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY );
759 1 : if( !xMarkStream.is() )
760 1 : return;
761 :
762 : // Write out the version
763 1 : OutStream->writeShort( 2 );
764 :
765 : // Remember position for length
766 1 : sal_Int32 nObjLenMark = xMarkStream->createMark();
767 1 : OutStream->writeLong( 0L );
768 :
769 1 : OutStream->writeLong( aIndex.size() );
770 :
771 : // Write out sequences
772 1 : ::std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin();
773 1 : ::std::deque<AttacherIndex_Impl>::iterator aEnd = aIndex.end();
774 5 : while( aIt != aEnd )
775 : {
776 : // Write out the length of the sequence and all descriptions
777 3 : OutStream->writeLong( (*aIt).aEventList.size() );
778 3 : ::std::deque< ScriptEventDescriptor >::iterator aEvtIt = (*aIt).aEventList.begin();
779 3 : ::std::deque< ScriptEventDescriptor >::iterator aEvtEnd = (*aIt).aEventList.end();
780 6 : 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 3 : ++aIt;
792 : }
793 :
794 : // The length is now known
795 1 : sal_Int32 nObjLen = xMarkStream->offsetToMark( nObjLenMark ) -4;
796 1 : xMarkStream->jumpToMark( nObjLenMark );
797 1 : OutStream->writeLong( nObjLen );
798 1 : xMarkStream->jumpToFurthest();
799 2 : xMarkStream->deleteMark( nObjLenMark );
800 : }
801 :
802 1 : void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream)
803 : throw( IOException, RuntimeException, std::exception )
804 : {
805 1 : Guard< Mutex > aGuard( aLock );
806 : // Don't run without XMarkableStream
807 2 : Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY );
808 1 : if( !xMarkStream.is() )
809 1 : return;
810 :
811 : // Read in the version
812 1 : 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 1 : sal_Int32 nLen = InStream->readLong();
817 :
818 : // Position for comparative purposes
819 1 : sal_Int32 nObjLenMark = xMarkStream->createMark();
820 :
821 : // Number of read sequences
822 1 : sal_Int32 nItemCount = InStream->readLong();
823 :
824 4 : for( sal_Int32 i = 0 ; i < nItemCount ; i++ )
825 : {
826 3 : insertEntry( i );
827 : // Read the length of the sequence
828 3 : sal_Int32 nSeqLen = InStream->readLong();
829 :
830 : // Display the sequences and read the descriptions
831 3 : Sequence< ScriptEventDescriptor > aSEDSeq( nSeqLen );
832 3 : ScriptEventDescriptor* pArray = aSEDSeq.getArray();
833 3 : 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 3 : registerScriptEvents( i, aSEDSeq );
843 3 : }
844 :
845 : // Have we read the specified length?
846 1 : sal_Int32 nRealLen = xMarkStream->offsetToMark( nObjLenMark );
847 1 : 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 1 : xMarkStream->jumpToFurthest();
863 2 : xMarkStream->deleteMark( nObjLenMark );
864 : }
865 :
866 : } // namesapce comphelper
867 :
868 :
869 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|