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