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/lang/XMultiServiceFactory.hpp>
23 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
24 #include <com/sun/star/registry/XRegistryKey.hpp>
25 #include <com/sun/star/beans/IntrospectionException.hpp>
26 #include <com/sun/star/beans/theIntrospection.hpp>
27 #include <com/sun/star/beans/MethodConcept.hpp>
28 #include <com/sun/star/script/CannotConvertException.hpp>
29 #include <com/sun/star/script/CannotCreateAdapterException.hpp>
30 #include <com/sun/star/script/XEventAttacher2.hpp>
31 #include <com/sun/star/script/Converter.hpp>
32 #include <com/sun/star/script/XAllListener.hpp>
33 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
34 #include <com/sun/star/reflection/theCoreReflection.hpp>
35 #include <com/sun/star/reflection/XIdlReflection.hpp>
37 // InvocationToAllListenerMapper
38 #include <com/sun/star/script/XInvocation.hpp>
39 #include <comphelper/processfactory.hxx>
40 #include <cppuhelper/weak.hxx>
41 #include <cppuhelper/factory.hxx>
42 #include <cppuhelper/implbase.hxx>
43 #include <cppuhelper/supportsservice.hxx>
45 using namespace com::sun::star::uno
;
46 using namespace com::sun::star::registry
;
47 using namespace com::sun::star::lang
;
48 using namespace com::sun::star::beans
;
49 using namespace com::sun::star::script
;
50 using namespace com::sun::star::reflection
;
55 #define SERVICENAME "com.sun.star.script.EventAttacher"
56 #define IMPLNAME "com.sun.star.comp.EventAttacher"
58 namespace comp_EventAttacher
{
61 // class InvocationToAllListenerMapper
62 // helper class to map XInvocation to XAllListener
64 class InvocationToAllListenerMapper
: public WeakImplHelper
< XInvocation
>
67 InvocationToAllListenerMapper( const Reference
< XIdlClass
>& ListenerType
,
68 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
);
71 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection() override
;
72 virtual Any SAL_CALL
invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
, Sequence
< sal_Int16
>& OutParamIndex
, Sequence
< Any
>& OutParam
) override
;
73 virtual void SAL_CALL
setValue(const OUString
& PropertyName
, const Any
& Value
) override
;
74 virtual Any SAL_CALL
getValue(const OUString
& PropertyName
) override
;
75 virtual sal_Bool SAL_CALL
hasMethod(const OUString
& Name
) override
;
76 virtual sal_Bool SAL_CALL
hasProperty(const OUString
& Name
) override
;
79 Reference
< XAllListener
> m_xAllListener
;
80 Reference
< XIdlClass
> m_xListenerType
;
85 // Function to replace AllListenerAdapterService::createAllListerAdapter
86 Reference
< XInterface
> createAllListenerAdapter
88 const Reference
< XInvocationAdapterFactory2
>& xInvocationAdapterFactory
,
89 const Reference
< XIdlClass
>& xListenerType
,
90 const Reference
< XAllListener
>& xListener
,
94 Reference
< XInterface
> xAdapter
;
95 if( xInvocationAdapterFactory
.is() && xListenerType
.is() && xListener
.is() )
97 Reference
< XInvocation
> xInvocationToAllListenerMapper
=
98 static_cast<XInvocation
*>(new InvocationToAllListenerMapper( xListenerType
, xListener
, Helper
));
99 Type
aListenerType( xListenerType
->getTypeClass(), xListenerType
->getName());
100 Sequence
<Type
> arg2(1);
101 arg2
[0] = aListenerType
;
102 xAdapter
= xInvocationAdapterFactory
->createAdapter( xInvocationToAllListenerMapper
, arg2
);
108 // InvocationToAllListenerMapper
109 InvocationToAllListenerMapper::InvocationToAllListenerMapper
110 ( const Reference
< XIdlClass
>& ListenerType
, const Reference
< XAllListener
>& AllListener
, const Any
& Helper
)
111 : m_xAllListener( AllListener
)
112 , m_xListenerType( ListenerType
)
118 Reference
< XIntrospectionAccess
> SAL_CALL
InvocationToAllListenerMapper::getIntrospection()
120 return Reference
< XIntrospectionAccess
>();
124 Any SAL_CALL
InvocationToAllListenerMapper::invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
,
125 Sequence
< sal_Int16
>& , Sequence
< Any
>& )
129 // Check if to firing or approveFiring has to be called
130 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( FunctionName
);
131 bool bApproveFiring
= false;
134 Reference
< XIdlClass
> xReturnType
= xMethod
->getReturnType();
135 Sequence
< Reference
< XIdlClass
> > aExceptionSeq
= xMethod
->getExceptionTypes();
136 if( ( xReturnType
.is() && xReturnType
->getTypeClass() != TypeClass_VOID
) ||
137 aExceptionSeq
.getLength() > 0 )
139 bApproveFiring
= true;
143 Sequence
< ParamInfo
> aParamSeq
= xMethod
->getParameterInfos();
144 sal_uInt32 nParamCount
= aParamSeq
.getLength();
145 if( nParamCount
> 1 )
147 const ParamInfo
* pInfo
= aParamSeq
.getConstArray();
148 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
150 if( pInfo
[ i
].aMode
!= ParamMode_IN
)
152 bApproveFiring
= true;
159 AllEventObject aAllEvent
;
160 aAllEvent
.Source
= static_cast<OWeakObject
*>(this);
161 aAllEvent
.Helper
= m_Helper
;
162 aAllEvent
.ListenerType
= Type(m_xListenerType
->getTypeClass(), m_xListenerType
->getName());
163 aAllEvent
.MethodName
= FunctionName
;
164 aAllEvent
.Arguments
= Params
;
166 aRet
= m_xAllListener
->approveFiring( aAllEvent
);
168 m_xAllListener
->firing( aAllEvent
);
173 void SAL_CALL
InvocationToAllListenerMapper::setValue(const OUString
& , const Any
& )
178 Any SAL_CALL
InvocationToAllListenerMapper::getValue(const OUString
& )
184 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasMethod(const OUString
& Name
)
186 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( Name
);
191 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasProperty(const OUString
& Name
)
193 Reference
< XIdlField
> xField
= m_xListenerType
->getField( Name
);
198 // class EventAttacherImpl
199 // represents an implementation of the EventAttacher service
201 class EventAttacherImpl
: public WeakImplHelper
< XEventAttacher2
, XInitialization
, XServiceInfo
>
204 explicit EventAttacherImpl( const Reference
< XComponentContext
>& );
207 virtual OUString SAL_CALL
getImplementationName( ) override
;
208 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
209 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) override
;
210 static Sequence
< OUString
> SAL_CALL
getSupportedServiceNames_Static( );
213 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
215 // Methoden von XEventAttacher
216 virtual Reference
< XEventListener
> SAL_CALL
attachListener(const Reference
< XInterface
>& xObject
,
217 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
,
218 const OUString
& ListenerType
, const OUString
& AddListenerParam
) override
;
219 virtual Reference
< XEventListener
> SAL_CALL
attachSingleEventListener(const Reference
< XInterface
>& xObject
,
220 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
,
221 const OUString
& ListenerType
, const OUString
& AddListenerParam
,
222 const OUString
& EventMethod
) override
;
223 virtual void SAL_CALL
removeListener(const Reference
< XInterface
>& xObject
,
224 const OUString
& ListenerType
, const OUString
& AddListenerParam
,
225 const Reference
< XEventListener
>& aToRemoveListener
) override
;
228 virtual Sequence
< Reference
<XEventListener
> > SAL_CALL
attachMultipleEventListeners(
229 const Reference
<XInterface
>& xObject
, const Sequence
<css::script::EventListener
>& aListeners
) override
;
231 // used by FilterAllListener_Impl
232 /// @throws Exception
233 Reference
< XTypeConverter
> getConverter();
235 friend class FilterAllListenerImpl
;
238 static Reference
<XEventListener
> attachListenerForTarget(
239 const Reference
<XIntrospectionAccess
>& xAccess
,
240 const Reference
<XInvocationAdapterFactory2
>& xInvocationAdapterFactory
,
241 const Reference
<XAllListener
>& xAllListener
,
244 const OUString
& aListenerType
,
245 const OUString
& aAddListenerParam
);
247 Sequence
< Reference
<XEventListener
> > attachListeners(
248 const Reference
<XInterface
>& xObject
,
249 const Sequence
< Reference
<XAllListener
> >& AllListeners
,
250 const Sequence
<css::script::EventListener
>& aListeners
);
254 Reference
< XComponentContext
> m_xContext
;
257 Reference
< XIntrospection
> m_xIntrospection
;
258 Reference
< XIdlReflection
> m_xReflection
;
259 Reference
< XTypeConverter
> m_xConverter
;
260 Reference
< XInvocationAdapterFactory2
> m_xInvocationAdapterFactory
;
263 /// @throws Exception
264 Reference
< XIntrospection
> getIntrospection();
265 /// @throws Exception
266 Reference
< XIdlReflection
> getReflection();
267 /// @throws Exception
268 Reference
< XInvocationAdapterFactory2
> getInvocationAdapterService();
272 EventAttacherImpl::EventAttacherImpl( const Reference
< XComponentContext
>& rxContext
)
273 : m_xContext( rxContext
)
277 /// @throws Exception
278 Reference
< XInterface
> SAL_CALL
EventAttacherImpl_CreateInstance( const Reference
< XMultiServiceFactory
>& rSMgr
)
280 XEventAttacher
*pEventAttacher
= static_cast<XEventAttacher
*>(new EventAttacherImpl( comphelper::getComponentContext(rSMgr
) ));
282 Reference
< XInterface
> xRet(pEventAttacher
, UNO_QUERY
);
288 OUString SAL_CALL
EventAttacherImpl::getImplementationName( )
290 return OUString( IMPLNAME
);
293 sal_Bool SAL_CALL
EventAttacherImpl::supportsService( const OUString
& ServiceName
)
295 return cppu::supportsService(this, ServiceName
);
298 Sequence
<OUString
> SAL_CALL
EventAttacherImpl::getSupportedServiceNames( )
300 return getSupportedServiceNames_Static();
304 Sequence
<OUString
> SAL_CALL
EventAttacherImpl::getSupportedServiceNames_Static( )
306 OUString
aStr( SERVICENAME
);
307 return Sequence
< OUString
>( &aStr
, 1 );
310 void SAL_CALL
EventAttacherImpl::initialize(const Sequence
< Any
>& Arguments
)
312 // get services from the argument list
313 const Any
* pArray
= Arguments
.getConstArray();
314 for( sal_Int32 i
= 0; i
< Arguments
.getLength(); i
++ )
316 if( pArray
[i
].getValueType().getTypeClass() != TypeClass_INTERFACE
)
317 throw IllegalArgumentException();
319 // InvocationAdapter service ?
320 Reference
< XInvocationAdapterFactory2
> xALAS
;
324 Guard
< Mutex
> aGuard( m_aMutex
);
325 m_xInvocationAdapterFactory
= xALAS
;
327 // Introspection service ?
328 Reference
< XIntrospection
> xI
;
332 Guard
< Mutex
> aGuard( m_aMutex
);
333 m_xIntrospection
= xI
;
335 // Reflection service ?
336 Reference
< XIdlReflection
> xIdlR
;
340 Guard
< Mutex
> aGuard( m_aMutex
);
341 m_xReflection
= xIdlR
;
343 // Converter Service ?
344 Reference
< XTypeConverter
> xC
;
348 Guard
< Mutex
> aGuard( m_aMutex
);
352 // no right interface
353 if( !xALAS
.is() && !xI
.is() && !xIdlR
.is() && !xC
.is() )
354 throw IllegalArgumentException();
359 //*** Private helper methods ***
360 Reference
< XIntrospection
> EventAttacherImpl::getIntrospection()
362 Guard
< Mutex
> aGuard( m_aMutex
);
363 if( !m_xIntrospection
.is() )
365 m_xIntrospection
= theIntrospection::get( m_xContext
);
367 return m_xIntrospection
;
371 //*** Private helper methods ***
372 Reference
< XIdlReflection
> EventAttacherImpl::getReflection()
374 Guard
< Mutex
> aGuard( m_aMutex
);
375 if( !m_xReflection
.is() )
377 m_xReflection
= theCoreReflection::get(m_xContext
);
379 return m_xReflection
;
383 //*** Private helper methods ***
384 Reference
< XInvocationAdapterFactory2
> EventAttacherImpl::getInvocationAdapterService()
386 Guard
< Mutex
> aGuard( m_aMutex
);
387 if( !m_xInvocationAdapterFactory
.is() )
389 m_xInvocationAdapterFactory
= InvocationAdapterFactory::create(m_xContext
);
391 return m_xInvocationAdapterFactory
;
395 //*** Private helper methods ***
396 Reference
< XTypeConverter
> EventAttacherImpl::getConverter()
398 Guard
< Mutex
> aGuard( m_aMutex
);
399 if( !m_xConverter
.is() )
401 m_xConverter
= Converter::create(m_xContext
);
407 // Implementation of an EventAttacher-related AllListeners, which brings
408 // a few Events to a general AllListener
409 class FilterAllListenerImpl
: public WeakImplHelper
< XAllListener
>
412 FilterAllListenerImpl( EventAttacherImpl
* pEA_
, const OUString
& EventMethod_
,
413 const Reference
< XAllListener
>& AllListener_
);
416 virtual void SAL_CALL
firing(const AllEventObject
& Event
) override
;
417 virtual Any SAL_CALL
approveFiring(const AllEventObject
& Event
) override
;
420 virtual void SAL_CALL
disposing(const EventObject
& Source
) override
;
424 /// @throws CannotConvertException
425 /// @throws RuntimeException
426 void convertToEventReturn( Any
& rRet
, const Type
& rRetType
);
428 EventAttacherImpl
* m_pEA
;
429 OUString m_EventMethod
;
430 Reference
< XAllListener
> m_AllListener
;
434 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl
* pEA_
, const OUString
& EventMethod_
,
435 const Reference
< XAllListener
>& AllListener_
)
437 , m_EventMethod( EventMethod_
)
438 , m_AllListener( AllListener_
)
443 void SAL_CALL
FilterAllListenerImpl::firing(const AllEventObject
& Event
)
445 if( Event
.MethodName
== m_EventMethod
&& m_AllListener
.is() )
446 m_AllListener
->firing( Event
);
449 // Convert to the standard event return
450 void FilterAllListenerImpl::convertToEventReturn( Any
& rRet
, const Type
& rRetType
)
452 // no return value? Set to the specified values
453 if( rRet
.getValueType().getTypeClass() == TypeClass_VOID
)
455 switch( rRetType
.getTypeClass() )
457 case TypeClass_INTERFACE
:
459 rRet
<<= Reference
< XInterface
>();
463 case TypeClass_BOOLEAN
:
467 case TypeClass_STRING
:
471 case TypeClass_FLOAT
: rRet
<<= float(0); break;
472 case TypeClass_DOUBLE
: rRet
<<= double(0.0); break;
473 case TypeClass_BYTE
: rRet
<<= sal_uInt8( 0 ); break;
474 case TypeClass_SHORT
: rRet
<<= sal_Int16( 0 ); break;
475 case TypeClass_LONG
: rRet
<<= sal_Int32( 0 ); break;
476 case TypeClass_UNSIGNED_SHORT
: rRet
<<= sal_uInt16( 0 ); break;
477 case TypeClass_UNSIGNED_LONG
: rRet
<<= sal_uInt32( 0 ); break;
482 else if( !rRet
.getValueType().equals( rRetType
) )
484 Reference
< XTypeConverter
> xConverter
= m_pEA
->getConverter();
485 if( xConverter
.is() )
486 rRet
= xConverter
->convertTo( rRet
, rRetType
);
488 throw CannotConvertException(); // TODO TypeConversionException
493 Any SAL_CALL
FilterAllListenerImpl::approveFiring( const AllEventObject
& Event
)
497 if( Event
.MethodName
== m_EventMethod
&& m_AllListener
.is() )
498 aRet
= m_AllListener
->approveFiring( Event
);
501 // Convert to the standard event return
504 Reference
< XIdlClass
> xListenerType
= m_pEA
->getReflection()->
505 forName( Event
.ListenerType
.getTypeName() );
506 Reference
< XIdlMethod
> xMeth
= xListenerType
->getMethod( Event
.MethodName
);
509 Reference
< XIdlClass
> xRetType
= xMeth
->getReturnType();
510 Type
aRetType( xRetType
->getTypeClass(), xRetType
->getName() );
511 convertToEventReturn( aRet
, aRetType
);
514 catch( const CannotConvertException
& e
)
516 throw InvocationTargetException( OUString(), Reference
< XInterface
>(), Any(&e
, cppu::UnoType
<CannotConvertException
>::get()) );
523 void FilterAllListenerImpl::disposing(const EventObject
& )
529 Reference
< XEventListener
> EventAttacherImpl::attachListener
531 const Reference
< XInterface
>& xObject
,
532 const Reference
< XAllListener
>& AllListener
,
534 const OUString
& ListenerType
,
535 const OUString
& AddListenerParam
538 if( !xObject
.is() || !AllListener
.is() )
539 throw IllegalArgumentException();
541 Reference
< XInvocationAdapterFactory2
> xInvocationAdapterFactory
= getInvocationAdapterService();
542 if( !xInvocationAdapterFactory
.is() )
543 throw ServiceNotRegisteredException();
545 Reference
< XIdlReflection
> xReflection
= getReflection();
546 if( !xReflection
.is() )
547 throw ServiceNotRegisteredException();
549 // Sign in, Call the fitting addListener method
550 // First Introspection, as the Methods can be analyzed in the same way
551 // For better performance it is implemented here again or make the Impl-Method
552 // of the Introspection configurable for this purpose.
553 Reference
< XIntrospection
> xIntrospection
= getIntrospection();
554 if( !xIntrospection
.is() )
555 return Reference
<XEventListener
>();
557 // Inspect Introspection
558 Any
aObjAny( &xObject
, cppu::UnoType
<XInterface
>::get());
560 Reference
< XIntrospectionAccess
> xAccess
= xIntrospection
->inspect( aObjAny
);
562 return Reference
<XEventListener
>();
564 return attachListenerForTarget(
565 xAccess
, xInvocationAdapterFactory
, AllListener
, aObjAny
, Helper
,
566 ListenerType
, AddListenerParam
);
569 Reference
<XEventListener
> EventAttacherImpl::attachListenerForTarget(
570 const Reference
<XIntrospectionAccess
>& xAccess
,
571 const Reference
<XInvocationAdapterFactory2
>& xInvocationAdapterFactory
,
572 const Reference
<XAllListener
>& xAllListener
,
575 const OUString
& aListenerType
,
576 const OUString
& aAddListenerParam
)
578 Reference
< XEventListener
> xRet
= nullptr;
580 // Construct the name of the addListener-Method.
581 sal_Int32 nIndex
= aListenerType
.lastIndexOf('.');
582 // set index to the interface name without package name
589 OUString aListenerName
= (!aListenerType
.isEmpty() && aListenerType
[nIndex
] == 'X') ? aListenerType
.copy(nIndex
+1) : aListenerType
;
590 OUString aAddListenerName
= "add" + aListenerName
;
592 // Send Methods to the correct addListener-Method
593 Sequence
< Reference
< XIdlMethod
> > aMethodSeq
= xAccess
->getMethods( MethodConcept::LISTENER
);
594 const Reference
< XIdlMethod
>* pMethods
= aMethodSeq
.getConstArray();
595 for (sal_Int32 i
= 0, n
= aMethodSeq
.getLength(); i
< n
; ++i
)
597 const Reference
< XIdlMethod
>& rxMethod
= pMethods
[i
];
599 // Is it the correct method?
600 OUString aMethName
= rxMethod
->getName();
602 if (aAddListenerName
!= aMethName
)
605 Sequence
< Reference
< XIdlClass
> > params
= rxMethod
->getParameterTypes();
606 sal_uInt32 nParamCount
= params
.getLength();
608 Reference
< XIdlClass
> xListenerType
;
609 if( nParamCount
== 1 )
610 xListenerType
= params
.getConstArray()[0];
611 else if( nParamCount
== 2 )
612 xListenerType
= params
.getConstArray()[1];
614 // Request Adapter for the actual Listener type
615 Reference
< XInterface
> xAdapter
= createAllListenerAdapter(
616 xInvocationAdapterFactory
, xListenerType
, xAllListener
, aHelper
);
619 throw CannotCreateAdapterException();
620 xRet
.set( xAdapter
, UNO_QUERY
);
622 // Just the Listener as parameter?
623 if( nParamCount
== 1 )
625 Sequence
< Any
> args( 1 );
626 args
.getArray()[0] <<= xAdapter
;
629 rxMethod
->invoke( aObject
, args
);
631 catch( const InvocationTargetException
& )
633 throw IntrospectionException();
636 // Else, pass the other parameter now
637 else if( nParamCount
== 2 )
639 Sequence
< Any
> args( 2 );
640 Any
* pAnys
= args
.getArray();
642 // Check the type of the 1st parameter
643 Reference
< XIdlClass
> xParamClass
= params
.getConstArray()[0];
644 if( xParamClass
->getTypeClass() == TypeClass_STRING
)
646 pAnys
[0] <<= aAddListenerParam
;
649 // 2nd Parameter == Listener? TODO: Test!
650 pAnys
[1] <<= xAdapter
;
652 // TODO: Convert String -> ?
656 rxMethod
->invoke( aObject
, args
);
658 catch( const InvocationTargetException
& )
660 throw IntrospectionException();
665 // Anything else is not supported
671 Sequence
< Reference
<XEventListener
> > EventAttacherImpl::attachListeners(
672 const Reference
<XInterface
>& xObject
,
673 const Sequence
< Reference
<XAllListener
> >& AllListeners
,
674 const Sequence
<css::script::EventListener
>& aListeners
)
676 sal_Int32 nCount
= aListeners
.getLength();
677 if (nCount
!= AllListeners
.getLength())
678 // This is a prerequisite!
679 throw RuntimeException();
682 throw IllegalArgumentException();
684 Reference
< XInvocationAdapterFactory2
> xInvocationAdapterFactory
= getInvocationAdapterService();
685 if( !xInvocationAdapterFactory
.is() )
686 throw ServiceNotRegisteredException();
688 Reference
< XIdlReflection
> xReflection
= getReflection();
689 if( !xReflection
.is() )
690 throw ServiceNotRegisteredException();
692 // Sign in, Call the fitting addListener method
693 // First Introspection, as the Methods can be analyzed in the same way
694 // For better performance it is implemented here again or make the Impl-Method
695 // of the Introspection configurable for this purpose.
696 Reference
< XIntrospection
> xIntrospection
= getIntrospection();
697 if( !xIntrospection
.is() )
698 return Sequence
< Reference
<XEventListener
> >();
700 // Inspect Introspection
701 Any
aObjAny( &xObject
, cppu::UnoType
<XInterface
>::get() );
703 Reference
<XIntrospectionAccess
> xAccess
= xIntrospection
->inspect(aObjAny
);
705 return Sequence
< Reference
<XEventListener
> >();
707 Sequence
< Reference
<XEventListener
> > aRet(nCount
);
708 Reference
<XEventListener
>* pArray
= aRet
.getArray();
710 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
712 pArray
[i
] = attachListenerForTarget(
713 xAccess
, xInvocationAdapterFactory
, AllListeners
[ i
],
714 aObjAny
, aListeners
[i
].Helper
, aListeners
[i
].ListenerType
, aListeners
[i
].AddListenerParam
);
721 Reference
< XEventListener
> EventAttacherImpl::attachSingleEventListener
723 const Reference
< XInterface
>& xObject
,
724 const Reference
< XAllListener
>& AllListener
,
726 const OUString
& ListenerType
,
727 const OUString
& AddListenerParam
,
728 const OUString
& EventMethod
731 // Subscribe FilterListener
732 Reference
< XAllListener
> aFilterListener
= static_cast<XAllListener
*>(
733 new FilterAllListenerImpl( this, EventMethod
, AllListener
));
734 return attachListener( xObject
, aFilterListener
, Helper
, ListenerType
, AddListenerParam
);
738 void EventAttacherImpl::removeListener
740 const Reference
< XInterface
>& xObject
,
741 const OUString
& ListenerType
,
742 const OUString
& AddListenerParam
,
743 const Reference
< XEventListener
>& aToRemoveListener
746 if( !xObject
.is() || !aToRemoveListener
.is() )
747 throw IllegalArgumentException();
749 Reference
< XIdlReflection
> xReflection
= getReflection();
750 if( !xReflection
.is() )
751 throw IntrospectionException();
753 // Sign off, Call the fitting removeListener method
754 // First Introspection, as the Methods can be analyzed in the same way
755 // For better performance it is implemented here again or make the Impl-Method
756 // of the Introspection configurable for this purpose.
757 Reference
< XIntrospection
> xIntrospection
= getIntrospection();
758 if( !xIntrospection
.is() )
759 throw IntrospectionException();
761 //Inspect Introspection
762 Any
aObjAny( &xObject
, cppu::UnoType
<XInterface
>::get());
763 Reference
< XIntrospectionAccess
> xAccess
= xIntrospection
->inspect( aObjAny
);
765 throw IntrospectionException();
767 // Create name of the removeListener-Method
768 OUString aRemoveListenerName
;
769 OUString
aListenerName( ListenerType
);
770 sal_Int32 nIndex
= aListenerName
.lastIndexOf( '.' );
771 // set index to the interface name without package name
777 if( aListenerName
[nIndex
] == 'X' )
778 // erase X from the interface name
779 aListenerName
= aListenerName
.copy( nIndex
+1 );
780 aRemoveListenerName
= "remove" + aListenerName
;
782 // Search methods for the correct removeListener method
783 Sequence
< Reference
< XIdlMethod
> > aMethodSeq
= xAccess
->getMethods( MethodConcept::LISTENER
);
784 sal_uInt32 i
, nLen
= aMethodSeq
.getLength();
785 const Reference
< XIdlMethod
>* pMethods
= aMethodSeq
.getConstArray();
786 for( i
= 0 ; i
< nLen
; i
++ )
789 const Reference
< XIdlMethod
>& rxMethod
= pMethods
[i
];
791 // Is it the right method?
792 if( aRemoveListenerName
== rxMethod
->getName() )
794 Sequence
< Reference
< XIdlClass
> > params
= rxMethod
->getParameterTypes();
795 sal_uInt32 nParamCount
= params
.getLength();
797 // Just the Listener as parameter?
798 if( nParamCount
== 1 )
800 Sequence
< Any
> args( 1 );
801 args
.getArray()[0] <<= aToRemoveListener
;
804 rxMethod
->invoke( aObjAny
, args
);
806 catch( const InvocationTargetException
& )
808 throw IntrospectionException();
811 // Else pass the other parameter
812 else if( nParamCount
== 2 )
814 Sequence
< Any
> args( 2 );
815 Any
* pAnys
= args
.getArray();
817 // Check the type of the 1st parameter
818 Reference
< XIdlClass
> xParamClass
= params
.getConstArray()[0];
819 if( xParamClass
->getTypeClass() == TypeClass_STRING
)
820 pAnys
[0] <<= AddListenerParam
;
822 // 2nd parameter == Listener? TODO: Test!
823 pAnys
[1] <<= aToRemoveListener
;
825 // TODO: Convert String -> ?
829 rxMethod
->invoke( aObjAny
, args
);
831 catch( const InvocationTargetException
& )
833 throw IntrospectionException();
841 Sequence
< Reference
<XEventListener
> > EventAttacherImpl::attachMultipleEventListeners(
842 const Reference
<XInterface
>& xObject
, const Sequence
<css::script::EventListener
>& aListeners
)
844 sal_Int32 nCount
= aListeners
.getLength();
845 Sequence
< Reference
<XAllListener
> > aFilterListeners(nCount
);
846 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
848 aFilterListeners
[i
] = static_cast<XAllListener
*>(
849 new FilterAllListenerImpl(this, aListeners
[i
].EventMethod
, aListeners
[i
].AllListener
));
852 return attachListeners(xObject
, aFilterListeners
, aListeners
);
859 SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
evtatt_component_getFactory(
860 const sal_Char
* pImplName
, void * pServiceManager
, void * )
862 void * pRet
= nullptr;
864 if (pServiceManager
&& rtl_str_compare( pImplName
, IMPLNAME
) == 0)
866 Reference
< XSingleServiceFactory
> xFactory( createOneInstanceFactory(
867 static_cast< XMultiServiceFactory
* >( pServiceManager
),
869 ::comp_EventAttacher::EventAttacherImpl_CreateInstance
,
870 ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) );
875 pRet
= xFactory
.get();
884 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */