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 <osl/diagnose.h>
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/Introspection.hpp>
26 #include <com/sun/star/beans/MethodConcept.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/XInvocationAdapterFactory.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 <comphelper/processfactory.hxx>
37 #include <cppuhelper/weak.hxx>
38 #include <cppuhelper/factory.hxx>
39 #include <cppuhelper/implbase1.hxx>
40 #include <cppuhelper/implbase3.hxx>
42 using namespace com::sun::star::uno
;
43 using namespace com::sun::star::registry
;
44 using namespace com::sun::star::lang
;
45 using namespace com::sun::star::beans
;
46 using namespace com::sun::star::script
;
47 using namespace com::sun::star::reflection
;
51 using ::rtl::OUString
;
54 #define SERVICENAME "com.sun.star.script.EventAttacher"
55 #define IMPLNAME "com.sun.star.comp.EventAttacher"
57 namespace comp_EventAttacher
{
59 //*************************************************************************
60 // class InvocationToAllListenerMapper
61 // helper class to map XInvocation to XAllListener
62 //*************************************************************************
63 class InvocationToAllListenerMapper
: public WeakImplHelper1
< XInvocation
>
66 InvocationToAllListenerMapper( const Reference
< XIdlClass
>& ListenerType
,
67 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
);
70 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection(void) throw( RuntimeException
);
71 virtual Any SAL_CALL
invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
, Sequence
< sal_Int16
>& OutParamIndex
, Sequence
< Any
>& OutParam
)
72 throw( IllegalArgumentException
, CannotConvertException
, InvocationTargetException
, RuntimeException
);
73 virtual void SAL_CALL
setValue(const OUString
& PropertyName
, const Any
& Value
)
74 throw( UnknownPropertyException
, CannotConvertException
, InvocationTargetException
, RuntimeException
);
75 virtual Any SAL_CALL
getValue(const OUString
& PropertyName
) throw( UnknownPropertyException
, RuntimeException
);
76 virtual sal_Bool SAL_CALL
hasMethod(const OUString
& Name
) throw( RuntimeException
);
77 virtual sal_Bool SAL_CALL
hasProperty(const OUString
& Name
) throw( RuntimeException
);
80 Reference
< XIdlReflection
> m_xCoreReflection
;
81 Reference
< XAllListener
> m_xAllListener
;
82 Reference
< XIdlClass
> m_xListenerType
;
87 // Function to replace AllListenerAdapterService::createAllListerAdapter
88 Reference
< XInterface
> createAllListenerAdapter
90 const Reference
< XInvocationAdapterFactory
>& 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 (XInvocation
*)new InvocationToAllListenerMapper( xListenerType
, xListener
, Helper
);
101 Type
aListenerType( xListenerType
->getTypeClass(), xListenerType
->getName());
102 xAdapter
= xInvocationAdapterFactory
->createAdapter( xInvocationToAllListenerMapper
, aListenerType
);
108 //--------------------------------------------------------------------------------------------------
109 // InvocationToAllListenerMapper
110 InvocationToAllListenerMapper::InvocationToAllListenerMapper
111 ( const Reference
< XIdlClass
>& ListenerType
, const Reference
< XAllListener
>& AllListener
, const Any
& Helper
)
112 : m_xAllListener( AllListener
)
113 , m_xListenerType( ListenerType
)
118 //*************************************************************************
119 Reference
< XIntrospectionAccess
> SAL_CALL
InvocationToAllListenerMapper::getIntrospection(void)
120 throw( RuntimeException
)
122 return Reference
< XIntrospectionAccess
>();
125 //*************************************************************************
126 Any SAL_CALL
InvocationToAllListenerMapper::invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
,
127 Sequence
< sal_Int16
>& , Sequence
< Any
>& )
128 throw( IllegalArgumentException
, CannotConvertException
,
129 InvocationTargetException
, RuntimeException
)
133 // Check if to firing or approveFiring has to be called
134 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( FunctionName
);
135 sal_Bool bApproveFiring
= sal_False
;
138 Reference
< XIdlClass
> xReturnType
= xMethod
->getReturnType();
139 Sequence
< Reference
< XIdlClass
> > aExceptionSeq
= xMethod
->getExceptionTypes();
140 if( ( xReturnType
.is() && xReturnType
->getTypeClass() != TypeClass_VOID
) ||
141 aExceptionSeq
.getLength() > 0 )
143 bApproveFiring
= sal_True
;
147 Sequence
< ParamInfo
> aParamSeq
= xMethod
->getParameterInfos();
148 sal_uInt32 nParamCount
= aParamSeq
.getLength();
149 if( nParamCount
> 1 )
151 const ParamInfo
* pInfos
= aParamSeq
.getConstArray();
152 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
154 if( pInfos
[ i
].aMode
!= ParamMode_IN
)
156 bApproveFiring
= sal_True
;
163 AllEventObject aAllEvent
;
164 aAllEvent
.Source
= (OWeakObject
*) this;
165 aAllEvent
.Helper
= m_Helper
;
166 aAllEvent
.ListenerType
= Type(m_xListenerType
->getTypeClass(), m_xListenerType
->getName());
167 aAllEvent
.MethodName
= FunctionName
;
168 aAllEvent
.Arguments
= Params
;
170 aRet
= m_xAllListener
->approveFiring( aAllEvent
);
172 m_xAllListener
->firing( aAllEvent
);
176 //*************************************************************************
177 void SAL_CALL
InvocationToAllListenerMapper::setValue(const OUString
& , const Any
& )
178 throw( UnknownPropertyException
, CannotConvertException
,
179 InvocationTargetException
, RuntimeException
)
183 //*************************************************************************
184 Any SAL_CALL
InvocationToAllListenerMapper::getValue(const OUString
& )
185 throw( UnknownPropertyException
, RuntimeException
)
190 //*************************************************************************
191 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasMethod(const OUString
& Name
)
192 throw( RuntimeException
)
194 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( Name
);
198 //*************************************************************************
199 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasProperty(const OUString
& Name
)
200 throw( RuntimeException
)
202 Reference
< XIdlField
> xField
= m_xListenerType
->getField( Name
);
206 //*************************************************************************
207 // class EventAttacherImpl
208 // represents an implementation of the EventAttacher service
209 //*************************************************************************
210 class EventAttacherImpl
: public WeakImplHelper3
< XEventAttacher2
, XInitialization
, XServiceInfo
>
213 EventAttacherImpl( const Reference
< XMultiServiceFactory
>& );
214 ~EventAttacherImpl();
217 virtual OUString SAL_CALL
getImplementationName( ) throw(RuntimeException
);
218 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) throw(RuntimeException
);
219 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) throw(RuntimeException
);
220 static OUString SAL_CALL
getImplementationName_Static( );
221 static Sequence
< OUString
> SAL_CALL
getSupportedServiceNames_Static( );
224 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
)
225 throw( Exception
, RuntimeException
);
227 // Methoden von XEventAttacher
228 virtual Reference
< XEventListener
> SAL_CALL
attachListener(const Reference
< XInterface
>& xObject
,
229 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
,
230 const OUString
& ListenerType
, const OUString
& AddListenerParam
)
231 throw( IllegalArgumentException
, ServiceNotRegisteredException
, CannotCreateAdapterException
, IntrospectionException
, RuntimeException
);
232 virtual Reference
< XEventListener
> SAL_CALL
attachSingleEventListener(const Reference
< XInterface
>& xObject
,
233 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
,
234 const OUString
& ListenerType
, const OUString
& AddListenerParam
,
235 const OUString
& EventMethod
)
236 throw( IllegalArgumentException
, ServiceNotRegisteredException
, CannotCreateAdapterException
, IntrospectionException
, RuntimeException
);
237 virtual void SAL_CALL
removeListener(const Reference
< XInterface
>& xObject
,
238 const OUString
& ListenerType
, const OUString
& AddListenerParam
,
239 const Reference
< XEventListener
>& aToRemoveListener
)
240 throw( IllegalArgumentException
, IntrospectionException
, RuntimeException
);
243 virtual Sequence
< Reference
<XEventListener
> > SAL_CALL
attachMultipleEventListeners(
244 const Reference
<XInterface
>& xObject
, const Sequence
<com::sun::star::script::EventListener
>& aListeners
)
245 throw( IllegalArgumentException
, ServiceNotRegisteredException
, CannotCreateAdapterException
, IntrospectionException
, RuntimeException
);
247 // used by FilterAllListener_Impl
248 Reference
< XTypeConverter
> getConverter() throw( Exception
);
250 friend class FilterAllListenerImpl
;
253 Reference
<XEventListener
> attachListenerForTarget(
254 const Reference
<XIntrospectionAccess
>& xAccess
,
255 const Reference
<XInvocationAdapterFactory
>& xInvocationAdapterFactory
,
256 const Reference
<XAllListener
>& xAllListener
,
259 const OUString
& aListenerType
,
260 const OUString
& aAddListenerParam
);
262 Sequence
< Reference
<XEventListener
> > attachListeners(
263 const Reference
<XInterface
>& xObject
,
264 const Sequence
< Reference
<XAllListener
> >& AllListeners
,
265 const Sequence
<com::sun::star::script::EventListener
>& aListeners
);
269 Reference
< XMultiServiceFactory
> m_xSMgr
;
272 Reference
< XIntrospection
> m_xIntrospection
;
273 Reference
< XIdlReflection
> m_xReflection
;
274 Reference
< XTypeConverter
> m_xConverter
;
275 Reference
< XInvocationAdapterFactory
> m_xInvocationAdapterFactory
;
278 Reference
< XIntrospection
> getIntrospection() throw( Exception
);
279 Reference
< XIdlReflection
> getReflection() throw( Exception
);
280 Reference
< XInvocationAdapterFactory
> getInvocationAdapterService() throw( Exception
);
284 //*************************************************************************
285 EventAttacherImpl::EventAttacherImpl( const Reference
< XMultiServiceFactory
>& rSMgr
)
290 //*************************************************************************
291 EventAttacherImpl::~EventAttacherImpl()
295 //*************************************************************************
296 Reference
< XInterface
> SAL_CALL
EventAttacherImpl_CreateInstance( const Reference
< XMultiServiceFactory
>& rSMgr
) throw( Exception
)
298 Reference
< XInterface
> xRet
;
299 XEventAttacher
*pEventAttacher
= (XEventAttacher
*) new EventAttacherImpl(rSMgr
);
303 xRet
= Reference
<XInterface
>::query(pEventAttacher
);
309 //*************************************************************************
310 OUString SAL_CALL
EventAttacherImpl::getImplementationName( )
311 throw(RuntimeException
)
313 return OUString( IMPLNAME
);
316 //*************************************************************************
317 sal_Bool SAL_CALL
EventAttacherImpl::supportsService( const OUString
& ServiceName
)
318 throw(RuntimeException
)
320 Sequence
< OUString
> aSNL
= getSupportedServiceNames();
321 const OUString
* pArray
= aSNL
.getArray();
322 for( sal_Int32 i
= 0; i
< aSNL
.getLength(); i
++ )
323 if( pArray
[i
] == ServiceName
)
328 //*************************************************************************
329 Sequence
<OUString
> SAL_CALL
EventAttacherImpl::getSupportedServiceNames( )
330 throw(RuntimeException
)
332 return getSupportedServiceNames_Static();
335 //*************************************************************************
336 Sequence
<OUString
> SAL_CALL
EventAttacherImpl::getSupportedServiceNames_Static( )
338 OUString
aStr( SERVICENAME
);
339 return Sequence
< OUString
>( &aStr
, 1 );
342 //*************************************************************************
343 void SAL_CALL
EventAttacherImpl::initialize(const Sequence
< Any
>& Arguments
) throw( Exception
, RuntimeException
)
345 // get services from the argument list
346 const Any
* pArray
= Arguments
.getConstArray();
347 for( sal_Int32 i
= 0; i
< Arguments
.getLength(); i
++ )
349 if( pArray
[i
].getValueType().getTypeClass() != TypeClass_INTERFACE
)
350 throw IllegalArgumentException();
352 // InvocationAdapter service ?
353 Reference
< XInvocationAdapterFactory
> xALAS
;
357 Guard
< Mutex
> aGuard( m_aMutex
);
358 m_xInvocationAdapterFactory
= xALAS
;
360 // Introspection service ?
361 Reference
< XIntrospection
> xI
;
365 Guard
< Mutex
> aGuard( m_aMutex
);
366 m_xIntrospection
= xI
;
368 // Reflection service ?
369 Reference
< XIdlReflection
> xIdlR
;
373 Guard
< Mutex
> aGuard( m_aMutex
);
374 m_xReflection
= xIdlR
;
376 // Converter Service ?
377 Reference
< XTypeConverter
> xC
;
381 Guard
< Mutex
> aGuard( m_aMutex
);
385 // no right interface
386 if( !xALAS
.is() && !xI
.is() && !xIdlR
.is() && !xC
.is() )
387 throw IllegalArgumentException();
391 //*************************************************************************
392 //*** Private helper methods ***
393 Reference
< XIntrospection
> EventAttacherImpl::getIntrospection() throw( Exception
)
395 Guard
< Mutex
> aGuard( m_aMutex
);
396 if( !m_xIntrospection
.is() )
398 m_xIntrospection
= Introspection::create( comphelper::getComponentContext(m_xSMgr
) );
400 return m_xIntrospection
;
403 //*************************************************************************
404 //*** Private helper methods ***
405 Reference
< XIdlReflection
> EventAttacherImpl::getReflection() throw( Exception
)
407 Guard
< Mutex
> aGuard( m_aMutex
);
408 if( !m_xReflection
.is() )
410 m_xReflection
= theCoreReflection::get(comphelper::getComponentContext(m_xSMgr
));
412 return m_xReflection
;
415 //*************************************************************************
416 //*** Private helper methods ***
417 Reference
< XInvocationAdapterFactory
> EventAttacherImpl::getInvocationAdapterService() throw( Exception
)
419 Guard
< Mutex
> aGuard( m_aMutex
);
420 if( !m_xInvocationAdapterFactory
.is() )
422 Reference
< XInterface
> xIFace( m_xSMgr
->createInstance( rtl::OUString("com.sun.star.script.InvocationAdapterFactory") ) );
423 m_xInvocationAdapterFactory
= Reference
< XInvocationAdapterFactory
>( xIFace
, UNO_QUERY
);
425 return m_xInvocationAdapterFactory
;
429 //*************************************************************************
430 //*** Private helper methods ***
431 Reference
< XTypeConverter
> EventAttacherImpl::getConverter() throw( Exception
)
433 Guard
< Mutex
> aGuard( m_aMutex
);
434 if( !m_xConverter
.is() )
436 m_xConverter
= Converter::create(comphelper::getComponentContext(m_xSMgr
));
441 //------------------------------------------------------------------------
442 //------------------------------------------------------------------------
443 //------------------------------------------------------------------------
444 // Implementation of an EventAttacher-related AllListeners, which brings
445 // a few Events to a general AllListener
446 class FilterAllListenerImpl
: public WeakImplHelper1
< XAllListener
>
449 FilterAllListenerImpl( EventAttacherImpl
* pEA_
, const OUString
& EventMethod_
,
450 const Reference
< XAllListener
>& AllListener_
);
453 virtual void SAL_CALL
firing(const AllEventObject
& Event
) throw( RuntimeException
);
454 virtual Any SAL_CALL
approveFiring(const AllEventObject
& Event
) throw( InvocationTargetException
, RuntimeException
);
457 virtual void SAL_CALL
disposing(const EventObject
& Source
) throw( RuntimeException
);
461 void convertToEventReturn( Any
& rRet
, const Type
& rRetType
)
462 throw( CannotConvertException
);
464 EventAttacherImpl
* m_pEA
;
465 Reference
< XInterface
> m_xEAHold
;
466 OUString m_EventMethod
;
467 Reference
< XAllListener
> m_AllListener
;
470 //*************************************************************************
471 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl
* pEA_
, const OUString
& EventMethod_
,
472 const Reference
< XAllListener
>& AllListener_
)
475 , m_EventMethod( EventMethod_
)
476 , m_AllListener( AllListener_
)
480 //*************************************************************************
481 void SAL_CALL
FilterAllListenerImpl::firing(const AllEventObject
& Event
)
482 throw( RuntimeException
)
484 if( Event
.MethodName
== m_EventMethod
&& m_AllListener
.is() )
485 m_AllListener
->firing( Event
);
488 //*************************************************************************
489 // Convert to the standard event return
490 void FilterAllListenerImpl::convertToEventReturn( Any
& rRet
, const Type
& rRetType
)
491 throw( CannotConvertException
)
493 // no return value? Set to the specified values
494 if( rRet
.getValueType().getTypeClass() == TypeClass_VOID
)
496 switch( rRetType
.getTypeClass() )
498 case TypeClass_INTERFACE
:
500 rRet
<<= Reference
< XInterface
>();
504 case TypeClass_BOOLEAN
:
508 case TypeClass_STRING
:
512 case TypeClass_FLOAT
: rRet
<<= float(0); break;
513 case TypeClass_DOUBLE
: rRet
<<= double(0.0); break;
514 case TypeClass_BYTE
: rRet
<<= sal_uInt8( 0 ); break;
515 case TypeClass_SHORT
: rRet
<<= sal_Int16( 0 ); break;
516 case TypeClass_LONG
: rRet
<<= sal_Int32( 0 ); break;
517 case TypeClass_UNSIGNED_SHORT
: rRet
<<= sal_uInt16( 0 ); break;
518 case TypeClass_UNSIGNED_LONG
: rRet
<<= sal_uInt32( 0 ); break;
523 else if( !rRet
.getValueType().equals( rRetType
) )
525 Reference
< XTypeConverter
> xConverter
= m_pEA
->getConverter();
526 if( xConverter
.is() )
527 rRet
= xConverter
->convertTo( rRet
, rRetType
);
529 throw CannotConvertException(); // TODO TypeConversionException
533 //*************************************************************************
534 Any SAL_CALL
FilterAllListenerImpl::approveFiring( const AllEventObject
& Event
)
535 throw( InvocationTargetException
, RuntimeException
)
539 if( Event
.MethodName
== m_EventMethod
&& m_AllListener
.is() )
540 aRet
= m_AllListener
->approveFiring( Event
);
543 // Convert to the standard event return
546 Reference
< XIdlClass
> xListenerType
= m_pEA
->getReflection()->
547 forName( Event
.ListenerType
.getTypeName() );
548 Reference
< XIdlMethod
> xMeth
= xListenerType
->getMethod( Event
.MethodName
);
551 Reference
< XIdlClass
> xRetType
= xMeth
->getReturnType();
552 Type
aRetType( xRetType
->getTypeClass(), xRetType
->getName() );
553 convertToEventReturn( aRet
, aRetType
);
556 catch( const CannotConvertException
& e
)
558 throw InvocationTargetException( OUString(), Reference
< XInterface
>(), Any(&e
, ::getCppuType( (CannotConvertException
*)0)) );
564 //*************************************************************************
565 void FilterAllListenerImpl::disposing(const EventObject
& )
566 throw( RuntimeException
)
572 //*************************************************************************
573 Reference
< XEventListener
> EventAttacherImpl::attachListener
575 const Reference
< XInterface
>& xObject
,
576 const Reference
< XAllListener
>& AllListener
,
578 const OUString
& ListenerType
,
579 const OUString
& AddListenerParam
581 throw( IllegalArgumentException
, ServiceNotRegisteredException
, CannotCreateAdapterException
, IntrospectionException
, RuntimeException
)
583 if( !xObject
.is() || !AllListener
.is() )
584 throw IllegalArgumentException();
586 Reference
< XInvocationAdapterFactory
> xInvocationAdapterFactory
= getInvocationAdapterService();
587 if( !xInvocationAdapterFactory
.is() )
588 throw ServiceNotRegisteredException();
590 Reference
< XIdlReflection
> xReflection
= getReflection();
591 if( !xReflection
.is() )
592 throw ServiceNotRegisteredException();
594 // Sign in, Call the fitting addListener method
595 // First Introspection, as the Methods can be analyzed in the same way
596 // For better perfomance it is implemented here again or make the Impl-Method
597 // of the Introspection configurable for this purpose.
598 Reference
< XIntrospection
> xIntrospection
= getIntrospection();
599 if( !xIntrospection
.is() )
600 return Reference
<XEventListener
>();
602 // Inspect Introspection
603 Any
aObjAny( &xObject
, ::getCppuType( (const Reference
< XInterface
> *)0) );
605 Reference
< XIntrospectionAccess
> xAccess
= xIntrospection
->inspect( aObjAny
);
607 return Reference
<XEventListener
>();
609 return attachListenerForTarget(
610 xAccess
, xInvocationAdapterFactory
, AllListener
, aObjAny
, Helper
,
611 ListenerType
, AddListenerParam
);
614 Reference
<XEventListener
> EventAttacherImpl::attachListenerForTarget(
615 const Reference
<XIntrospectionAccess
>& xAccess
,
616 const Reference
<XInvocationAdapterFactory
>& xInvocationAdapterFactory
,
617 const Reference
<XAllListener
>& xAllListener
,
620 const OUString
& aListenerType
,
621 const OUString
& aAddListenerParam
)
623 Reference
< XEventListener
> xRet
= NULL
;
625 // Construct the name of the addListener-Method.
626 sal_Int32 nIndex
= aListenerType
.lastIndexOf('.');
627 // set index to the interface name without package name
634 OUString aListenerName
= (aListenerType
[nIndex
] == 'X') ? aListenerType
.copy(nIndex
+1) : aListenerType
;
635 OUString aAddListenerName
= OUString("add") + aListenerName
;
637 // Send Methods to the correct addListener-Method
638 Sequence
< Reference
< XIdlMethod
> > aMethodSeq
= xAccess
->getMethods( MethodConcept::LISTENER
);
639 const Reference
< XIdlMethod
>* pMethods
= aMethodSeq
.getConstArray();
640 for (sal_Int32 i
= 0, n
= aMethodSeq
.getLength(); i
< n
; ++i
)
642 const Reference
< XIdlMethod
>& rxMethod
= pMethods
[i
];
644 // Is it the correct method?
645 OUString aMethName
= rxMethod
->getName();
647 if (aAddListenerName
!= aMethName
)
650 Sequence
< Reference
< XIdlClass
> > params
= rxMethod
->getParameterTypes();
651 sal_uInt32 nParamCount
= params
.getLength();
653 Reference
< XIdlClass
> xListenerType
;
654 if( nParamCount
== 1 )
655 xListenerType
= params
.getConstArray()[0];
656 else if( nParamCount
== 2 )
657 xListenerType
= params
.getConstArray()[1];
659 // Request Adapter for the actual Listener type
660 Reference
< XInterface
> xAdapter
= createAllListenerAdapter(
661 xInvocationAdapterFactory
, xListenerType
, xAllListener
, aHelper
);
664 throw CannotCreateAdapterException();
665 xRet
= Reference
< XEventListener
>( xAdapter
, UNO_QUERY
);
667 // Just the Listener as parameter?
668 if( nParamCount
== 1 )
670 Sequence
< Any
> args( 1 );
671 args
.getArray()[0] <<= xAdapter
;
674 rxMethod
->invoke( aObject
, args
);
676 catch( const InvocationTargetException
& )
678 throw IntrospectionException();
681 // Else, pass the other parameter now
682 else if( nParamCount
== 2 )
684 Sequence
< Any
> args( 2 );
685 Any
* pAnys
= args
.getArray();
687 // Check the type of the 1st parameter
688 Reference
< XIdlClass
> xParamClass
= params
.getConstArray()[0];
689 if( xParamClass
->getTypeClass() == TypeClass_STRING
)
691 pAnys
[0] <<= aAddListenerParam
;
694 // 2nd Parameter == Listener? TODO: Test!
695 pAnys
[1] <<= xAdapter
;
697 // TODO: Convert String -> ?
701 rxMethod
->invoke( aObject
, args
);
703 catch( const InvocationTargetException
& )
705 throw IntrospectionException();
710 // Anything else is not supported
716 Sequence
< Reference
<XEventListener
> > EventAttacherImpl::attachListeners(
717 const Reference
<XInterface
>& xObject
,
718 const Sequence
< Reference
<XAllListener
> >& AllListeners
,
719 const Sequence
<com::sun::star::script::EventListener
>& aListeners
)
721 sal_Int32 nCount
= aListeners
.getLength();
722 if (nCount
!= AllListeners
.getLength())
723 // This is a prerequisite!
724 throw RuntimeException();
727 throw IllegalArgumentException();
729 Reference
< XInvocationAdapterFactory
> xInvocationAdapterFactory
= getInvocationAdapterService();
730 if( !xInvocationAdapterFactory
.is() )
731 throw ServiceNotRegisteredException();
733 Reference
< XIdlReflection
> xReflection
= getReflection();
734 if( !xReflection
.is() )
735 throw ServiceNotRegisteredException();
737 // Sign in, Call the fitting addListener method
738 // First Introspection, as the Methods can be analyzed in the same way
739 // For better perfomance 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 return Sequence
< Reference
<XEventListener
> >();
745 // Inspect Introspection
746 Any
aObjAny( &xObject
, ::getCppuType(static_cast<const Reference
<XInterface
>*>(0)) );
748 Reference
<XIntrospectionAccess
> xAccess
= xIntrospection
->inspect(aObjAny
);
750 return Sequence
< Reference
<XEventListener
> >();
752 Sequence
< Reference
<XEventListener
> > aRet(nCount
);
753 Reference
<XEventListener
>* pArray
= aRet
.getArray();
755 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
757 pArray
[i
] = attachListenerForTarget(
758 xAccess
, xInvocationAdapterFactory
, AllListeners
[ i
],
759 aObjAny
, aListeners
[i
].Helper
, aListeners
[i
].ListenerType
, aListeners
[i
].AddListenerParam
);
766 Reference
< XEventListener
> EventAttacherImpl::attachSingleEventListener
768 const Reference
< XInterface
>& xObject
,
769 const Reference
< XAllListener
>& AllListener
,
771 const OUString
& ListenerType
,
772 const OUString
& AddListenerParam
,
773 const OUString
& EventMethod
775 throw( IllegalArgumentException
, ServiceNotRegisteredException
, CannotCreateAdapterException
, IntrospectionException
, RuntimeException
)
777 // Subscribe FilterListener
778 Reference
< XAllListener
> aFilterListener
= (XAllListener
*)
779 new FilterAllListenerImpl( this, EventMethod
, AllListener
);
780 return attachListener( xObject
, aFilterListener
, Helper
, ListenerType
, AddListenerParam
);
784 void EventAttacherImpl::removeListener
786 const Reference
< XInterface
>& xObject
,
787 const OUString
& ListenerType
,
788 const OUString
& AddListenerParam
,
789 const Reference
< XEventListener
>& aToRemoveListener
791 throw( IllegalArgumentException
, IntrospectionException
, RuntimeException
)
793 if( !xObject
.is() || !aToRemoveListener
.is() )
794 throw IllegalArgumentException();
796 Reference
< XIdlReflection
> xReflection
= getReflection();
797 if( !xReflection
.is() )
798 throw IntrospectionException();
800 // Sign off, Call the fitting removeListener method
801 // First Introspection, as the Methods can be analyzed in the same way
802 // For better perfomance it is implemented here again or make the Impl-Method
803 // of the Introspection configurable for this purpose.
804 Reference
< XIntrospection
> xIntrospection
= getIntrospection();
805 if( !xIntrospection
.is() )
806 throw IntrospectionException();
808 //Inspect Introspection
809 Any
aObjAny( &xObject
, ::getCppuType( (const Reference
< XInterface
> *)0) );
810 Reference
< XIntrospectionAccess
> xAccess
= xIntrospection
->inspect( aObjAny
);
812 throw IntrospectionException();
814 // Create name of the removeListener-Method
815 OUString aRemoveListenerName
;
816 OUString
aListenerName( ListenerType
);
817 sal_Int32 nIndex
= aListenerName
.lastIndexOf( '.' );
818 // set index to the interface name without package name
824 if( aListenerName
[nIndex
] == 'X' )
825 // erase X from the interface name
826 aListenerName
= aListenerName
.copy( nIndex
+1 );
827 aRemoveListenerName
= OUString( "remove" ) + aListenerName
;
829 // Search methods for the correct removeListener method
830 Sequence
< Reference
< XIdlMethod
> > aMethodSeq
= xAccess
->getMethods( MethodConcept::LISTENER
);
831 sal_uInt32 i
, nLen
= aMethodSeq
.getLength();
832 const Reference
< XIdlMethod
>* pMethods
= aMethodSeq
.getConstArray();
833 for( i
= 0 ; i
< nLen
; i
++ )
836 const Reference
< XIdlMethod
>& rxMethod
= pMethods
[i
];
838 // Is it the right method?
839 if( aRemoveListenerName
== rxMethod
->getName() )
841 Sequence
< Reference
< XIdlClass
> > params
= rxMethod
->getParameterTypes();
842 sal_uInt32 nParamCount
= params
.getLength();
844 // Just the Listener as parameter?
845 if( nParamCount
== 1 )
847 Sequence
< Any
> args( 1 );
848 args
.getArray()[0] <<= aToRemoveListener
;
851 rxMethod
->invoke( aObjAny
, args
);
853 catch( const InvocationTargetException
& )
855 throw IntrospectionException();
858 // Else pass the other parameter
859 else if( nParamCount
== 2 )
861 Sequence
< Any
> args( 2 );
862 Any
* pAnys
= args
.getArray();
864 // Check the type of the 1st parameter
865 Reference
< XIdlClass
> xParamClass
= params
.getConstArray()[0];
866 if( xParamClass
->getTypeClass() == TypeClass_STRING
)
867 pAnys
[0] <<= AddListenerParam
;
869 // 2nd parameter == Listener? TODO: Test!
870 pAnys
[1] <<= aToRemoveListener
;
872 // TODO: Convert String -> ?
876 rxMethod
->invoke( aObjAny
, args
);
878 catch( const InvocationTargetException
& )
880 throw IntrospectionException();
888 Sequence
< Reference
<XEventListener
> > EventAttacherImpl::attachMultipleEventListeners(
889 const Reference
<XInterface
>& xObject
, const Sequence
<com::sun::star::script::EventListener
>& aListeners
)
890 throw( IllegalArgumentException
, ServiceNotRegisteredException
, CannotCreateAdapterException
, IntrospectionException
, RuntimeException
)
892 sal_Int32 nCount
= aListeners
.getLength();
893 Sequence
< Reference
<XAllListener
> > aFilterListeners(nCount
);
894 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
896 aFilterListeners
[i
] = (XAllListener
*)
897 new FilterAllListenerImpl(this, aListeners
[i
].EventMethod
, aListeners
[i
].AllListener
);
900 return attachListeners(xObject
, aFilterListeners
, aListeners
);
907 SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
evtatt_component_getFactory(
908 const sal_Char
* pImplName
, void * pServiceManager
, void * )
912 if (pServiceManager
&& rtl_str_compare( pImplName
, IMPLNAME
) == 0)
914 Reference
< XSingleServiceFactory
> xFactory( createOneInstanceFactory(
915 reinterpret_cast< XMultiServiceFactory
* >( pServiceManager
),
916 OUString( IMPLNAME
),
917 ::comp_EventAttacher::EventAttacherImpl_CreateInstance
,
918 ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) );
923 pRet
= xFactory
.get();
933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */