nss: upgrade to release 3.73
[LibreOffice.git] / eventattacher / source / eventattacher.cxx
blob9dd229f32e0d8cb99f0c2ccf10b63e21e0a97343
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 namespace com::sun::star::lang { class XMultiServiceFactory; }
44 using namespace com::sun::star::uno;
45 using namespace com::sun::star::registry;
46 using namespace com::sun::star::lang;
47 using namespace com::sun::star::beans;
48 using namespace com::sun::star::script;
49 using namespace com::sun::star::reflection;
50 using namespace cppu;
51 using namespace osl;
54 namespace comp_EventAttacher {
57 // class InvocationToAllListenerMapper
58 // helper class to map XInvocation to XAllListener
60 namespace {
62 class InvocationToAllListenerMapper : public WeakImplHelper< XInvocation >
64 public:
65 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
66 const Reference< XAllListener >& AllListener, const Any& Helper );
68 // XInvocation
69 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() override;
70 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) override;
71 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) override;
72 virtual Any SAL_CALL getValue(const OUString& PropertyName) override;
73 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) override;
74 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) override;
76 private:
77 Reference< XAllListener > m_xAllListener;
78 Reference< XIdlClass > m_xListenerType;
79 Any m_Helper;
84 // Function to replace AllListenerAdapterService::createAllListerAdapter
85 static Reference< XInterface > createAllListenerAdapter
87 const Reference< XInvocationAdapterFactory2 >& xInvocationAdapterFactory,
88 const Reference< XIdlClass >& xListenerType,
89 const Reference< XAllListener >& xListener,
90 const Any& Helper
93 Reference< XInterface > xAdapter;
94 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
96 Reference< XInvocation > xInvocationToAllListenerMapper =
97 new InvocationToAllListenerMapper(xListenerType, xListener, Helper);
98 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName());
99 Sequence<Type> arg2(1);
100 arg2[0] = aListenerType;
101 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, arg2 );
103 return xAdapter;
107 // InvocationToAllListenerMapper
108 InvocationToAllListenerMapper::InvocationToAllListenerMapper
109 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
110 : m_xAllListener( AllListener )
111 , m_xListenerType( ListenerType )
112 , m_Helper( Helper )
117 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection()
119 return Reference< XIntrospectionAccess >();
123 Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
124 Sequence< sal_Int16 >& , Sequence< Any >& )
126 Any aRet;
128 // Check if to firing or approveFiring has to be called
129 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
130 bool bApproveFiring = false;
131 if( !xMethod.is() )
132 return aRet;
133 Reference< XIdlClass > xReturnType = xMethod->getReturnType();
134 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
135 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
136 aExceptionSeq.hasElements() )
138 bApproveFiring = true;
140 else
142 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
143 sal_uInt32 nParamCount = aParamSeq.getLength();
144 if( nParamCount > 1 )
146 const ParamInfo* pInfo = aParamSeq.getConstArray();
147 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
149 if( pInfo[ i ].aMode != ParamMode_IN )
151 bApproveFiring = true;
152 break;
158 AllEventObject aAllEvent;
159 aAllEvent.Source = static_cast<OWeakObject*>(this);
160 aAllEvent.Helper = m_Helper;
161 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName());
162 aAllEvent.MethodName = FunctionName;
163 aAllEvent.Arguments = Params;
164 if( bApproveFiring )
165 aRet = m_xAllListener->approveFiring( aAllEvent );
166 else
167 m_xAllListener->firing( aAllEvent );
168 return aRet;
172 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& , const Any& )
177 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& )
179 return Any();
183 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
185 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
186 return xMethod.is();
190 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
192 Reference< XIdlField > xField = m_xListenerType->getField( Name );
193 return xField.is();
197 // class EventAttacherImpl
198 // represents an implementation of the EventAttacher service
200 namespace {
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;
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();
273 EventAttacherImpl::EventAttacherImpl( const Reference< XComponentContext >& rxContext )
274 : m_xContext( rxContext )
278 /// @throws Exception
279 OUString SAL_CALL EventAttacherImpl::getImplementationName( )
281 return "com.sun.star.comp.EventAttacher";
284 sal_Bool SAL_CALL EventAttacherImpl::supportsService( const OUString& ServiceName )
286 return cppu::supportsService(this, ServiceName);
289 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames( )
291 return { "com.sun.star.script.EventAttacher" };
294 void SAL_CALL EventAttacherImpl::initialize(const Sequence< Any >& Arguments)
296 // get services from the argument list
297 for( const Any& arg : Arguments )
299 if( arg.getValueType().getTypeClass() != TypeClass_INTERFACE )
300 throw IllegalArgumentException();
302 // InvocationAdapter service ?
303 Reference< XInvocationAdapterFactory2 > xALAS;
304 arg >>= xALAS;
305 if( xALAS.is() )
307 Guard< Mutex > aGuard( m_aMutex );
308 m_xInvocationAdapterFactory = xALAS;
310 // Introspection service ?
311 Reference< XIntrospection > xI;
312 arg >>= xI;
313 if( xI.is() )
315 Guard< Mutex > aGuard( m_aMutex );
316 m_xIntrospection = xI;
318 // Reflection service ?
319 Reference< XIdlReflection > xIdlR;
320 arg >>= xIdlR;
321 if( xIdlR.is() )
323 Guard< Mutex > aGuard( m_aMutex );
324 m_xReflection = xIdlR;
326 // Converter Service ?
327 Reference< XTypeConverter > xC;
328 arg >>= xC;
329 if( xC.is() )
331 Guard< Mutex > aGuard( m_aMutex );
332 m_xConverter = xC;
335 // no right interface
336 if( !xALAS.is() && !xI.is() && !xIdlR.is() && !xC.is() )
337 throw IllegalArgumentException();
342 //*** Private helper methods ***
343 Reference< XIntrospection > EventAttacherImpl::getIntrospection()
345 Guard< Mutex > aGuard( m_aMutex );
346 if( !m_xIntrospection.is() )
348 m_xIntrospection = theIntrospection::get( m_xContext );
350 return m_xIntrospection;
354 //*** Private helper methods ***
355 Reference< XIdlReflection > EventAttacherImpl::getReflection()
357 Guard< Mutex > aGuard( m_aMutex );
358 if( !m_xReflection.is() )
360 m_xReflection = theCoreReflection::get(m_xContext);
362 return m_xReflection;
366 //*** Private helper methods ***
367 Reference< XInvocationAdapterFactory2 > EventAttacherImpl::getInvocationAdapterService()
369 Guard< Mutex > aGuard( m_aMutex );
370 if( !m_xInvocationAdapterFactory.is() )
372 m_xInvocationAdapterFactory = InvocationAdapterFactory::create(m_xContext);
374 return m_xInvocationAdapterFactory;
378 //*** Private helper methods ***
379 Reference< XTypeConverter > EventAttacherImpl::getConverter()
381 Guard< Mutex > aGuard( m_aMutex );
382 if( !m_xConverter.is() )
384 m_xConverter = Converter::create(m_xContext);
386 return m_xConverter;
389 namespace {
391 // Implementation of an EventAttacher-related AllListeners, which brings
392 // a few Events to a general AllListener
393 class FilterAllListenerImpl : public WeakImplHelper< XAllListener >
395 public:
396 FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
397 const Reference< XAllListener >& AllListener_ );
399 // XAllListener
400 virtual void SAL_CALL firing(const AllEventObject& Event) override;
401 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) override;
403 // XEventListener
404 virtual void SAL_CALL disposing(const EventObject& Source) override;
406 private:
407 // convert
408 /// @throws CannotConvertException
409 /// @throws RuntimeException
410 void convertToEventReturn( Any & rRet, const Type& rRetType );
412 EventAttacherImpl * m_pEA;
413 OUString m_EventMethod;
414 Reference< XAllListener > m_AllListener;
419 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
420 const Reference< XAllListener >& AllListener_ )
421 : m_pEA( pEA_ )
422 , m_EventMethod( EventMethod_ )
423 , m_AllListener( AllListener_ )
428 void SAL_CALL FilterAllListenerImpl::firing(const AllEventObject& Event)
430 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
431 m_AllListener->firing( Event );
434 // Convert to the standard event return
435 void FilterAllListenerImpl::convertToEventReturn( Any & rRet, const Type & rRetType )
437 // no return value? Set to the specified values
438 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
440 switch( rRetType.getTypeClass() )
442 case TypeClass_INTERFACE:
444 rRet <<= Reference< XInterface >();
446 break;
448 case TypeClass_BOOLEAN:
449 rRet <<= true;
450 break;
452 case TypeClass_STRING:
453 rRet <<= OUString();
454 break;
456 case TypeClass_FLOAT: rRet <<= float(0); break;
457 case TypeClass_DOUBLE: rRet <<= 0.0; break;
458 case TypeClass_BYTE: rRet <<= sal_uInt8( 0 ); break;
459 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
460 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
461 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
462 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
463 default:
464 break;
467 else if( !rRet.getValueType().equals( rRetType ) )
469 Reference< XTypeConverter > xConverter = m_pEA->getConverter();
470 if( !xConverter.is() )
471 throw CannotConvertException(); // TODO TypeConversionException
472 rRet = xConverter->convertTo( rRet, rRetType );
477 Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event )
479 Any aRet;
481 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
482 aRet = m_AllListener->approveFiring( Event );
483 else
485 // Convert to the standard event return
488 Reference< XIdlClass > xListenerType = m_pEA->getReflection()->
489 forName( Event.ListenerType.getTypeName() );
490 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
491 if( xMeth.is() )
493 Reference< XIdlClass > xRetType = xMeth->getReturnType();
494 Type aRetType( xRetType->getTypeClass(), xRetType->getName() );
495 convertToEventReturn( aRet, aRetType );
498 catch( const CannotConvertException& )
500 css::uno::Any anyEx = cppu::getCaughtException();
501 throw InvocationTargetException( OUString(), Reference< XInterface >(), anyEx );
504 return aRet;
508 void FilterAllListenerImpl::disposing(const EventObject& )
510 // TODO: ???
514 Reference< XEventListener > EventAttacherImpl::attachListener
516 const Reference< XInterface >& xObject,
517 const Reference< XAllListener >& AllListener,
518 const Any& Helper,
519 const OUString& ListenerType,
520 const OUString& AddListenerParam
523 if( !xObject.is() || !AllListener.is() )
524 throw IllegalArgumentException();
526 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
527 if( !xInvocationAdapterFactory.is() )
528 throw ServiceNotRegisteredException();
530 Reference< XIdlReflection > xReflection = getReflection();
531 if( !xReflection.is() )
532 throw ServiceNotRegisteredException();
534 // Sign in, Call the fitting addListener method
535 // First Introspection, as the Methods can be analyzed in the same way
536 // For better performance it is implemented here again or make the Impl-Method
537 // of the Introspection configurable for this purpose.
538 Reference< XIntrospection > xIntrospection = getIntrospection();
539 if( !xIntrospection.is() )
540 return Reference<XEventListener>();
542 // Inspect Introspection
543 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
545 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
546 if( !xAccess.is() )
547 return Reference<XEventListener>();
549 return attachListenerForTarget(
550 xAccess, xInvocationAdapterFactory, AllListener, aObjAny, Helper,
551 ListenerType, AddListenerParam);
554 Reference<XEventListener> EventAttacherImpl::attachListenerForTarget(
555 const Reference<XIntrospectionAccess>& xAccess,
556 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
557 const Reference<XAllListener>& xAllListener,
558 const Any& aObject,
559 const Any& aHelper,
560 const OUString& aListenerType,
561 const OUString& aAddListenerParam)
563 Reference< XEventListener > xRet;
565 // Construct the name of the addListener-Method.
566 sal_Int32 nIndex = aListenerType.lastIndexOf('.');
567 // set index to the interface name without package name
568 if( nIndex == -1 )
569 // not found
570 nIndex = 0;
571 else
572 nIndex++;
574 OUString aListenerName = (!aListenerType.isEmpty() && aListenerType[nIndex] == 'X') ? aListenerType.copy(nIndex+1) : aListenerType;
575 OUString aAddListenerName = "add" + aListenerName;
577 // Send Methods to the correct addListener-Method
578 const Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
579 for (const Reference< XIdlMethod >& rxMethod : aMethodSeq)
581 // Is it the correct method?
582 OUString aMethName = rxMethod->getName();
584 if (aAddListenerName != aMethName)
585 continue;
587 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
588 sal_uInt32 nParamCount = params.getLength();
590 Reference< XIdlClass > xListenerType;
591 if( nParamCount == 1 )
592 xListenerType = params.getConstArray()[0];
593 else if( nParamCount == 2 )
594 xListenerType = params.getConstArray()[1];
596 // Request Adapter for the actual Listener type
597 Reference< XInterface > xAdapter = createAllListenerAdapter(
598 xInvocationAdapterFactory, xListenerType, xAllListener, aHelper );
600 if( !xAdapter.is() )
601 throw CannotCreateAdapterException();
602 xRet.set( xAdapter, UNO_QUERY );
604 // Just the Listener as parameter?
605 if( nParamCount == 1 )
607 Sequence< Any > args( 1 );
608 args.getArray()[0] <<= xAdapter;
611 rxMethod->invoke( aObject, args );
613 catch( const InvocationTargetException& )
615 throw IntrospectionException();
618 // Else, pass the other parameter now
619 else if( nParamCount == 2 )
621 Sequence< Any > args( 2 );
622 Any* pAnys = args.getArray();
624 // Check the type of the 1st parameter
625 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
626 if( xParamClass->getTypeClass() == TypeClass_STRING )
628 pAnys[0] <<= aAddListenerParam;
631 // 2nd Parameter == Listener? TODO: Test!
632 pAnys[1] <<= xAdapter;
634 // TODO: Convert String -> ?
635 // else
638 rxMethod->invoke( aObject, args );
640 catch( const InvocationTargetException& )
642 throw IntrospectionException();
645 break;
646 // else...
647 // Anything else is not supported
650 return xRet;
653 Sequence< Reference<XEventListener> > EventAttacherImpl::attachListeners(
654 const Reference<XInterface>& xObject,
655 const Sequence< Reference<XAllListener> >& AllListeners,
656 const Sequence<css::script::EventListener>& aListeners )
658 sal_Int32 nCount = aListeners.getLength();
659 if (nCount != AllListeners.getLength())
660 // This is a prerequisite!
661 throw RuntimeException();
663 if (!xObject.is())
664 throw IllegalArgumentException();
666 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
667 if( !xInvocationAdapterFactory.is() )
668 throw ServiceNotRegisteredException();
670 Reference< XIdlReflection > xReflection = getReflection();
671 if( !xReflection.is() )
672 throw ServiceNotRegisteredException();
674 // Sign in, Call the fitting addListener method
675 // First Introspection, as the Methods can be analyzed in the same way
676 // For better performance it is implemented here again or make the Impl-Method
677 // of the Introspection configurable for this purpose.
678 Reference< XIntrospection > xIntrospection = getIntrospection();
679 if( !xIntrospection.is() )
680 return Sequence< Reference<XEventListener> >();
682 // Inspect Introspection
683 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get() );
685 Reference<XIntrospectionAccess> xAccess = xIntrospection->inspect(aObjAny);
686 if (!xAccess.is())
687 return Sequence< Reference<XEventListener> >();
689 Sequence< Reference<XEventListener> > aRet(nCount);
690 Reference<XEventListener>* pArray = aRet.getArray();
692 for (sal_Int32 i = 0; i < nCount; ++i)
694 pArray[i] = attachListenerForTarget(
695 xAccess, xInvocationAdapterFactory, AllListeners[ i ],
696 aObjAny, aListeners[i].Helper, aListeners[i].ListenerType, aListeners[i].AddListenerParam);
699 return aRet;
702 // XEventAttacher
703 Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
705 const Reference< XInterface >& xObject,
706 const Reference< XAllListener >& AllListener,
707 const Any& Helper,
708 const OUString& ListenerType,
709 const OUString& AddListenerParam,
710 const OUString& EventMethod
713 // Subscribe FilterListener
714 Reference<XAllListener> aFilterListener
715 = new FilterAllListenerImpl(this, EventMethod, AllListener);
716 return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam);
719 // XEventAttacher
720 void EventAttacherImpl::removeListener
722 const Reference< XInterface >& xObject,
723 const OUString& ListenerType,
724 const OUString& AddListenerParam,
725 const Reference< XEventListener >& aToRemoveListener
728 if( !xObject.is() || !aToRemoveListener.is() )
729 throw IllegalArgumentException();
731 Reference< XIdlReflection > xReflection = getReflection();
732 if( !xReflection.is() )
733 throw IntrospectionException();
735 // Sign off, Call the fitting removeListener method
736 // First Introspection, as the Methods can be analyzed in the same way
737 // For better performance it is implemented here again or make the Impl-Method
738 // of the Introspection configurable for this purpose.
739 Reference< XIntrospection > xIntrospection = getIntrospection();
740 if( !xIntrospection.is() )
741 throw IntrospectionException();
743 //Inspect Introspection
744 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
745 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
746 if( !xAccess.is() )
747 throw IntrospectionException();
749 // Create name of the removeListener-Method
750 OUString aRemoveListenerName;
751 OUString aListenerName( ListenerType );
752 sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
753 // set index to the interface name without package name
754 if( nIndex == -1 )
755 // not found
756 nIndex = 0;
757 else
758 nIndex++;
759 if( aListenerName[nIndex] == 'X' )
760 // erase X from the interface name
761 aListenerName = aListenerName.copy( nIndex +1 );
762 aRemoveListenerName = "remove" + aListenerName;
764 // Search methods for the correct removeListener method
765 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
766 sal_uInt32 i, nLen = aMethodSeq.getLength();
767 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
768 for( i = 0 ; i < nLen ; i++ )
770 // Call Method
771 const Reference< XIdlMethod >& rxMethod = pMethods[i];
773 // Is it the right method?
774 if( aRemoveListenerName == rxMethod->getName() )
776 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
777 sal_uInt32 nParamCount = params.getLength();
779 // Just the Listener as parameter?
780 if( nParamCount == 1 )
782 Sequence< Any > args( 1 );
783 args.getArray()[0] <<= aToRemoveListener;
786 rxMethod->invoke( aObjAny, args );
788 catch( const InvocationTargetException& )
790 throw IntrospectionException();
793 // Else pass the other parameter
794 else if( nParamCount == 2 )
796 Sequence< Any > args( 2 );
797 Any* pAnys = args.getArray();
799 // Check the type of the 1st parameter
800 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
801 if( xParamClass->getTypeClass() == TypeClass_STRING )
802 pAnys[0] <<= AddListenerParam;
804 // 2nd parameter == Listener? TODO: Test!
805 pAnys[1] <<= aToRemoveListener;
807 // TODO: Convert String -> ?
808 // else
811 rxMethod->invoke( aObjAny, args );
813 catch( const InvocationTargetException& )
815 throw IntrospectionException();
818 break;
823 Sequence< Reference<XEventListener> > EventAttacherImpl::attachMultipleEventListeners(
824 const Reference<XInterface>& xObject, const Sequence<css::script::EventListener>& aListeners )
826 sal_Int32 nCount = aListeners.getLength();
827 Sequence< Reference<XAllListener> > aFilterListeners(nCount);
828 for (sal_Int32 i = 0; i < nCount; ++i)
830 aFilterListeners[i]
831 = new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener);
834 return attachListeners(xObject, aFilterListeners, aListeners);
839 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
840 eventattacher_EventAttacher(
841 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
843 return cppu::acquire(static_cast<cppu::OWeakObject*>(new comp_EventAttacher::EventAttacherImpl(context)));
847 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */