bump product version to 6.3.0.0.beta1
[LibreOffice.git] / eventattacher / source / eventattacher.cxx
blobe73b92b3d6ba7414ff309c5b5dbc24c77aa4f2de
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/XSingleServiceFactory.hpp>
23 #include <com/sun/star/beans/IntrospectionException.hpp>
24 #include <com/sun/star/beans/theIntrospection.hpp>
25 #include <com/sun/star/beans/MethodConcept.hpp>
26 #include <com/sun/star/script/CannotConvertException.hpp>
27 #include <com/sun/star/script/CannotCreateAdapterException.hpp>
28 #include <com/sun/star/script/XEventAttacher2.hpp>
29 #include <com/sun/star/script/Converter.hpp>
30 #include <com/sun/star/script/XAllListener.hpp>
31 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
32 #include <com/sun/star/reflection/theCoreReflection.hpp>
33 #include <com/sun/star/reflection/XIdlReflection.hpp>
35 // InvocationToAllListenerMapper
36 #include <com/sun/star/script/XInvocation.hpp>
37 #include <comphelper/processfactory.hxx>
38 #include <cppuhelper/exc_hlp.hxx>
39 #include <cppuhelper/weak.hxx>
40 #include <cppuhelper/factory.hxx>
41 #include <cppuhelper/implbase.hxx>
42 #include <cppuhelper/supportsservice.hxx>
44 namespace com::sun::star::lang { class XMultiServiceFactory; }
46 using namespace com::sun::star::uno;
47 using namespace com::sun::star::registry;
48 using namespace com::sun::star::lang;
49 using namespace com::sun::star::beans;
50 using namespace com::sun::star::script;
51 using namespace com::sun::star::reflection;
52 using namespace cppu;
53 using namespace osl;
56 #define SERVICENAME "com.sun.star.script.EventAttacher"
57 #define IMPLNAME "com.sun.star.comp.EventAttacher"
59 namespace comp_EventAttacher {
62 // class InvocationToAllListenerMapper
63 // helper class to map XInvocation to XAllListener
65 class InvocationToAllListenerMapper : public WeakImplHelper< XInvocation >
67 public:
68 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
69 const Reference< XAllListener >& AllListener, const Any& Helper );
71 // XInvocation
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;
79 private:
80 Reference< XAllListener > m_xAllListener;
81 Reference< XIdlClass > m_xListenerType;
82 Any m_Helper;
86 // Function to replace AllListenerAdapterService::createAllListerAdapter
87 static Reference< XInterface > createAllListenerAdapter
89 const Reference< XInvocationAdapterFactory2 >& xInvocationAdapterFactory,
90 const Reference< XIdlClass >& xListenerType,
91 const Reference< XAllListener >& xListener,
92 const Any& Helper
95 Reference< XInterface > xAdapter;
96 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
98 Reference< XInvocation > xInvocationToAllListenerMapper =
99 new InvocationToAllListenerMapper(xListenerType, xListener, Helper);
100 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName());
101 Sequence<Type> arg2(1);
102 arg2[0] = aListenerType;
103 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, arg2 );
105 return xAdapter;
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 )
114 , m_Helper( 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 >& )
128 Any aRet;
130 // Check if to firing or approveFiring has to be called
131 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
132 bool bApproveFiring = false;
133 if( !xMethod.is() )
134 return aRet;
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;
142 else
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;
154 break;
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;
166 if( bApproveFiring )
167 aRet = m_xAllListener->approveFiring( aAllEvent );
168 else
169 m_xAllListener->firing( aAllEvent );
170 return aRet;
174 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& , const Any& )
179 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& )
181 return Any();
185 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
187 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
188 return xMethod.is();
192 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
194 Reference< XIdlField > xField = m_xListenerType->getField( Name );
195 return xField.is();
199 // class EventAttacherImpl
200 // represents an implementation of the EventAttacher service
202 class EventAttacherImpl : public WeakImplHelper < XEventAttacher2, XInitialization, XServiceInfo >
204 public:
205 explicit EventAttacherImpl( const Reference< XComponentContext >& );
207 // XServiceInfo
208 virtual OUString SAL_CALL getImplementationName( ) override;
209 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
210 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
211 static Sequence< OUString > getSupportedServiceNames_Static( );
213 // XInitialization
214 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
216 // methods of XEventAttacher
217 virtual Reference< XEventListener > SAL_CALL attachListener(const Reference< XInterface >& xObject,
218 const Reference< XAllListener >& AllListener, const Any& Helper,
219 const OUString& ListenerType, const OUString& AddListenerParam) override;
220 virtual Reference< XEventListener > SAL_CALL attachSingleEventListener(const Reference< XInterface >& xObject,
221 const Reference< XAllListener >& AllListener, const Any& Helper,
222 const OUString& ListenerType, const OUString& AddListenerParam,
223 const OUString& EventMethod) override;
224 virtual void SAL_CALL removeListener(const Reference< XInterface >& xObject,
225 const OUString& ListenerType, const OUString& AddListenerParam,
226 const Reference< XEventListener >& aToRemoveListener) override;
228 // XEventAttacher2
229 virtual Sequence< Reference<XEventListener> > SAL_CALL attachMultipleEventListeners(
230 const Reference<XInterface>& xObject, const Sequence<css::script::EventListener>& aListeners ) override;
232 // used by FilterAllListener_Impl
233 /// @throws Exception
234 Reference< XTypeConverter > getConverter();
236 friend class FilterAllListenerImpl;
238 private:
239 static Reference<XEventListener> attachListenerForTarget(
240 const Reference<XIntrospectionAccess>& xAccess,
241 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
242 const Reference<XAllListener>& xAllListener,
243 const Any& aObject,
244 const Any& aHelper,
245 const OUString& aListenerType,
246 const OUString& aAddListenerParam );
248 Sequence< Reference<XEventListener> > attachListeners(
249 const Reference<XInterface>& xObject,
250 const Sequence< Reference<XAllListener> >& AllListeners,
251 const Sequence<css::script::EventListener>& aListeners );
253 private:
254 Mutex m_aMutex;
255 Reference< XComponentContext > m_xContext;
257 // Save Services
258 Reference< XIntrospection > m_xIntrospection;
259 Reference< XIdlReflection > m_xReflection;
260 Reference< XTypeConverter > m_xConverter;
261 Reference< XInvocationAdapterFactory2 > m_xInvocationAdapterFactory;
263 // needed services
264 /// @throws Exception
265 Reference< XIntrospection > getIntrospection();
266 /// @throws Exception
267 Reference< XIdlReflection > getReflection();
268 /// @throws Exception
269 Reference< XInvocationAdapterFactory2 > getInvocationAdapterService();
273 EventAttacherImpl::EventAttacherImpl( const Reference< XComponentContext >& rxContext )
274 : m_xContext( rxContext )
278 /// @throws Exception
279 static Reference< XInterface > EventAttacherImpl_CreateInstance( const Reference< XMultiServiceFactory >& rSMgr )
281 XEventAttacher* pEventAttacher = new EventAttacherImpl(comphelper::getComponentContext(rSMgr));
283 Reference< XInterface > xRet(pEventAttacher, UNO_QUERY);
285 return xRet;
289 OUString SAL_CALL EventAttacherImpl::getImplementationName( )
291 return OUString( IMPLNAME );
294 sal_Bool SAL_CALL EventAttacherImpl::supportsService( const OUString& ServiceName )
296 return cppu::supportsService(this, ServiceName);
299 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames( )
301 return getSupportedServiceNames_Static();
305 Sequence<OUString> EventAttacherImpl::getSupportedServiceNames_Static( )
307 OUString aStr( SERVICENAME );
308 return Sequence< OUString >( &aStr, 1 );
311 void SAL_CALL EventAttacherImpl::initialize(const Sequence< Any >& Arguments)
313 // get services from the argument list
314 const Any * pArray = Arguments.getConstArray();
315 for( sal_Int32 i = 0; i < Arguments.getLength(); i++ )
317 if( pArray[i].getValueType().getTypeClass() != TypeClass_INTERFACE )
318 throw IllegalArgumentException();
320 // InvocationAdapter service ?
321 Reference< XInvocationAdapterFactory2 > xALAS;
322 pArray[i] >>= xALAS;
323 if( xALAS.is() )
325 Guard< Mutex > aGuard( m_aMutex );
326 m_xInvocationAdapterFactory = xALAS;
328 // Introspection service ?
329 Reference< XIntrospection > xI;
330 pArray[i] >>= xI;
331 if( xI.is() )
333 Guard< Mutex > aGuard( m_aMutex );
334 m_xIntrospection = xI;
336 // Reflection service ?
337 Reference< XIdlReflection > xIdlR;
338 pArray[i] >>= xIdlR;
339 if( xIdlR.is() )
341 Guard< Mutex > aGuard( m_aMutex );
342 m_xReflection = xIdlR;
344 // Converter Service ?
345 Reference< XTypeConverter > xC;
346 pArray[i] >>= xC;
347 if( xC.is() )
349 Guard< Mutex > aGuard( m_aMutex );
350 m_xConverter = xC;
353 // no right interface
354 if( !xALAS.is() && !xI.is() && !xIdlR.is() && !xC.is() )
355 throw IllegalArgumentException();
360 //*** Private helper methods ***
361 Reference< XIntrospection > EventAttacherImpl::getIntrospection()
363 Guard< Mutex > aGuard( m_aMutex );
364 if( !m_xIntrospection.is() )
366 m_xIntrospection = theIntrospection::get( m_xContext );
368 return m_xIntrospection;
372 //*** Private helper methods ***
373 Reference< XIdlReflection > EventAttacherImpl::getReflection()
375 Guard< Mutex > aGuard( m_aMutex );
376 if( !m_xReflection.is() )
378 m_xReflection = theCoreReflection::get(m_xContext);
380 return m_xReflection;
384 //*** Private helper methods ***
385 Reference< XInvocationAdapterFactory2 > EventAttacherImpl::getInvocationAdapterService()
387 Guard< Mutex > aGuard( m_aMutex );
388 if( !m_xInvocationAdapterFactory.is() )
390 m_xInvocationAdapterFactory = InvocationAdapterFactory::create(m_xContext);
392 return m_xInvocationAdapterFactory;
396 //*** Private helper methods ***
397 Reference< XTypeConverter > EventAttacherImpl::getConverter()
399 Guard< Mutex > aGuard( m_aMutex );
400 if( !m_xConverter.is() )
402 m_xConverter = Converter::create(m_xContext);
404 return m_xConverter;
408 // Implementation of an EventAttacher-related AllListeners, which brings
409 // a few Events to a general AllListener
410 class FilterAllListenerImpl : public WeakImplHelper< XAllListener >
412 public:
413 FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
414 const Reference< XAllListener >& AllListener_ );
416 // XAllListener
417 virtual void SAL_CALL firing(const AllEventObject& Event) override;
418 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) override;
420 // XEventListener
421 virtual void SAL_CALL disposing(const EventObject& Source) override;
423 private:
424 // convert
425 /// @throws CannotConvertException
426 /// @throws RuntimeException
427 void convertToEventReturn( Any & rRet, const Type& rRetType );
429 EventAttacherImpl * m_pEA;
430 OUString m_EventMethod;
431 Reference< XAllListener > m_AllListener;
435 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
436 const Reference< XAllListener >& AllListener_ )
437 : m_pEA( pEA_ )
438 , m_EventMethod( EventMethod_ )
439 , m_AllListener( AllListener_ )
444 void SAL_CALL FilterAllListenerImpl::firing(const AllEventObject& Event)
446 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
447 m_AllListener->firing( Event );
450 // Convert to the standard event return
451 void FilterAllListenerImpl::convertToEventReturn( Any & rRet, const Type & rRetType )
453 // no return value? Set to the specified values
454 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
456 switch( rRetType.getTypeClass() )
458 case TypeClass_INTERFACE:
460 rRet <<= Reference< XInterface >();
462 break;
464 case TypeClass_BOOLEAN:
465 rRet <<= true;
466 break;
468 case TypeClass_STRING:
469 rRet <<= OUString();
470 break;
472 case TypeClass_FLOAT: rRet <<= float(0); break;
473 case TypeClass_DOUBLE: rRet <<= 0.0; break;
474 case TypeClass_BYTE: rRet <<= sal_uInt8( 0 ); break;
475 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
476 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
477 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
478 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
479 default:
480 break;
483 else if( !rRet.getValueType().equals( rRetType ) )
485 Reference< XTypeConverter > xConverter = m_pEA->getConverter();
486 if( !xConverter.is() )
487 throw CannotConvertException(); // TODO TypeConversionException
488 rRet = xConverter->convertTo( rRet, rRetType );
493 Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event )
495 Any aRet;
497 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
498 aRet = m_AllListener->approveFiring( Event );
499 else
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 );
507 if( xMeth.is() )
509 Reference< XIdlClass > xRetType = xMeth->getReturnType();
510 Type aRetType( xRetType->getTypeClass(), xRetType->getName() );
511 convertToEventReturn( aRet, aRetType );
514 catch( const CannotConvertException& )
516 css::uno::Any anyEx = cppu::getCaughtException();
517 throw InvocationTargetException( OUString(), Reference< XInterface >(), anyEx );
520 return aRet;
524 void FilterAllListenerImpl::disposing(const EventObject& )
526 // TODO: ???
530 Reference< XEventListener > EventAttacherImpl::attachListener
532 const Reference< XInterface >& xObject,
533 const Reference< XAllListener >& AllListener,
534 const Any& Helper,
535 const OUString& ListenerType,
536 const OUString& AddListenerParam
539 if( !xObject.is() || !AllListener.is() )
540 throw IllegalArgumentException();
542 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
543 if( !xInvocationAdapterFactory.is() )
544 throw ServiceNotRegisteredException();
546 Reference< XIdlReflection > xReflection = getReflection();
547 if( !xReflection.is() )
548 throw ServiceNotRegisteredException();
550 // Sign in, Call the fitting addListener method
551 // First Introspection, as the Methods can be analyzed in the same way
552 // For better performance it is implemented here again or make the Impl-Method
553 // of the Introspection configurable for this purpose.
554 Reference< XIntrospection > xIntrospection = getIntrospection();
555 if( !xIntrospection.is() )
556 return Reference<XEventListener>();
558 // Inspect Introspection
559 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
561 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
562 if( !xAccess.is() )
563 return Reference<XEventListener>();
565 return attachListenerForTarget(
566 xAccess, xInvocationAdapterFactory, AllListener, aObjAny, Helper,
567 ListenerType, AddListenerParam);
570 Reference<XEventListener> EventAttacherImpl::attachListenerForTarget(
571 const Reference<XIntrospectionAccess>& xAccess,
572 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
573 const Reference<XAllListener>& xAllListener,
574 const Any& aObject,
575 const Any& aHelper,
576 const OUString& aListenerType,
577 const OUString& aAddListenerParam)
579 Reference< XEventListener > xRet;
581 // Construct the name of the addListener-Method.
582 sal_Int32 nIndex = aListenerType.lastIndexOf('.');
583 // set index to the interface name without package name
584 if( nIndex == -1 )
585 // not found
586 nIndex = 0;
587 else
588 nIndex++;
590 OUString aListenerName = (!aListenerType.isEmpty() && aListenerType[nIndex] == 'X') ? aListenerType.copy(nIndex+1) : aListenerType;
591 OUString aAddListenerName = "add" + aListenerName;
593 // Send Methods to the correct addListener-Method
594 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
595 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
596 for (sal_Int32 i = 0, n = aMethodSeq.getLength(); i < n ; ++i)
598 const Reference< XIdlMethod >& rxMethod = pMethods[i];
600 // Is it the correct method?
601 OUString aMethName = rxMethod->getName();
603 if (aAddListenerName != aMethName)
604 continue;
606 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
607 sal_uInt32 nParamCount = params.getLength();
609 Reference< XIdlClass > xListenerType;
610 if( nParamCount == 1 )
611 xListenerType = params.getConstArray()[0];
612 else if( nParamCount == 2 )
613 xListenerType = params.getConstArray()[1];
615 // Request Adapter for the actual Listener type
616 Reference< XInterface > xAdapter = createAllListenerAdapter(
617 xInvocationAdapterFactory, xListenerType, xAllListener, aHelper );
619 if( !xAdapter.is() )
620 throw CannotCreateAdapterException();
621 xRet.set( xAdapter, UNO_QUERY );
623 // Just the Listener as parameter?
624 if( nParamCount == 1 )
626 Sequence< Any > args( 1 );
627 args.getArray()[0] <<= xAdapter;
630 rxMethod->invoke( aObject, args );
632 catch( const InvocationTargetException& )
634 throw IntrospectionException();
637 // Else, pass the other parameter now
638 else if( nParamCount == 2 )
640 Sequence< Any > args( 2 );
641 Any* pAnys = args.getArray();
643 // Check the type of the 1st parameter
644 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
645 if( xParamClass->getTypeClass() == TypeClass_STRING )
647 pAnys[0] <<= aAddListenerParam;
650 // 2nd Parameter == Listener? TODO: Test!
651 pAnys[1] <<= xAdapter;
653 // TODO: Convert String -> ?
654 // else
657 rxMethod->invoke( aObject, args );
659 catch( const InvocationTargetException& )
661 throw IntrospectionException();
664 break;
665 // else...
666 // Anything else is not supported
669 return xRet;
672 Sequence< Reference<XEventListener> > EventAttacherImpl::attachListeners(
673 const Reference<XInterface>& xObject,
674 const Sequence< Reference<XAllListener> >& AllListeners,
675 const Sequence<css::script::EventListener>& aListeners )
677 sal_Int32 nCount = aListeners.getLength();
678 if (nCount != AllListeners.getLength())
679 // This is a prerequisite!
680 throw RuntimeException();
682 if (!xObject.is())
683 throw IllegalArgumentException();
685 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
686 if( !xInvocationAdapterFactory.is() )
687 throw ServiceNotRegisteredException();
689 Reference< XIdlReflection > xReflection = getReflection();
690 if( !xReflection.is() )
691 throw ServiceNotRegisteredException();
693 // Sign in, Call the fitting addListener method
694 // First Introspection, as the Methods can be analyzed in the same way
695 // For better performance it is implemented here again or make the Impl-Method
696 // of the Introspection configurable for this purpose.
697 Reference< XIntrospection > xIntrospection = getIntrospection();
698 if( !xIntrospection.is() )
699 return Sequence< Reference<XEventListener> >();
701 // Inspect Introspection
702 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get() );
704 Reference<XIntrospectionAccess> xAccess = xIntrospection->inspect(aObjAny);
705 if (!xAccess.is())
706 return Sequence< Reference<XEventListener> >();
708 Sequence< Reference<XEventListener> > aRet(nCount);
709 Reference<XEventListener>* pArray = aRet.getArray();
711 for (sal_Int32 i = 0; i < nCount; ++i)
713 pArray[i] = attachListenerForTarget(
714 xAccess, xInvocationAdapterFactory, AllListeners[ i ],
715 aObjAny, aListeners[i].Helper, aListeners[i].ListenerType, aListeners[i].AddListenerParam);
718 return aRet;
721 // XEventAttacher
722 Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
724 const Reference< XInterface >& xObject,
725 const Reference< XAllListener >& AllListener,
726 const Any& Helper,
727 const OUString& ListenerType,
728 const OUString& AddListenerParam,
729 const OUString& EventMethod
732 // Subscribe FilterListener
733 Reference<XAllListener> aFilterListener
734 = new FilterAllListenerImpl(this, EventMethod, AllListener);
735 return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam);
738 // XEventAttacher
739 void EventAttacherImpl::removeListener
741 const Reference< XInterface >& xObject,
742 const OUString& ListenerType,
743 const OUString& AddListenerParam,
744 const Reference< XEventListener >& aToRemoveListener
747 if( !xObject.is() || !aToRemoveListener.is() )
748 throw IllegalArgumentException();
750 Reference< XIdlReflection > xReflection = getReflection();
751 if( !xReflection.is() )
752 throw IntrospectionException();
754 // Sign off, Call the fitting removeListener method
755 // First Introspection, as the Methods can be analyzed in the same way
756 // For better performance it is implemented here again or make the Impl-Method
757 // of the Introspection configurable for this purpose.
758 Reference< XIntrospection > xIntrospection = getIntrospection();
759 if( !xIntrospection.is() )
760 throw IntrospectionException();
762 //Inspect Introspection
763 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
764 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
765 if( !xAccess.is() )
766 throw IntrospectionException();
768 // Create name of the removeListener-Method
769 OUString aRemoveListenerName;
770 OUString aListenerName( ListenerType );
771 sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
772 // set index to the interface name without package name
773 if( nIndex == -1 )
774 // not found
775 nIndex = 0;
776 else
777 nIndex++;
778 if( aListenerName[nIndex] == 'X' )
779 // erase X from the interface name
780 aListenerName = aListenerName.copy( nIndex +1 );
781 aRemoveListenerName = "remove" + aListenerName;
783 // Search methods for the correct removeListener method
784 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
785 sal_uInt32 i, nLen = aMethodSeq.getLength();
786 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
787 for( i = 0 ; i < nLen ; i++ )
789 // Call Method
790 const Reference< XIdlMethod >& rxMethod = pMethods[i];
792 // Is it the right method?
793 if( aRemoveListenerName == rxMethod->getName() )
795 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
796 sal_uInt32 nParamCount = params.getLength();
798 // Just the Listener as parameter?
799 if( nParamCount == 1 )
801 Sequence< Any > args( 1 );
802 args.getArray()[0] <<= aToRemoveListener;
805 rxMethod->invoke( aObjAny, args );
807 catch( const InvocationTargetException& )
809 throw IntrospectionException();
812 // Else pass the other parameter
813 else if( nParamCount == 2 )
815 Sequence< Any > args( 2 );
816 Any* pAnys = args.getArray();
818 // Check the type of the 1st parameter
819 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
820 if( xParamClass->getTypeClass() == TypeClass_STRING )
821 pAnys[0] <<= AddListenerParam;
823 // 2nd parameter == Listener? TODO: Test!
824 pAnys[1] <<= aToRemoveListener;
826 // TODO: Convert String -> ?
827 // else
830 rxMethod->invoke( aObjAny, args );
832 catch( const InvocationTargetException& )
834 throw IntrospectionException();
837 break;
842 Sequence< Reference<XEventListener> > EventAttacherImpl::attachMultipleEventListeners(
843 const Reference<XInterface>& xObject, const Sequence<css::script::EventListener>& aListeners )
845 sal_Int32 nCount = aListeners.getLength();
846 Sequence< Reference<XAllListener> > aFilterListeners(nCount);
847 for (sal_Int32 i = 0; i < nCount; ++i)
849 aFilterListeners[i]
850 = new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener);
853 return attachListeners(xObject, aFilterListeners, aListeners);
858 extern "C"
860 SAL_DLLPUBLIC_EXPORT void * evtatt_component_getFactory(
861 const sal_Char * pImplName, void * pServiceManager, void * )
863 void * pRet = nullptr;
865 if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
867 Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory(
868 static_cast< XMultiServiceFactory * >( pServiceManager ),
869 IMPLNAME,
870 ::comp_EventAttacher::EventAttacherImpl_CreateInstance,
871 ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) );
873 if (xFactory.is())
875 xFactory->acquire();
876 pRet = xFactory.get();
880 return pRet;
885 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */