Bug Summary

File:comphelper/source/eventattachermgr/eventattachermgr.cxx
Location:line 278, column 52
Description:Called C++ object pointer is null

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