tdf#145842 canceling remote file delete makes file disappear from treeview
[LibreOffice.git] / eventattacher / source / eventattacher.cxx
blob33c41a0f9d032ffe7ee159d2cf74bee4716179f0
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/beans/IntrospectionException.hpp>
23 #include <com/sun/star/beans/theIntrospection.hpp>
24 #include <com/sun/star/beans/MethodConcept.hpp>
25 #include <com/sun/star/script/CannotConvertException.hpp>
26 #include <com/sun/star/script/CannotCreateAdapterException.hpp>
27 #include <com/sun/star/script/XEventAttacher2.hpp>
28 #include <com/sun/star/script/Converter.hpp>
29 #include <com/sun/star/script/XAllListener.hpp>
30 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
31 #include <com/sun/star/reflection/theCoreReflection.hpp>
32 #include <com/sun/star/reflection/XIdlReflection.hpp>
34 // InvocationToAllListenerMapper
35 #include <com/sun/star/script/XInvocation.hpp>
36 #include <cppuhelper/exc_hlp.hxx>
37 #include <cppuhelper/weak.hxx>
38 #include <cppuhelper/factory.hxx>
39 #include <cppuhelper/implbase.hxx>
40 #include <cppuhelper/supportsservice.hxx>
42 #include <mutex>
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 namespace comp_EventAttacher {
59 // class InvocationToAllListenerMapper
60 // helper class to map XInvocation to XAllListener
62 namespace {
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;
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 { 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.hasElements() )
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 namespace {
203 class EventAttacherImpl : public WeakImplHelper < XEventAttacher2, XInitialization, XServiceInfo >
205 public:
206 explicit EventAttacherImpl( const Reference< XComponentContext >& );
208 // XServiceInfo
209 virtual OUString SAL_CALL getImplementationName( ) override;
210 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
211 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
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 std::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();
274 EventAttacherImpl::EventAttacherImpl( const Reference< XComponentContext >& rxContext )
275 : m_xContext( rxContext )
279 /// @throws Exception
280 OUString SAL_CALL EventAttacherImpl::getImplementationName( )
282 return "com.sun.star.comp.EventAttacher";
285 sal_Bool SAL_CALL EventAttacherImpl::supportsService( const OUString& ServiceName )
287 return cppu::supportsService(this, ServiceName);
290 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames( )
292 return { "com.sun.star.script.EventAttacher" };
295 void SAL_CALL EventAttacherImpl::initialize(const Sequence< Any >& Arguments)
297 // get services from the argument list
298 for( const Any& arg : Arguments )
300 if( arg.getValueType().getTypeClass() != TypeClass_INTERFACE )
301 throw IllegalArgumentException();
303 // InvocationAdapter service ?
304 Reference< XInvocationAdapterFactory2 > xALAS;
305 arg >>= xALAS;
306 if( xALAS.is() )
308 std::scoped_lock aGuard( m_aMutex );
309 m_xInvocationAdapterFactory = xALAS;
311 // Introspection service ?
312 Reference< XIntrospection > xI;
313 arg >>= xI;
314 if( xI.is() )
316 std::scoped_lock aGuard( m_aMutex );
317 m_xIntrospection = xI;
319 // Reflection service ?
320 Reference< XIdlReflection > xIdlR;
321 arg >>= xIdlR;
322 if( xIdlR.is() )
324 std::scoped_lock aGuard( m_aMutex );
325 m_xReflection = xIdlR;
327 // Converter Service ?
328 Reference< XTypeConverter > xC;
329 arg >>= xC;
330 if( xC.is() )
332 std::scoped_lock aGuard( m_aMutex );
333 m_xConverter = xC;
336 // no right interface
337 if( !xALAS.is() && !xI.is() && !xIdlR.is() && !xC.is() )
338 throw IllegalArgumentException();
343 //*** Private helper methods ***
344 Reference< XIntrospection > EventAttacherImpl::getIntrospection()
346 std::scoped_lock aGuard( m_aMutex );
347 if( !m_xIntrospection.is() )
349 m_xIntrospection = theIntrospection::get( m_xContext );
351 return m_xIntrospection;
355 //*** Private helper methods ***
356 Reference< XIdlReflection > EventAttacherImpl::getReflection()
358 std::scoped_lock aGuard( m_aMutex );
359 if( !m_xReflection.is() )
361 m_xReflection = theCoreReflection::get(m_xContext);
363 return m_xReflection;
367 //*** Private helper methods ***
368 Reference< XInvocationAdapterFactory2 > EventAttacherImpl::getInvocationAdapterService()
370 std::scoped_lock aGuard( m_aMutex );
371 if( !m_xInvocationAdapterFactory.is() )
373 m_xInvocationAdapterFactory = InvocationAdapterFactory::create(m_xContext);
375 return m_xInvocationAdapterFactory;
379 //*** Private helper methods ***
380 Reference< XTypeConverter > EventAttacherImpl::getConverter()
382 std::scoped_lock aGuard( m_aMutex );
383 if( !m_xConverter.is() )
385 m_xConverter = Converter::create(m_xContext);
387 return m_xConverter;
390 namespace {
392 // Implementation of an EventAttacher-related AllListeners, which brings
393 // a few Events to a general AllListener
394 class FilterAllListenerImpl : public WeakImplHelper< XAllListener >
396 public:
397 FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
398 const Reference< XAllListener >& AllListener_ );
400 // XAllListener
401 virtual void SAL_CALL firing(const AllEventObject& Event) override;
402 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) override;
404 // XEventListener
405 virtual void SAL_CALL disposing(const EventObject& Source) override;
407 private:
408 // convert
409 /// @throws CannotConvertException
410 /// @throws RuntimeException
411 void convertToEventReturn( Any & rRet, const Type& rRetType );
413 EventAttacherImpl * m_pEA;
414 OUString m_EventMethod;
415 Reference< XAllListener > m_AllListener;
420 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
421 const Reference< XAllListener >& AllListener_ )
422 : m_pEA( pEA_ )
423 , m_EventMethod( EventMethod_ )
424 , m_AllListener( AllListener_ )
429 void SAL_CALL FilterAllListenerImpl::firing(const AllEventObject& Event)
431 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
432 m_AllListener->firing( Event );
435 // Convert to the standard event return
436 void FilterAllListenerImpl::convertToEventReturn( Any & rRet, const Type & rRetType )
438 // no return value? Set to the specified values
439 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
441 switch( rRetType.getTypeClass() )
443 case TypeClass_INTERFACE:
445 rRet <<= Reference< XInterface >();
447 break;
449 case TypeClass_BOOLEAN:
450 rRet <<= true;
451 break;
453 case TypeClass_STRING:
454 rRet <<= OUString();
455 break;
457 case TypeClass_FLOAT: rRet <<= float(0); break;
458 case TypeClass_DOUBLE: rRet <<= 0.0; break;
459 case TypeClass_BYTE: rRet <<= sal_uInt8( 0 ); break;
460 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
461 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
462 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
463 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
464 default:
465 break;
468 else if( !rRet.getValueType().equals( rRetType ) )
470 Reference< XTypeConverter > xConverter = m_pEA->getConverter();
471 if( !xConverter.is() )
472 throw CannotConvertException(); // TODO TypeConversionException
473 rRet = xConverter->convertTo( rRet, rRetType );
478 Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event )
480 Any aRet;
482 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
483 aRet = m_AllListener->approveFiring( Event );
484 else
486 // Convert to the standard event return
489 Reference< XIdlClass > xListenerType = m_pEA->getReflection()->
490 forName( Event.ListenerType.getTypeName() );
491 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
492 if( xMeth.is() )
494 Reference< XIdlClass > xRetType = xMeth->getReturnType();
495 Type aRetType( xRetType->getTypeClass(), xRetType->getName() );
496 convertToEventReturn( aRet, aRetType );
499 catch( const CannotConvertException& )
501 css::uno::Any anyEx = cppu::getCaughtException();
502 throw InvocationTargetException( OUString(), Reference< XInterface >(), anyEx );
505 return aRet;
509 void FilterAllListenerImpl::disposing(const EventObject& )
511 // TODO: ???
515 Reference< XEventListener > EventAttacherImpl::attachListener
517 const Reference< XInterface >& xObject,
518 const Reference< XAllListener >& AllListener,
519 const Any& Helper,
520 const OUString& ListenerType,
521 const OUString& AddListenerParam
524 if( !xObject.is() || !AllListener.is() )
525 throw IllegalArgumentException();
527 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
528 if( !xInvocationAdapterFactory.is() )
529 throw ServiceNotRegisteredException();
531 Reference< XIdlReflection > xReflection = getReflection();
532 if( !xReflection.is() )
533 throw ServiceNotRegisteredException();
535 // Sign in, Call the fitting addListener method
536 // First Introspection, as the Methods can be analyzed in the same way
537 // For better performance it is implemented here again or make the Impl-Method
538 // of the Introspection configurable for this purpose.
539 Reference< XIntrospection > xIntrospection = getIntrospection();
540 if( !xIntrospection.is() )
541 return Reference<XEventListener>();
543 // Inspect Introspection
544 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
546 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
547 if( !xAccess.is() )
548 return Reference<XEventListener>();
550 return attachListenerForTarget(
551 xAccess, xInvocationAdapterFactory, AllListener, aObjAny, Helper,
552 ListenerType, AddListenerParam);
555 Reference<XEventListener> EventAttacherImpl::attachListenerForTarget(
556 const Reference<XIntrospectionAccess>& xAccess,
557 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
558 const Reference<XAllListener>& xAllListener,
559 const Any& aObject,
560 const Any& aHelper,
561 const OUString& aListenerType,
562 const OUString& aAddListenerParam)
564 Reference< XEventListener > xRet;
566 // Construct the name of the addListener-Method.
567 sal_Int32 nIndex = aListenerType.lastIndexOf('.');
568 // set index to the interface name without package name
569 if( nIndex == -1 )
570 // not found
571 nIndex = 0;
572 else
573 nIndex++;
575 OUString aListenerName = (!aListenerType.isEmpty() && aListenerType[nIndex] == 'X') ? aListenerType.copy(nIndex+1) : aListenerType;
576 OUString aAddListenerName = "add" + aListenerName;
578 // Send Methods to the correct addListener-Method
579 const Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
580 for (const Reference< XIdlMethod >& rxMethod : aMethodSeq)
582 // Is it the correct method?
583 OUString aMethName = rxMethod->getName();
585 if (aAddListenerName != aMethName)
586 continue;
588 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
589 sal_uInt32 nParamCount = params.getLength();
591 Reference< XIdlClass > xListenerType;
592 if( nParamCount == 1 )
593 xListenerType = params.getConstArray()[0];
594 else if( nParamCount == 2 )
595 xListenerType = params.getConstArray()[1];
597 // Request Adapter for the actual Listener type
598 Reference< XInterface > xAdapter = createAllListenerAdapter(
599 xInvocationAdapterFactory, xListenerType, xAllListener, aHelper );
601 if( !xAdapter.is() )
602 throw CannotCreateAdapterException();
603 xRet.set( xAdapter, UNO_QUERY );
605 // Just the Listener as parameter?
606 if( nParamCount == 1 )
608 Sequence< Any > args( 1 );
609 args.getArray()[0] <<= xAdapter;
612 rxMethod->invoke( aObject, args );
614 catch( const InvocationTargetException& )
616 throw IntrospectionException();
619 // Else, pass the other parameter now
620 else if( nParamCount == 2 )
622 Sequence< Any > args( 2 );
623 Any* pAnys = args.getArray();
625 // Check the type of the 1st parameter
626 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
627 if( xParamClass->getTypeClass() == TypeClass_STRING )
629 pAnys[0] <<= aAddListenerParam;
632 // 2nd Parameter == Listener? TODO: Test!
633 pAnys[1] <<= xAdapter;
635 // TODO: Convert String -> ?
636 // else
639 rxMethod->invoke( aObject, args );
641 catch( const InvocationTargetException& )
643 throw IntrospectionException();
646 break;
647 // else...
648 // Anything else is not supported
651 return xRet;
654 Sequence< Reference<XEventListener> > EventAttacherImpl::attachListeners(
655 const Reference<XInterface>& xObject,
656 const Sequence< Reference<XAllListener> >& AllListeners,
657 const Sequence<css::script::EventListener>& aListeners )
659 sal_Int32 nCount = aListeners.getLength();
660 if (nCount != AllListeners.getLength())
661 // This is a prerequisite!
662 throw RuntimeException();
664 if (!xObject.is())
665 throw IllegalArgumentException();
667 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
668 if( !xInvocationAdapterFactory.is() )
669 throw ServiceNotRegisteredException();
671 Reference< XIdlReflection > xReflection = getReflection();
672 if( !xReflection.is() )
673 throw ServiceNotRegisteredException();
675 // Sign in, Call the fitting addListener method
676 // First Introspection, as the Methods can be analyzed in the same way
677 // For better performance it is implemented here again or make the Impl-Method
678 // of the Introspection configurable for this purpose.
679 Reference< XIntrospection > xIntrospection = getIntrospection();
680 if( !xIntrospection.is() )
681 return Sequence< Reference<XEventListener> >();
683 // Inspect Introspection
684 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get() );
686 Reference<XIntrospectionAccess> xAccess = xIntrospection->inspect(aObjAny);
687 if (!xAccess.is())
688 return Sequence< Reference<XEventListener> >();
690 Sequence< Reference<XEventListener> > aRet(nCount);
691 Reference<XEventListener>* pArray = aRet.getArray();
693 for (sal_Int32 i = 0; i < nCount; ++i)
695 pArray[i] = attachListenerForTarget(
696 xAccess, xInvocationAdapterFactory, AllListeners[ i ],
697 aObjAny, aListeners[i].Helper, aListeners[i].ListenerType, aListeners[i].AddListenerParam);
700 return aRet;
703 // XEventAttacher
704 Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
706 const Reference< XInterface >& xObject,
707 const Reference< XAllListener >& AllListener,
708 const Any& Helper,
709 const OUString& ListenerType,
710 const OUString& AddListenerParam,
711 const OUString& EventMethod
714 // Subscribe FilterListener
715 Reference<XAllListener> aFilterListener
716 = new FilterAllListenerImpl(this, EventMethod, AllListener);
717 return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam);
720 // XEventAttacher
721 void EventAttacherImpl::removeListener
723 const Reference< XInterface >& xObject,
724 const OUString& ListenerType,
725 const OUString& AddListenerParam,
726 const Reference< XEventListener >& aToRemoveListener
729 if( !xObject.is() || !aToRemoveListener.is() )
730 throw IllegalArgumentException();
732 Reference< XIdlReflection > xReflection = getReflection();
733 if( !xReflection.is() )
734 throw IntrospectionException();
736 // Sign off, Call the fitting removeListener method
737 // First Introspection, as the Methods can be analyzed in the same way
738 // For better performance it is implemented here again or make the Impl-Method
739 // of the Introspection configurable for this purpose.
740 Reference< XIntrospection > xIntrospection = getIntrospection();
741 if( !xIntrospection.is() )
742 throw IntrospectionException();
744 //Inspect Introspection
745 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
746 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
747 if( !xAccess.is() )
748 throw IntrospectionException();
750 // Create name of the removeListener-Method
751 OUString aRemoveListenerName;
752 OUString aListenerName( ListenerType );
753 sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
754 // set index to the interface name without package name
755 if( nIndex == -1 )
756 // not found
757 nIndex = 0;
758 else
759 nIndex++;
760 if( aListenerName[nIndex] == 'X' )
761 // erase X from the interface name
762 aListenerName = aListenerName.copy( nIndex +1 );
763 aRemoveListenerName = "remove" + aListenerName;
765 // Search methods for the correct removeListener method
766 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
767 sal_uInt32 i, nLen = aMethodSeq.getLength();
768 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
769 for( i = 0 ; i < nLen ; i++ )
771 // Call Method
772 const Reference< XIdlMethod >& rxMethod = pMethods[i];
774 // Is it the right method?
775 if( aRemoveListenerName == rxMethod->getName() )
777 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
778 sal_uInt32 nParamCount = params.getLength();
780 // Just the Listener as parameter?
781 if( nParamCount == 1 )
783 Sequence< Any > args( 1 );
784 args.getArray()[0] <<= aToRemoveListener;
787 rxMethod->invoke( aObjAny, args );
789 catch( const InvocationTargetException& )
791 throw IntrospectionException();
794 // Else pass the other parameter
795 else if( nParamCount == 2 )
797 Sequence< Any > args( 2 );
798 Any* pAnys = args.getArray();
800 // Check the type of the 1st parameter
801 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
802 if( xParamClass->getTypeClass() == TypeClass_STRING )
803 pAnys[0] <<= AddListenerParam;
805 // 2nd parameter == Listener? TODO: Test!
806 pAnys[1] <<= aToRemoveListener;
808 // TODO: Convert String -> ?
809 // else
812 rxMethod->invoke( aObjAny, args );
814 catch( const InvocationTargetException& )
816 throw IntrospectionException();
819 break;
824 Sequence< Reference<XEventListener> > EventAttacherImpl::attachMultipleEventListeners(
825 const Reference<XInterface>& xObject, const Sequence<css::script::EventListener>& aListeners )
827 sal_Int32 nCount = aListeners.getLength();
828 Sequence< Reference<XAllListener> > aFilterListeners(nCount);
829 auto aFilterListenersRange = asNonConstRange(aFilterListeners);
830 for (sal_Int32 i = 0; i < nCount; ++i)
832 aFilterListenersRange[i]
833 = new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener);
836 return attachListeners(xObject, aFilterListeners, aListeners);
841 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
842 eventattacher_EventAttacher(
843 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
845 return cppu::acquire(new comp_EventAttacher::EventAttacherImpl(context));
849 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */