1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
20 #include <com/sun/star/lang/XServiceInfo.hpp>
21 #include <com/sun/star/lang/XInitialization.hpp>
22 #include <com/sun/star/beans/IntrospectionException.hpp>
23 #include <com/sun/star/beans/theIntrospection.hpp>
24 #include <com/sun/star/beans/MethodConcept.hpp>
25 #include <com/sun/star/script/CannotConvertException.hpp>
26 #include <com/sun/star/script/CannotCreateAdapterException.hpp>
27 #include <com/sun/star/script/XEventAttacher2.hpp>
28 #include <com/sun/star/script/Converter.hpp>
29 #include <com/sun/star/script/XAllListener.hpp>
30 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
31 #include <com/sun/star/reflection/theCoreReflection.hpp>
32 #include <com/sun/star/reflection/XIdlReflection.hpp>
34 // InvocationToAllListenerMapper
35 #include <com/sun/star/script/XInvocation.hpp>
36 #include <cppuhelper/exc_hlp.hxx>
37 #include <cppuhelper/weak.hxx>
38 #include <cppuhelper/factory.hxx>
39 #include <cppuhelper/implbase.hxx>
40 #include <cppuhelper/supportsservice.hxx>
45 namespace com::sun::star::lang
{ class XMultiServiceFactory
; }
47 using namespace com::sun::star::uno
;
48 using namespace com::sun::star::registry
;
49 using namespace com::sun::star::lang
;
50 using namespace com::sun::star::beans
;
51 using namespace com::sun::star::script
;
52 using namespace com::sun::star::reflection
;
57 namespace comp_EventAttacher
{
60 // class InvocationToAllListenerMapper
61 // helper class to map XInvocation to XAllListener
65 class InvocationToAllListenerMapper
: public WeakImplHelper
< XInvocation
>
68 InvocationToAllListenerMapper( const Reference
< XIdlClass
>& ListenerType
,
69 const Reference
< XAllListener
>& AllListener
, Any Helper
);
72 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection() override
;
73 virtual Any SAL_CALL
invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
, Sequence
< sal_Int16
>& OutParamIndex
, Sequence
< Any
>& OutParam
) override
;
74 virtual void SAL_CALL
setValue(const OUString
& PropertyName
, const Any
& Value
) override
;
75 virtual Any SAL_CALL
getValue(const OUString
& PropertyName
) override
;
76 virtual sal_Bool SAL_CALL
hasMethod(const OUString
& Name
) override
;
77 virtual sal_Bool SAL_CALL
hasProperty(const OUString
& Name
) override
;
80 Reference
< XAllListener
> m_xAllListener
;
81 Reference
< XIdlClass
> m_xListenerType
;
87 // Function to replace AllListenerAdapterService::createAllListerAdapter
88 static Reference
< XInterface
> createAllListenerAdapter
90 const Reference
< XInvocationAdapterFactory2
>& xInvocationAdapterFactory
,
91 const Reference
< XIdlClass
>& xListenerType
,
92 const Reference
< XAllListener
>& xListener
,
96 Reference
< XInterface
> xAdapter
;
97 if( xInvocationAdapterFactory
.is() && xListenerType
.is() && xListener
.is() )
99 Reference
< XInvocation
> xInvocationToAllListenerMapper
=
100 new InvocationToAllListenerMapper(xListenerType
, xListener
, Helper
);
101 Type
aListenerType( xListenerType
->getTypeClass(), xListenerType
->getName());
102 Sequence
<Type
> arg2
{ aListenerType
};
103 xAdapter
= xInvocationAdapterFactory
->createAdapter( xInvocationToAllListenerMapper
, arg2
);
109 // InvocationToAllListenerMapper
110 InvocationToAllListenerMapper::InvocationToAllListenerMapper
111 ( const Reference
< XIdlClass
>& ListenerType
, const Reference
< XAllListener
>& AllListener
, Any Helper
)
112 : m_xAllListener( AllListener
)
113 , m_xListenerType( ListenerType
)
114 , m_Helper(std::move( Helper
))
119 Reference
< XIntrospectionAccess
> SAL_CALL
InvocationToAllListenerMapper::getIntrospection()
121 return Reference
< XIntrospectionAccess
>();
125 Any SAL_CALL
InvocationToAllListenerMapper::invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
,
126 Sequence
< sal_Int16
>& , Sequence
< Any
>& )
130 // Check if to firing or approveFiring has to be called
131 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( FunctionName
);
132 bool bApproveFiring
= false;
135 Reference
< XIdlClass
> xReturnType
= xMethod
->getReturnType();
136 Sequence
< Reference
< XIdlClass
> > aExceptionSeq
= xMethod
->getExceptionTypes();
137 if( ( xReturnType
.is() && xReturnType
->getTypeClass() != TypeClass_VOID
) ||
138 aExceptionSeq
.hasElements() )
140 bApproveFiring
= true;
144 Sequence
< ParamInfo
> aParamSeq
= xMethod
->getParameterInfos();
145 sal_uInt32 nParamCount
= aParamSeq
.getLength();
146 if( nParamCount
> 1 )
148 const ParamInfo
* pInfo
= aParamSeq
.getConstArray();
149 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
151 if( pInfo
[ i
].aMode
!= ParamMode_IN
)
153 bApproveFiring
= true;
160 AllEventObject aAllEvent
;
161 aAllEvent
.Source
= static_cast<OWeakObject
*>(this);
162 aAllEvent
.Helper
= m_Helper
;
163 aAllEvent
.ListenerType
= Type(m_xListenerType
->getTypeClass(), m_xListenerType
->getName());
164 aAllEvent
.MethodName
= FunctionName
;
165 aAllEvent
.Arguments
= Params
;
167 aRet
= m_xAllListener
->approveFiring( aAllEvent
);
169 m_xAllListener
->firing( aAllEvent
);
174 void SAL_CALL
InvocationToAllListenerMapper::setValue(const OUString
& , const Any
& )
179 Any SAL_CALL
InvocationToAllListenerMapper::getValue(const OUString
& )
185 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasMethod(const OUString
& Name
)
187 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( Name
);
192 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasProperty(const OUString
& Name
)
194 Reference
< XIdlField
> xField
= m_xListenerType
->getField( Name
);
199 // class EventAttacherImpl
200 // represents an implementation of the EventAttacher service
204 class EventAttacherImpl
: public WeakImplHelper
< XEventAttacher2
, XInitialization
, XServiceInfo
>
207 explicit EventAttacherImpl( const Reference
< XComponentContext
>& );
210 virtual OUString SAL_CALL
getImplementationName( ) override
;
211 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
212 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) override
;
215 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
217 // methods of XEventAttacher
218 virtual Reference
< XEventListener
> SAL_CALL
attachListener(const Reference
< XInterface
>& xObject
,
219 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
,
220 const OUString
& ListenerType
, const OUString
& AddListenerParam
) override
;
221 virtual Reference
< XEventListener
> SAL_CALL
attachSingleEventListener(const Reference
< XInterface
>& xObject
,
222 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
,
223 const OUString
& ListenerType
, const OUString
& AddListenerParam
,
224 const OUString
& EventMethod
) override
;
225 virtual void SAL_CALL
removeListener(const Reference
< XInterface
>& xObject
,
226 const OUString
& ListenerType
, const OUString
& AddListenerParam
,
227 const Reference
< XEventListener
>& aToRemoveListener
) override
;
230 virtual Sequence
< Reference
<XEventListener
> > SAL_CALL
attachMultipleEventListeners(
231 const Reference
<XInterface
>& xObject
, const Sequence
<css::script::EventListener
>& aListeners
) override
;
233 // used by FilterAllListener_Impl
234 /// @throws Exception
235 Reference
< XTypeConverter
> getConverter();
237 friend class FilterAllListenerImpl
;
240 static Reference
<XEventListener
> attachListenerForTarget(
241 const Reference
<XIntrospectionAccess
>& xAccess
,
242 const Reference
<XInvocationAdapterFactory2
>& xInvocationAdapterFactory
,
243 const Reference
<XAllListener
>& xAllListener
,
246 const OUString
& aListenerType
,
247 const OUString
& aAddListenerParam
);
249 Sequence
< Reference
<XEventListener
> > attachListeners(
250 const Reference
<XInterface
>& xObject
,
251 const Sequence
< Reference
<XAllListener
> >& AllListeners
,
252 const Sequence
<css::script::EventListener
>& aListeners
);
256 Reference
< XComponentContext
> m_xContext
;
259 Reference
< XIntrospection
> m_xIntrospection
;
260 Reference
< XIdlReflection
> m_xReflection
;
261 Reference
< XTypeConverter
> m_xConverter
;
262 Reference
< XInvocationAdapterFactory2
> m_xInvocationAdapterFactory
;
265 /// @throws Exception
266 Reference
< XIntrospection
> getIntrospection();
267 /// @throws Exception
268 Reference
< XIdlReflection
> getReflection();
269 /// @throws Exception
270 Reference
< XInvocationAdapterFactory2
> getInvocationAdapterService();
275 EventAttacherImpl::EventAttacherImpl( const Reference
< XComponentContext
>& rxContext
)
276 : m_xContext( rxContext
)
280 /// @throws Exception
281 OUString SAL_CALL
EventAttacherImpl::getImplementationName( )
283 return "com.sun.star.comp.EventAttacher";
286 sal_Bool SAL_CALL
EventAttacherImpl::supportsService( const OUString
& ServiceName
)
288 return cppu::supportsService(this, ServiceName
);
291 Sequence
<OUString
> SAL_CALL
EventAttacherImpl::getSupportedServiceNames( )
293 return { "com.sun.star.script.EventAttacher" };
296 void SAL_CALL
EventAttacherImpl::initialize(const Sequence
< Any
>& Arguments
)
298 // get services from the argument list
299 for( const Any
& arg
: Arguments
)
301 if( arg
.getValueType().getTypeClass() != TypeClass_INTERFACE
)
302 throw IllegalArgumentException();
304 // InvocationAdapter service ?
305 Reference
< XInvocationAdapterFactory2
> xALAS
;
309 std::scoped_lock
aGuard( m_aMutex
);
310 m_xInvocationAdapterFactory
= xALAS
;
312 // Introspection service ?
313 Reference
< XIntrospection
> xI
;
317 std::scoped_lock
aGuard( m_aMutex
);
318 m_xIntrospection
= xI
;
320 // Reflection service ?
321 Reference
< XIdlReflection
> xIdlR
;
325 std::scoped_lock
aGuard( m_aMutex
);
326 m_xReflection
= xIdlR
;
328 // Converter Service ?
329 Reference
< XTypeConverter
> xC
;
333 std::scoped_lock
aGuard( m_aMutex
);
337 // no right interface
338 if( !xALAS
.is() && !xI
.is() && !xIdlR
.is() && !xC
.is() )
339 throw IllegalArgumentException();
344 //*** Private helper methods ***
345 Reference
< XIntrospection
> EventAttacherImpl::getIntrospection()
347 std::scoped_lock
aGuard( m_aMutex
);
348 if( !m_xIntrospection
.is() )
350 m_xIntrospection
= theIntrospection::get( m_xContext
);
352 return m_xIntrospection
;
356 //*** Private helper methods ***
357 Reference
< XIdlReflection
> EventAttacherImpl::getReflection()
359 std::scoped_lock
aGuard( m_aMutex
);
360 if( !m_xReflection
.is() )
362 m_xReflection
= theCoreReflection::get(m_xContext
);
364 return m_xReflection
;
368 //*** Private helper methods ***
369 Reference
< XInvocationAdapterFactory2
> EventAttacherImpl::getInvocationAdapterService()
371 std::scoped_lock
aGuard( m_aMutex
);
372 if( !m_xInvocationAdapterFactory
.is() )
374 m_xInvocationAdapterFactory
= InvocationAdapterFactory::create(m_xContext
);
376 return m_xInvocationAdapterFactory
;
380 //*** Private helper methods ***
381 Reference
< XTypeConverter
> EventAttacherImpl::getConverter()
383 std::scoped_lock
aGuard( m_aMutex
);
384 if( !m_xConverter
.is() )
386 m_xConverter
= Converter::create(m_xContext
);
393 // Implementation of an EventAttacher-related AllListeners, which brings
394 // a few Events to a general AllListener
395 class FilterAllListenerImpl
: public WeakImplHelper
< XAllListener
>
398 FilterAllListenerImpl( EventAttacherImpl
* pEA_
, OUString EventMethod_
,
399 const Reference
< XAllListener
>& AllListener_
);
402 virtual void SAL_CALL
firing(const AllEventObject
& Event
) override
;
403 virtual Any SAL_CALL
approveFiring(const AllEventObject
& Event
) override
;
406 virtual void SAL_CALL
disposing(const EventObject
& Source
) override
;
410 /// @throws CannotConvertException
411 /// @throws RuntimeException
412 void convertToEventReturn( Any
& rRet
, const Type
& rRetType
);
414 EventAttacherImpl
* m_pEA
;
415 OUString m_EventMethod
;
416 Reference
< XAllListener
> m_AllListener
;
421 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl
* pEA_
, OUString EventMethod_
,
422 const Reference
< XAllListener
>& AllListener_
)
424 , m_EventMethod(std::move( EventMethod_
))
425 , m_AllListener( AllListener_
)
430 void SAL_CALL
FilterAllListenerImpl::firing(const AllEventObject
& Event
)
432 if( Event
.MethodName
== m_EventMethod
&& m_AllListener
.is() )
433 m_AllListener
->firing( Event
);
436 // Convert to the standard event return
437 void FilterAllListenerImpl::convertToEventReturn( Any
& rRet
, const Type
& rRetType
)
439 // no return value? Set to the specified values
440 if( rRet
.getValueType().getTypeClass() == TypeClass_VOID
)
442 switch( rRetType
.getTypeClass() )
444 case TypeClass_INTERFACE
:
446 rRet
<<= Reference
< XInterface
>();
450 case TypeClass_BOOLEAN
:
454 case TypeClass_STRING
:
458 case TypeClass_FLOAT
: rRet
<<= float(0); break;
459 case TypeClass_DOUBLE
: rRet
<<= 0.0; break;
460 case TypeClass_BYTE
: rRet
<<= sal_uInt8( 0 ); break;
461 case TypeClass_SHORT
: rRet
<<= sal_Int16( 0 ); break;
462 case TypeClass_LONG
: rRet
<<= sal_Int32( 0 ); break;
463 case TypeClass_UNSIGNED_SHORT
: rRet
<<= sal_uInt16( 0 ); break;
464 case TypeClass_UNSIGNED_LONG
: rRet
<<= sal_uInt32( 0 ); break;
469 else if( !rRet
.getValueType().equals( rRetType
) )
471 Reference
< XTypeConverter
> xConverter
= m_pEA
->getConverter();
472 if( !xConverter
.is() )
473 throw CannotConvertException(); // TODO TypeConversionException
474 rRet
= xConverter
->convertTo( rRet
, rRetType
);
479 Any SAL_CALL
FilterAllListenerImpl::approveFiring( const AllEventObject
& Event
)
483 if( Event
.MethodName
== m_EventMethod
&& m_AllListener
.is() )
484 aRet
= m_AllListener
->approveFiring( Event
);
487 // Convert to the standard event return
490 Reference
< XIdlClass
> xListenerType
= m_pEA
->getReflection()->
491 forName( Event
.ListenerType
.getTypeName() );
492 Reference
< XIdlMethod
> xMeth
= xListenerType
->getMethod( Event
.MethodName
);
495 Reference
< XIdlClass
> xRetType
= xMeth
->getReturnType();
496 Type
aRetType( xRetType
->getTypeClass(), xRetType
->getName() );
497 convertToEventReturn( aRet
, aRetType
);
500 catch( const CannotConvertException
& )
502 css::uno::Any anyEx
= cppu::getCaughtException();
503 throw InvocationTargetException( OUString(), Reference
< XInterface
>(), anyEx
);
510 void FilterAllListenerImpl::disposing(const EventObject
& )
516 Reference
< XEventListener
> EventAttacherImpl::attachListener
518 const Reference
< XInterface
>& xObject
,
519 const Reference
< XAllListener
>& AllListener
,
521 const OUString
& ListenerType
,
522 const OUString
& AddListenerParam
525 if( !xObject
.is() || !AllListener
.is() )
526 throw IllegalArgumentException();
528 Reference
< XInvocationAdapterFactory2
> xInvocationAdapterFactory
= getInvocationAdapterService();
529 if( !xInvocationAdapterFactory
.is() )
530 throw ServiceNotRegisteredException();
532 Reference
< XIdlReflection
> xReflection
= getReflection();
533 if( !xReflection
.is() )
534 throw ServiceNotRegisteredException();
536 // Sign in, Call the fitting addListener method
537 // First Introspection, as the Methods can be analyzed in the same way
538 // For better performance it is implemented here again or make the Impl-Method
539 // of the Introspection configurable for this purpose.
540 Reference
< XIntrospection
> xIntrospection
= getIntrospection();
541 if( !xIntrospection
.is() )
542 return Reference
<XEventListener
>();
544 // Inspect Introspection
545 Any
aObjAny( &xObject
, cppu::UnoType
<XInterface
>::get());
547 Reference
< XIntrospectionAccess
> xAccess
= xIntrospection
->inspect( aObjAny
);
549 return Reference
<XEventListener
>();
551 return attachListenerForTarget(
552 xAccess
, xInvocationAdapterFactory
, AllListener
, aObjAny
, Helper
,
553 ListenerType
, AddListenerParam
);
556 Reference
<XEventListener
> EventAttacherImpl::attachListenerForTarget(
557 const Reference
<XIntrospectionAccess
>& xAccess
,
558 const Reference
<XInvocationAdapterFactory2
>& xInvocationAdapterFactory
,
559 const Reference
<XAllListener
>& xAllListener
,
562 const OUString
& aListenerType
,
563 const OUString
& aAddListenerParam
)
565 Reference
< XEventListener
> xRet
;
567 // Construct the name of the addListener-Method.
568 sal_Int32 nIndex
= aListenerType
.lastIndexOf('.');
569 // set index to the interface name without package name
576 OUString aListenerName
= (!aListenerType
.isEmpty() && aListenerType
[nIndex
] == 'X') ? aListenerType
.copy(nIndex
+1) : aListenerType
;
577 OUString aAddListenerName
= "add" + aListenerName
;
579 // Send Methods to the correct addListener-Method
580 const Sequence
< Reference
< XIdlMethod
> > aMethodSeq
= xAccess
->getMethods( MethodConcept::LISTENER
);
581 for (const Reference
< XIdlMethod
>& rxMethod
: aMethodSeq
)
583 // Is it the correct method?
584 OUString aMethName
= rxMethod
->getName();
586 if (aAddListenerName
!= aMethName
)
589 Sequence
< Reference
< XIdlClass
> > params
= rxMethod
->getParameterTypes();
590 sal_uInt32 nParamCount
= params
.getLength();
592 Reference
< XIdlClass
> xListenerType
;
593 if( nParamCount
== 1 )
594 xListenerType
= params
.getConstArray()[0];
595 else if( nParamCount
== 2 )
596 xListenerType
= params
.getConstArray()[1];
598 // Request Adapter for the actual Listener type
599 Reference
< XInterface
> xAdapter
= createAllListenerAdapter(
600 xInvocationAdapterFactory
, xListenerType
, xAllListener
, aHelper
);
603 throw CannotCreateAdapterException();
604 xRet
.set( xAdapter
, UNO_QUERY
);
606 // Just the Listener as parameter?
607 if( nParamCount
== 1 )
609 Sequence
< Any
> args( 1 );
610 args
.getArray()[0] <<= xAdapter
;
613 rxMethod
->invoke( aObject
, args
);
615 catch( const InvocationTargetException
& )
617 throw IntrospectionException();
620 // Else, pass the other parameter now
621 else if( nParamCount
== 2 )
623 Sequence
< Any
> args( 2 );
624 Any
* pAnys
= args
.getArray();
626 // Check the type of the 1st parameter
627 Reference
< XIdlClass
> xParamClass
= params
.getConstArray()[0];
628 if( xParamClass
->getTypeClass() == TypeClass_STRING
)
630 pAnys
[0] <<= aAddListenerParam
;
633 // 2nd Parameter == Listener? TODO: Test!
634 pAnys
[1] <<= xAdapter
;
636 // TODO: Convert String -> ?
640 rxMethod
->invoke( aObject
, args
);
642 catch( const InvocationTargetException
& )
644 throw IntrospectionException();
649 // Anything else is not supported
655 Sequence
< Reference
<XEventListener
> > EventAttacherImpl::attachListeners(
656 const Reference
<XInterface
>& xObject
,
657 const Sequence
< Reference
<XAllListener
> >& AllListeners
,
658 const Sequence
<css::script::EventListener
>& aListeners
)
660 sal_Int32 nCount
= aListeners
.getLength();
661 if (nCount
!= AllListeners
.getLength())
662 // This is a prerequisite!
663 throw RuntimeException();
666 throw IllegalArgumentException();
668 Reference
< XInvocationAdapterFactory2
> xInvocationAdapterFactory
= getInvocationAdapterService();
669 if( !xInvocationAdapterFactory
.is() )
670 throw ServiceNotRegisteredException();
672 Reference
< XIdlReflection
> xReflection
= getReflection();
673 if( !xReflection
.is() )
674 throw ServiceNotRegisteredException();
676 // Sign in, Call the fitting addListener method
677 // First Introspection, as the Methods can be analyzed in the same way
678 // For better performance it is implemented here again or make the Impl-Method
679 // of the Introspection configurable for this purpose.
680 Reference
< XIntrospection
> xIntrospection
= getIntrospection();
681 if( !xIntrospection
.is() )
682 return Sequence
< Reference
<XEventListener
> >();
684 // Inspect Introspection
685 Any
aObjAny( &xObject
, cppu::UnoType
<XInterface
>::get() );
687 Reference
<XIntrospectionAccess
> xAccess
= xIntrospection
->inspect(aObjAny
);
689 return Sequence
< Reference
<XEventListener
> >();
691 Sequence
< Reference
<XEventListener
> > aRet(nCount
);
692 Reference
<XEventListener
>* pArray
= aRet
.getArray();
694 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
696 pArray
[i
] = attachListenerForTarget(
697 xAccess
, xInvocationAdapterFactory
, AllListeners
[ i
],
698 aObjAny
, aListeners
[i
].Helper
, aListeners
[i
].ListenerType
, aListeners
[i
].AddListenerParam
);
705 Reference
< XEventListener
> EventAttacherImpl::attachSingleEventListener
707 const Reference
< XInterface
>& xObject
,
708 const Reference
< XAllListener
>& AllListener
,
710 const OUString
& ListenerType
,
711 const OUString
& AddListenerParam
,
712 const OUString
& EventMethod
715 // Subscribe FilterListener
716 Reference
<XAllListener
> aFilterListener
717 = new FilterAllListenerImpl(this, EventMethod
, AllListener
);
718 return attachListener( xObject
, aFilterListener
, Helper
, ListenerType
, AddListenerParam
);
722 void EventAttacherImpl::removeListener
724 const Reference
< XInterface
>& xObject
,
725 const OUString
& ListenerType
,
726 const OUString
& AddListenerParam
,
727 const Reference
< XEventListener
>& aToRemoveListener
730 if( !xObject
.is() || !aToRemoveListener
.is() )
731 throw IllegalArgumentException();
733 Reference
< XIdlReflection
> xReflection
= getReflection();
734 if( !xReflection
.is() )
735 throw IntrospectionException();
737 // Sign off, Call the fitting removeListener method
738 // First Introspection, as the Methods can be analyzed in the same way
739 // For better performance it is implemented here again or make the Impl-Method
740 // of the Introspection configurable for this purpose.
741 Reference
< XIntrospection
> xIntrospection
= getIntrospection();
742 if( !xIntrospection
.is() )
743 throw IntrospectionException();
745 //Inspect Introspection
746 Any
aObjAny( &xObject
, cppu::UnoType
<XInterface
>::get());
747 Reference
< XIntrospectionAccess
> xAccess
= xIntrospection
->inspect( aObjAny
);
749 throw IntrospectionException();
751 // Create name of the removeListener-Method
752 OUString aRemoveListenerName
;
753 OUString
aListenerName( ListenerType
);
754 sal_Int32 nIndex
= aListenerName
.lastIndexOf( '.' );
755 // set index to the interface name without package name
761 if( aListenerName
[nIndex
] == 'X' )
762 // erase X from the interface name
763 aListenerName
= aListenerName
.copy( nIndex
+1 );
764 aRemoveListenerName
= "remove" + aListenerName
;
766 // Search methods for the correct removeListener method
767 Sequence
< Reference
< XIdlMethod
> > aMethodSeq
= xAccess
->getMethods( MethodConcept::LISTENER
);
768 sal_uInt32 i
, nLen
= aMethodSeq
.getLength();
769 const Reference
< XIdlMethod
>* pMethods
= aMethodSeq
.getConstArray();
770 for( i
= 0 ; i
< nLen
; i
++ )
773 const Reference
< XIdlMethod
>& rxMethod
= pMethods
[i
];
775 // Is it the right method?
776 if( aRemoveListenerName
== rxMethod
->getName() )
778 Sequence
< Reference
< XIdlClass
> > params
= rxMethod
->getParameterTypes();
779 sal_uInt32 nParamCount
= params
.getLength();
781 // Just the Listener as parameter?
782 if( nParamCount
== 1 )
784 Sequence
< Any
> args( 1 );
785 args
.getArray()[0] <<= aToRemoveListener
;
788 rxMethod
->invoke( aObjAny
, args
);
790 catch( const InvocationTargetException
& )
792 throw IntrospectionException();
795 // Else pass the other parameter
796 else if( nParamCount
== 2 )
798 Sequence
< Any
> args( 2 );
799 Any
* pAnys
= args
.getArray();
801 // Check the type of the 1st parameter
802 Reference
< XIdlClass
> xParamClass
= params
.getConstArray()[0];
803 if( xParamClass
->getTypeClass() == TypeClass_STRING
)
804 pAnys
[0] <<= AddListenerParam
;
806 // 2nd parameter == Listener? TODO: Test!
807 pAnys
[1] <<= aToRemoveListener
;
809 // TODO: Convert String -> ?
813 rxMethod
->invoke( aObjAny
, args
);
815 catch( const InvocationTargetException
& )
817 throw IntrospectionException();
825 Sequence
< Reference
<XEventListener
> > EventAttacherImpl::attachMultipleEventListeners(
826 const Reference
<XInterface
>& xObject
, const Sequence
<css::script::EventListener
>& aListeners
)
828 sal_Int32 nCount
= aListeners
.getLength();
829 Sequence
< Reference
<XAllListener
> > aFilterListeners(nCount
);
830 auto aFilterListenersRange
= asNonConstRange(aFilterListeners
);
831 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
833 aFilterListenersRange
[i
]
834 = new FilterAllListenerImpl(this, aListeners
[i
].EventMethod
, aListeners
[i
].AllListener
);
837 return attachListeners(xObject
, aFilterListeners
, aListeners
);
842 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
843 eventattacher_EventAttacher(
844 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& )
846 return cppu::acquire(new comp_EventAttacher::EventAttacherImpl(context
));
850 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */