Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / eventattacher / source / eventattacher.cxx
blob758189f653071a641b123782161c576eb03a2503
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
51 using namespace cppu;
52 using namespace osl;
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 >
66 public:
67 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
68 const Reference< XAllListener >& AllListener, const Any& Helper );
70 // XInvocation
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;
78 private:
79 Reference< XAllListener > m_xAllListener;
80 Reference< XIdlClass > m_xListenerType;
81 Any m_Helper;
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,
91 const Any& Helper
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 );
104 return xAdapter;
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 )
113 , m_Helper( Helper )
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 >& )
127 Any aRet;
129 // Check if to firing or approveFiring has to be called
130 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
131 bool bApproveFiring = false;
132 if( !xMethod.is() )
133 return aRet;
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;
141 else
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;
153 break;
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;
165 if( bApproveFiring )
166 aRet = m_xAllListener->approveFiring( aAllEvent );
167 else
168 m_xAllListener->firing( aAllEvent );
169 return aRet;
173 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& , const Any& )
178 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& )
180 return Any();
184 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
186 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
187 return xMethod.is();
191 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
193 Reference< XIdlField > xField = m_xListenerType->getField( Name );
194 return xField.is();
198 // class EventAttacherImpl
199 // represents an implementation of the EventAttacher service
201 class EventAttacherImpl : public WeakImplHelper < XEventAttacher2, XInitialization, XServiceInfo >
203 public:
204 explicit EventAttacherImpl( const Reference< XComponentContext >& );
206 // XServiceInfo
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 > getSupportedServiceNames_Static( );
212 // XInitialization
213 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
215 // methods of 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;
227 // XEventAttacher2
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;
237 private:
238 static Reference<XEventListener> attachListenerForTarget(
239 const Reference<XIntrospectionAccess>& xAccess,
240 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
241 const Reference<XAllListener>& xAllListener,
242 const Any& aObject,
243 const Any& aHelper,
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 );
252 private:
253 Mutex m_aMutex;
254 Reference< XComponentContext > m_xContext;
256 // Save Services
257 Reference< XIntrospection > m_xIntrospection;
258 Reference< XIdlReflection > m_xReflection;
259 Reference< XTypeConverter > m_xConverter;
260 Reference< XInvocationAdapterFactory2 > m_xInvocationAdapterFactory;
262 // needed services
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 > EventAttacherImpl_CreateInstance( const Reference< XMultiServiceFactory >& rSMgr )
280 XEventAttacher *pEventAttacher = static_cast<XEventAttacher*>(new EventAttacherImpl( comphelper::getComponentContext(rSMgr) ));
282 Reference< XInterface > xRet(pEventAttacher, UNO_QUERY);
284 return xRet;
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> 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;
321 pArray[i] >>= xALAS;
322 if( xALAS.is() )
324 Guard< Mutex > aGuard( m_aMutex );
325 m_xInvocationAdapterFactory = xALAS;
327 // Introspection service ?
328 Reference< XIntrospection > xI;
329 pArray[i] >>= xI;
330 if( xI.is() )
332 Guard< Mutex > aGuard( m_aMutex );
333 m_xIntrospection = xI;
335 // Reflection service ?
336 Reference< XIdlReflection > xIdlR;
337 pArray[i] >>= xIdlR;
338 if( xIdlR.is() )
340 Guard< Mutex > aGuard( m_aMutex );
341 m_xReflection = xIdlR;
343 // Converter Service ?
344 Reference< XTypeConverter > xC;
345 pArray[i] >>= xC;
346 if( xC.is() )
348 Guard< Mutex > aGuard( m_aMutex );
349 m_xConverter = xC;
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);
403 return m_xConverter;
407 // Implementation of an EventAttacher-related AllListeners, which brings
408 // a few Events to a general AllListener
409 class FilterAllListenerImpl : public WeakImplHelper< XAllListener >
411 public:
412 FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
413 const Reference< XAllListener >& AllListener_ );
415 // XAllListener
416 virtual void SAL_CALL firing(const AllEventObject& Event) override;
417 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) override;
419 // XEventListener
420 virtual void SAL_CALL disposing(const EventObject& Source) override;
422 private:
423 // convert
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_ )
436 : m_pEA( pEA_ )
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 >();
461 break;
463 case TypeClass_BOOLEAN:
464 rRet <<= true;
465 break;
467 case TypeClass_STRING:
468 rRet <<= OUString();
469 break;
471 case TypeClass_FLOAT: rRet <<= float(0); break;
472 case TypeClass_DOUBLE: rRet <<= 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;
478 default:
479 break;
482 else if( !rRet.getValueType().equals( rRetType ) )
484 Reference< XTypeConverter > xConverter = m_pEA->getConverter();
485 if( !xConverter.is() )
486 throw CannotConvertException(); // TODO TypeConversionException
487 rRet = xConverter->convertTo( rRet, rRetType );
492 Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event )
494 Any aRet;
496 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
497 aRet = m_AllListener->approveFiring( Event );
498 else
500 // Convert to the standard event return
503 Reference< XIdlClass > xListenerType = m_pEA->getReflection()->
504 forName( Event.ListenerType.getTypeName() );
505 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
506 if( xMeth.is() )
508 Reference< XIdlClass > xRetType = xMeth->getReturnType();
509 Type aRetType( xRetType->getTypeClass(), xRetType->getName() );
510 convertToEventReturn( aRet, aRetType );
513 catch( const CannotConvertException& e )
515 throw InvocationTargetException( OUString(), Reference< XInterface >(), Any(&e, cppu::UnoType<CannotConvertException>::get()) );
518 return aRet;
522 void FilterAllListenerImpl::disposing(const EventObject& )
524 // TODO: ???
528 Reference< XEventListener > EventAttacherImpl::attachListener
530 const Reference< XInterface >& xObject,
531 const Reference< XAllListener >& AllListener,
532 const Any& Helper,
533 const OUString& ListenerType,
534 const OUString& AddListenerParam
537 if( !xObject.is() || !AllListener.is() )
538 throw IllegalArgumentException();
540 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
541 if( !xInvocationAdapterFactory.is() )
542 throw ServiceNotRegisteredException();
544 Reference< XIdlReflection > xReflection = getReflection();
545 if( !xReflection.is() )
546 throw ServiceNotRegisteredException();
548 // Sign in, Call the fitting addListener method
549 // First Introspection, as the Methods can be analyzed in the same way
550 // For better performance it is implemented here again or make the Impl-Method
551 // of the Introspection configurable for this purpose.
552 Reference< XIntrospection > xIntrospection = getIntrospection();
553 if( !xIntrospection.is() )
554 return Reference<XEventListener>();
556 // Inspect Introspection
557 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
559 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
560 if( !xAccess.is() )
561 return Reference<XEventListener>();
563 return attachListenerForTarget(
564 xAccess, xInvocationAdapterFactory, AllListener, aObjAny, Helper,
565 ListenerType, AddListenerParam);
568 Reference<XEventListener> EventAttacherImpl::attachListenerForTarget(
569 const Reference<XIntrospectionAccess>& xAccess,
570 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
571 const Reference<XAllListener>& xAllListener,
572 const Any& aObject,
573 const Any& aHelper,
574 const OUString& aListenerType,
575 const OUString& aAddListenerParam)
577 Reference< XEventListener > xRet = nullptr;
579 // Construct the name of the addListener-Method.
580 sal_Int32 nIndex = aListenerType.lastIndexOf('.');
581 // set index to the interface name without package name
582 if( nIndex == -1 )
583 // not found
584 nIndex = 0;
585 else
586 nIndex++;
588 OUString aListenerName = (!aListenerType.isEmpty() && aListenerType[nIndex] == 'X') ? aListenerType.copy(nIndex+1) : aListenerType;
589 OUString aAddListenerName = "add" + aListenerName;
591 // Send Methods to the correct addListener-Method
592 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
593 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
594 for (sal_Int32 i = 0, n = aMethodSeq.getLength(); i < n ; ++i)
596 const Reference< XIdlMethod >& rxMethod = pMethods[i];
598 // Is it the correct method?
599 OUString aMethName = rxMethod->getName();
601 if (aAddListenerName != aMethName)
602 continue;
604 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
605 sal_uInt32 nParamCount = params.getLength();
607 Reference< XIdlClass > xListenerType;
608 if( nParamCount == 1 )
609 xListenerType = params.getConstArray()[0];
610 else if( nParamCount == 2 )
611 xListenerType = params.getConstArray()[1];
613 // Request Adapter for the actual Listener type
614 Reference< XInterface > xAdapter = createAllListenerAdapter(
615 xInvocationAdapterFactory, xListenerType, xAllListener, aHelper );
617 if( !xAdapter.is() )
618 throw CannotCreateAdapterException();
619 xRet.set( xAdapter, UNO_QUERY );
621 // Just the Listener as parameter?
622 if( nParamCount == 1 )
624 Sequence< Any > args( 1 );
625 args.getArray()[0] <<= xAdapter;
628 rxMethod->invoke( aObject, args );
630 catch( const InvocationTargetException& )
632 throw IntrospectionException();
635 // Else, pass the other parameter now
636 else if( nParamCount == 2 )
638 Sequence< Any > args( 2 );
639 Any* pAnys = args.getArray();
641 // Check the type of the 1st parameter
642 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
643 if( xParamClass->getTypeClass() == TypeClass_STRING )
645 pAnys[0] <<= aAddListenerParam;
648 // 2nd Parameter == Listener? TODO: Test!
649 pAnys[1] <<= xAdapter;
651 // TODO: Convert String -> ?
652 // else
655 rxMethod->invoke( aObject, args );
657 catch( const InvocationTargetException& )
659 throw IntrospectionException();
662 break;
663 // else...
664 // Anything else is not supported
667 return xRet;
670 Sequence< Reference<XEventListener> > EventAttacherImpl::attachListeners(
671 const Reference<XInterface>& xObject,
672 const Sequence< Reference<XAllListener> >& AllListeners,
673 const Sequence<css::script::EventListener>& aListeners )
675 sal_Int32 nCount = aListeners.getLength();
676 if (nCount != AllListeners.getLength())
677 // This is a prerequisite!
678 throw RuntimeException();
680 if (!xObject.is())
681 throw IllegalArgumentException();
683 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
684 if( !xInvocationAdapterFactory.is() )
685 throw ServiceNotRegisteredException();
687 Reference< XIdlReflection > xReflection = getReflection();
688 if( !xReflection.is() )
689 throw ServiceNotRegisteredException();
691 // Sign in, Call the fitting addListener method
692 // First Introspection, as the Methods can be analyzed in the same way
693 // For better performance it is implemented here again or make the Impl-Method
694 // of the Introspection configurable for this purpose.
695 Reference< XIntrospection > xIntrospection = getIntrospection();
696 if( !xIntrospection.is() )
697 return Sequence< Reference<XEventListener> >();
699 // Inspect Introspection
700 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get() );
702 Reference<XIntrospectionAccess> xAccess = xIntrospection->inspect(aObjAny);
703 if (!xAccess.is())
704 return Sequence< Reference<XEventListener> >();
706 Sequence< Reference<XEventListener> > aRet(nCount);
707 Reference<XEventListener>* pArray = aRet.getArray();
709 for (sal_Int32 i = 0; i < nCount; ++i)
711 pArray[i] = attachListenerForTarget(
712 xAccess, xInvocationAdapterFactory, AllListeners[ i ],
713 aObjAny, aListeners[i].Helper, aListeners[i].ListenerType, aListeners[i].AddListenerParam);
716 return aRet;
719 // XEventAttacher
720 Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
722 const Reference< XInterface >& xObject,
723 const Reference< XAllListener >& AllListener,
724 const Any& Helper,
725 const OUString& ListenerType,
726 const OUString& AddListenerParam,
727 const OUString& EventMethod
730 // Subscribe FilterListener
731 Reference< XAllListener > aFilterListener = static_cast<XAllListener*>(
732 new FilterAllListenerImpl( this, EventMethod, AllListener ));
733 return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam);
736 // XEventAttacher
737 void EventAttacherImpl::removeListener
739 const Reference< XInterface >& xObject,
740 const OUString& ListenerType,
741 const OUString& AddListenerParam,
742 const Reference< XEventListener >& aToRemoveListener
745 if( !xObject.is() || !aToRemoveListener.is() )
746 throw IllegalArgumentException();
748 Reference< XIdlReflection > xReflection = getReflection();
749 if( !xReflection.is() )
750 throw IntrospectionException();
752 // Sign off, Call the fitting removeListener method
753 // First Introspection, as the Methods can be analyzed in the same way
754 // For better performance it is implemented here again or make the Impl-Method
755 // of the Introspection configurable for this purpose.
756 Reference< XIntrospection > xIntrospection = getIntrospection();
757 if( !xIntrospection.is() )
758 throw IntrospectionException();
760 //Inspect Introspection
761 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
762 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
763 if( !xAccess.is() )
764 throw IntrospectionException();
766 // Create name of the removeListener-Method
767 OUString aRemoveListenerName;
768 OUString aListenerName( ListenerType );
769 sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
770 // set index to the interface name without package name
771 if( nIndex == -1 )
772 // not found
773 nIndex = 0;
774 else
775 nIndex++;
776 if( aListenerName[nIndex] == 'X' )
777 // erase X from the interface name
778 aListenerName = aListenerName.copy( nIndex +1 );
779 aRemoveListenerName = "remove" + aListenerName;
781 // Search methods for the correct removeListener method
782 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
783 sal_uInt32 i, nLen = aMethodSeq.getLength();
784 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
785 for( i = 0 ; i < nLen ; i++ )
787 // Call Method
788 const Reference< XIdlMethod >& rxMethod = pMethods[i];
790 // Is it the right method?
791 if( aRemoveListenerName == rxMethod->getName() )
793 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
794 sal_uInt32 nParamCount = params.getLength();
796 // Just the Listener as parameter?
797 if( nParamCount == 1 )
799 Sequence< Any > args( 1 );
800 args.getArray()[0] <<= aToRemoveListener;
803 rxMethod->invoke( aObjAny, args );
805 catch( const InvocationTargetException& )
807 throw IntrospectionException();
810 // Else pass the other parameter
811 else if( nParamCount == 2 )
813 Sequence< Any > args( 2 );
814 Any* pAnys = args.getArray();
816 // Check the type of the 1st parameter
817 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
818 if( xParamClass->getTypeClass() == TypeClass_STRING )
819 pAnys[0] <<= AddListenerParam;
821 // 2nd parameter == Listener? TODO: Test!
822 pAnys[1] <<= aToRemoveListener;
824 // TODO: Convert String -> ?
825 // else
828 rxMethod->invoke( aObjAny, args );
830 catch( const InvocationTargetException& )
832 throw IntrospectionException();
835 break;
840 Sequence< Reference<XEventListener> > EventAttacherImpl::attachMultipleEventListeners(
841 const Reference<XInterface>& xObject, const Sequence<css::script::EventListener>& aListeners )
843 sal_Int32 nCount = aListeners.getLength();
844 Sequence< Reference<XAllListener> > aFilterListeners(nCount);
845 for (sal_Int32 i = 0; i < nCount; ++i)
847 aFilterListeners[i] = static_cast<XAllListener*>(
848 new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener));
851 return attachListeners(xObject, aFilterListeners, aListeners);
856 extern "C"
858 SAL_DLLPUBLIC_EXPORT void * evtatt_component_getFactory(
859 const sal_Char * pImplName, void * pServiceManager, void * )
861 void * pRet = nullptr;
863 if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
865 Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory(
866 static_cast< XMultiServiceFactory * >( pServiceManager ),
867 IMPLNAME,
868 ::comp_EventAttacher::EventAttacherImpl_CreateInstance,
869 ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) );
871 if (xFactory.is())
873 xFactory->acquire();
874 pRet = xFactory.get();
878 return pRet;
883 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */