Bump version to 5.0-14
[LibreOffice.git] / eventattacher / source / eventattacher.cxx
blob6e7cd7cbbdc3c4a1a183ff58e5c5feeb7b7d3810
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 <osl/diagnose.h>
20 #include <com/sun/star/lang/XServiceInfo.hpp>
21 #include <com/sun/star/lang/XInitialization.hpp>
22 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
23 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
24 #include <com/sun/star/registry/XRegistryKey.hpp>
25 #include <com/sun/star/beans/theIntrospection.hpp>
26 #include <com/sun/star/beans/MethodConcept.hpp>
27 #include <com/sun/star/script/XEventAttacher2.hpp>
28 #include <com/sun/star/script/Converter.hpp>
29 #include <com/sun/star/script/XAllListener.hpp>
30 #include <com/sun/star/script/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 <comphelper/processfactory.hxx>
37 #include <cppuhelper/weak.hxx>
38 #include <cppuhelper/factory.hxx>
39 #include <cppuhelper/implbase1.hxx>
40 #include <cppuhelper/implbase3.hxx>
41 #include <cppuhelper/supportsservice.hxx>
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star::registry;
45 using namespace com::sun::star::lang;
46 using namespace com::sun::star::beans;
47 using namespace com::sun::star::script;
48 using namespace com::sun::star::reflection;
49 using namespace cppu;
50 using namespace osl;
54 #define SERVICENAME "com.sun.star.script.EventAttacher"
55 #define IMPLNAME "com.sun.star.comp.EventAttacher"
57 namespace comp_EventAttacher {
60 // class InvocationToAllListenerMapper
61 // helper class to map XInvocation to XAllListener
63 class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation >
65 public:
66 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
67 const Reference< XAllListener >& AllListener, const Any& Helper );
69 // XInvocation
70 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
71 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
72 throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
73 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value)
74 throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
75 virtual Any SAL_CALL getValue(const OUString& PropertyName) throw( UnknownPropertyException, RuntimeException, std::exception ) SAL_OVERRIDE;
76 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
77 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
79 private:
80 Reference< XIdlReflection > m_xCoreReflection;
81 Reference< XAllListener > m_xAllListener;
82 Reference< XIdlClass > m_xListenerType;
83 Any m_Helper;
87 // Function to replace AllListenerAdapterService::createAllListerAdapter
88 Reference< XInterface > createAllListenerAdapter
90 const Reference< XInvocationAdapterFactory2 >& xInvocationAdapterFactory,
91 const Reference< XIdlClass >& xListenerType,
92 const Reference< XAllListener >& xListener,
93 const Any& Helper
96 Reference< XInterface > xAdapter;
97 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
99 Reference< XInvocation > xInvocationToAllListenerMapper =
100 (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper );
101 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName());
102 Sequence<Type> arg2(1);
103 arg2[0] = aListenerType;
104 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, arg2 );
106 return xAdapter;
111 // InvocationToAllListenerMapper
112 InvocationToAllListenerMapper::InvocationToAllListenerMapper
113 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
114 : m_xAllListener( AllListener )
115 , m_xListenerType( ListenerType )
116 , m_Helper( Helper )
121 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection()
122 throw( RuntimeException, std::exception )
124 return Reference< XIntrospectionAccess >();
128 Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
129 Sequence< sal_Int16 >& , Sequence< Any >& )
130 throw( IllegalArgumentException, CannotConvertException,
131 InvocationTargetException, RuntimeException, std::exception )
133 Any aRet;
135 // Check if to firing or approveFiring has to be called
136 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
137 bool bApproveFiring = false;
138 if( !xMethod.is() )
139 return aRet;
140 Reference< XIdlClass > xReturnType = xMethod->getReturnType();
141 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
142 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
143 aExceptionSeq.getLength() > 0 )
145 bApproveFiring = true;
147 else
149 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
150 sal_uInt32 nParamCount = aParamSeq.getLength();
151 if( nParamCount > 1 )
153 const ParamInfo* pInfos = aParamSeq.getConstArray();
154 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
156 if( pInfos[ i ].aMode != ParamMode_IN )
158 bApproveFiring = true;
159 break;
165 AllEventObject aAllEvent;
166 aAllEvent.Source = (OWeakObject*) this;
167 aAllEvent.Helper = m_Helper;
168 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName());
169 aAllEvent.MethodName = FunctionName;
170 aAllEvent.Arguments = Params;
171 if( bApproveFiring )
172 aRet = m_xAllListener->approveFiring( aAllEvent );
173 else
174 m_xAllListener->firing( aAllEvent );
175 return aRet;
179 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& , const Any& )
180 throw( UnknownPropertyException, CannotConvertException,
181 InvocationTargetException, RuntimeException, std::exception )
186 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& )
187 throw( UnknownPropertyException, RuntimeException, std::exception )
189 return Any();
193 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
194 throw( RuntimeException, std::exception )
196 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
197 return xMethod.is();
201 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
202 throw( RuntimeException, std::exception )
204 Reference< XIdlField > xField = m_xListenerType->getField( Name );
205 return xField.is();
209 // class EventAttacherImpl
210 // represents an implementation of the EventAttacher service
212 class EventAttacherImpl : public WeakImplHelper3 < XEventAttacher2, XInitialization, XServiceInfo >
214 public:
215 EventAttacherImpl( const Reference< XComponentContext >& );
216 virtual ~EventAttacherImpl();
218 // XServiceInfo
219 virtual OUString SAL_CALL getImplementationName( ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
220 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
221 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
222 static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static( );
224 // XInitialization
225 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments )
226 throw( Exception, RuntimeException, std::exception) SAL_OVERRIDE;
228 // Methoden von XEventAttacher
229 virtual Reference< XEventListener > SAL_CALL attachListener(const Reference< XInterface >& xObject,
230 const Reference< XAllListener >& AllListener, const Any& Helper,
231 const OUString& ListenerType, const OUString& AddListenerParam)
232 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException, std::exception ) SAL_OVERRIDE;
233 virtual Reference< XEventListener > SAL_CALL attachSingleEventListener(const Reference< XInterface >& xObject,
234 const Reference< XAllListener >& AllListener, const Any& Helper,
235 const OUString& ListenerType, const OUString& AddListenerParam,
236 const OUString& EventMethod)
237 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException, std::exception ) SAL_OVERRIDE;
238 virtual void SAL_CALL removeListener(const Reference< XInterface >& xObject,
239 const OUString& ListenerType, const OUString& AddListenerParam,
240 const Reference< XEventListener >& aToRemoveListener)
241 throw( IllegalArgumentException, IntrospectionException, RuntimeException, std::exception ) SAL_OVERRIDE;
243 // XEventAttacher2
244 virtual Sequence< Reference<XEventListener> > SAL_CALL attachMultipleEventListeners(
245 const Reference<XInterface>& xObject, const Sequence<com::sun::star::script::EventListener>& aListeners )
246 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException, std::exception ) SAL_OVERRIDE;
248 // used by FilterAllListener_Impl
249 Reference< XTypeConverter > getConverter() throw( Exception );
251 friend class FilterAllListenerImpl;
253 private:
254 static Reference<XEventListener> attachListenerForTarget(
255 const Reference<XIntrospectionAccess>& xAccess,
256 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
257 const Reference<XAllListener>& xAllListener,
258 const Any& aObject,
259 const Any& aHelper,
260 const OUString& aListenerType,
261 const OUString& aAddListenerParam );
263 Sequence< Reference<XEventListener> > attachListeners(
264 const Reference<XInterface>& xObject,
265 const Sequence< Reference<XAllListener> >& AllListeners,
266 const Sequence<com::sun::star::script::EventListener>& aListeners );
268 private:
269 Mutex m_aMutex;
270 Reference< XComponentContext > m_xContext;
272 // Save Services
273 Reference< XIntrospection > m_xIntrospection;
274 Reference< XIdlReflection > m_xReflection;
275 Reference< XTypeConverter > m_xConverter;
276 Reference< XInvocationAdapterFactory2 > m_xInvocationAdapterFactory;
278 // needed services
279 Reference< XIntrospection > getIntrospection() throw( Exception );
280 Reference< XIdlReflection > getReflection() throw( Exception );
281 Reference< XInvocationAdapterFactory2 > getInvocationAdapterService() throw( Exception );
286 EventAttacherImpl::EventAttacherImpl( const Reference< XComponentContext >& rxContext )
287 : m_xContext( rxContext )
292 EventAttacherImpl::~EventAttacherImpl()
297 Reference< XInterface > SAL_CALL EventAttacherImpl_CreateInstance( const Reference< XMultiServiceFactory >& rSMgr ) throw( Exception )
299 XEventAttacher *pEventAttacher = (XEventAttacher*) new EventAttacherImpl( comphelper::getComponentContext(rSMgr) );
301 Reference< XInterface > xRet = Reference<XInterface>::query(pEventAttacher);
303 return xRet;
307 OUString SAL_CALL EventAttacherImpl::getImplementationName( )
308 throw(RuntimeException, std::exception)
310 return OUString( IMPLNAME );
313 sal_Bool SAL_CALL EventAttacherImpl::supportsService( const OUString& ServiceName )
314 throw(RuntimeException, std::exception)
316 return cppu::supportsService(this, ServiceName);
319 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames( )
320 throw(RuntimeException, std::exception)
322 return getSupportedServiceNames_Static();
326 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames_Static( )
328 OUString aStr( SERVICENAME );
329 return Sequence< OUString >( &aStr, 1 );
332 void SAL_CALL EventAttacherImpl::initialize(const Sequence< Any >& Arguments) throw( Exception, RuntimeException, std::exception )
334 // get services from the argument list
335 const Any * pArray = Arguments.getConstArray();
336 for( sal_Int32 i = 0; i < Arguments.getLength(); i++ )
338 if( pArray[i].getValueType().getTypeClass() != TypeClass_INTERFACE )
339 throw IllegalArgumentException();
341 // InvocationAdapter service ?
342 Reference< XInvocationAdapterFactory2 > xALAS;
343 pArray[i] >>= xALAS;
344 if( xALAS.is() )
346 Guard< Mutex > aGuard( m_aMutex );
347 m_xInvocationAdapterFactory = xALAS;
349 // Introspection service ?
350 Reference< XIntrospection > xI;
351 pArray[i] >>= xI;
352 if( xI.is() )
354 Guard< Mutex > aGuard( m_aMutex );
355 m_xIntrospection = xI;
357 // Reflection service ?
358 Reference< XIdlReflection > xIdlR;
359 pArray[i] >>= xIdlR;
360 if( xIdlR.is() )
362 Guard< Mutex > aGuard( m_aMutex );
363 m_xReflection = xIdlR;
365 // Converter Service ?
366 Reference< XTypeConverter > xC;
367 pArray[i] >>= xC;
368 if( xC.is() )
370 Guard< Mutex > aGuard( m_aMutex );
371 m_xConverter = xC;
374 // no right interface
375 if( !xALAS.is() && !xI.is() && !xIdlR.is() && !xC.is() )
376 throw IllegalArgumentException();
381 //*** Private helper methods ***
382 Reference< XIntrospection > EventAttacherImpl::getIntrospection() throw( Exception )
384 Guard< Mutex > aGuard( m_aMutex );
385 if( !m_xIntrospection.is() )
387 m_xIntrospection = theIntrospection::get( m_xContext );
389 return m_xIntrospection;
393 //*** Private helper methods ***
394 Reference< XIdlReflection > EventAttacherImpl::getReflection() throw( Exception )
396 Guard< Mutex > aGuard( m_aMutex );
397 if( !m_xReflection.is() )
399 m_xReflection = theCoreReflection::get(m_xContext);
401 return m_xReflection;
405 //*** Private helper methods ***
406 Reference< XInvocationAdapterFactory2 > EventAttacherImpl::getInvocationAdapterService() throw( Exception )
408 Guard< Mutex > aGuard( m_aMutex );
409 if( !m_xInvocationAdapterFactory.is() )
411 m_xInvocationAdapterFactory = InvocationAdapterFactory::create(m_xContext);
413 return m_xInvocationAdapterFactory;
418 //*** Private helper methods ***
419 Reference< XTypeConverter > EventAttacherImpl::getConverter() throw( Exception )
421 Guard< Mutex > aGuard( m_aMutex );
422 if( !m_xConverter.is() )
424 m_xConverter = Converter::create(m_xContext);
426 return m_xConverter;
432 // Implementation of an EventAttacher-related AllListeners, which brings
433 // a few Events to a general AllListener
434 class FilterAllListenerImpl : public WeakImplHelper1< XAllListener >
436 public:
437 FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
438 const Reference< XAllListener >& AllListener_ );
440 // XAllListener
441 virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
442 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
444 // XEventListener
445 virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
447 private:
448 // convert
449 void convertToEventReturn( Any & rRet, const Type& rRetType )
450 throw (CannotConvertException, RuntimeException);
452 EventAttacherImpl * m_pEA;
453 Reference< XInterface > m_xEAHold;
454 OUString m_EventMethod;
455 Reference< XAllListener > m_AllListener;
459 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
460 const Reference< XAllListener >& AllListener_ )
461 : m_pEA( pEA_ )
462 , m_xEAHold( *pEA_ )
463 , m_EventMethod( EventMethod_ )
464 , m_AllListener( AllListener_ )
469 void SAL_CALL FilterAllListenerImpl::firing(const AllEventObject& Event)
470 throw( RuntimeException, std::exception )
472 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
473 m_AllListener->firing( Event );
476 // Convert to the standard event return
477 void FilterAllListenerImpl::convertToEventReturn( Any & rRet, const Type & rRetType )
478 throw (CannotConvertException, RuntimeException)
480 // no return value? Set to the specified values
481 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
483 switch( rRetType.getTypeClass() )
485 case TypeClass_INTERFACE:
487 rRet <<= Reference< XInterface >();
489 break;
491 case TypeClass_BOOLEAN:
492 rRet <<= sal_True;
493 break;
495 case TypeClass_STRING:
496 rRet <<= OUString();
497 break;
499 case TypeClass_FLOAT: rRet <<= float(0); break;
500 case TypeClass_DOUBLE: rRet <<= double(0.0); break;
501 case TypeClass_BYTE: rRet <<= sal_uInt8( 0 ); break;
502 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
503 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
504 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
505 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
506 default:
507 break;
510 else if( !rRet.getValueType().equals( rRetType ) )
512 Reference< XTypeConverter > xConverter = m_pEA->getConverter();
513 if( xConverter.is() )
514 rRet = xConverter->convertTo( rRet, rRetType );
515 else
516 throw CannotConvertException(); // TODO TypeConversionException
521 Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event )
522 throw( InvocationTargetException, RuntimeException, std::exception )
524 Any aRet;
526 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
527 aRet = m_AllListener->approveFiring( Event );
528 else
530 // Convert to the standard event return
533 Reference< XIdlClass > xListenerType = m_pEA->getReflection()->
534 forName( Event.ListenerType.getTypeName() );
535 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
536 if( xMeth.is() )
538 Reference< XIdlClass > xRetType = xMeth->getReturnType();
539 Type aRetType( xRetType->getTypeClass(), xRetType->getName() );
540 convertToEventReturn( aRet, aRetType );
543 catch( const CannotConvertException& e )
545 throw InvocationTargetException( OUString(), Reference< XInterface >(), Any(&e, cppu::UnoType<CannotConvertException>::get()) );
548 return aRet;
552 void FilterAllListenerImpl::disposing(const EventObject& )
553 throw( RuntimeException, std::exception )
555 // TODO: ???
560 Reference< XEventListener > EventAttacherImpl::attachListener
562 const Reference< XInterface >& xObject,
563 const Reference< XAllListener >& AllListener,
564 const Any& Helper,
565 const OUString& ListenerType,
566 const OUString& AddListenerParam
568 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException, std::exception )
570 if( !xObject.is() || !AllListener.is() )
571 throw IllegalArgumentException();
573 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
574 if( !xInvocationAdapterFactory.is() )
575 throw ServiceNotRegisteredException();
577 Reference< XIdlReflection > xReflection = getReflection();
578 if( !xReflection.is() )
579 throw ServiceNotRegisteredException();
581 // Sign in, Call the fitting addListener method
582 // First Introspection, as the Methods can be analyzed in the same way
583 // For better performance it is implemented here again or make the Impl-Method
584 // of the Introspection configurable for this purpose.
585 Reference< XIntrospection > xIntrospection = getIntrospection();
586 if( !xIntrospection.is() )
587 return Reference<XEventListener>();
589 // Inspect Introspection
590 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
592 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
593 if( !xAccess.is() )
594 return Reference<XEventListener>();
596 return attachListenerForTarget(
597 xAccess, xInvocationAdapterFactory, AllListener, aObjAny, Helper,
598 ListenerType, AddListenerParam);
601 Reference<XEventListener> EventAttacherImpl::attachListenerForTarget(
602 const Reference<XIntrospectionAccess>& xAccess,
603 const Reference<XInvocationAdapterFactory2>& xInvocationAdapterFactory,
604 const Reference<XAllListener>& xAllListener,
605 const Any& aObject,
606 const Any& aHelper,
607 const OUString& aListenerType,
608 const OUString& aAddListenerParam)
610 Reference< XEventListener > xRet = NULL;
612 // Construct the name of the addListener-Method.
613 sal_Int32 nIndex = aListenerType.lastIndexOf('.');
614 // set index to the interface name without package name
615 if( nIndex == -1 )
616 // not found
617 nIndex = 0;
618 else
619 nIndex++;
621 OUString aListenerName = (!aListenerType.isEmpty() && aListenerType[nIndex] == 'X') ? aListenerType.copy(nIndex+1) : aListenerType;
622 OUString aAddListenerName = "add" + aListenerName;
624 // Send Methods to the correct addListener-Method
625 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
626 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
627 for (sal_Int32 i = 0, n = aMethodSeq.getLength(); i < n ; ++i)
629 const Reference< XIdlMethod >& rxMethod = pMethods[i];
631 // Is it the correct method?
632 OUString aMethName = rxMethod->getName();
634 if (aAddListenerName != aMethName)
635 continue;
637 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
638 sal_uInt32 nParamCount = params.getLength();
640 Reference< XIdlClass > xListenerType;
641 if( nParamCount == 1 )
642 xListenerType = params.getConstArray()[0];
643 else if( nParamCount == 2 )
644 xListenerType = params.getConstArray()[1];
646 // Request Adapter for the actual Listener type
647 Reference< XInterface > xAdapter = createAllListenerAdapter(
648 xInvocationAdapterFactory, xListenerType, xAllListener, aHelper );
650 if( !xAdapter.is() )
651 throw CannotCreateAdapterException();
652 xRet = Reference< XEventListener >( xAdapter, UNO_QUERY );
654 // Just the Listener as parameter?
655 if( nParamCount == 1 )
657 Sequence< Any > args( 1 );
658 args.getArray()[0] <<= xAdapter;
661 rxMethod->invoke( aObject, args );
663 catch( const InvocationTargetException& )
665 throw IntrospectionException();
668 // Else, pass the other parameter now
669 else if( nParamCount == 2 )
671 Sequence< Any > args( 2 );
672 Any* pAnys = args.getArray();
674 // Check the type of the 1st parameter
675 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
676 if( xParamClass->getTypeClass() == TypeClass_STRING )
678 pAnys[0] <<= aAddListenerParam;
681 // 2nd Parameter == Listener? TODO: Test!
682 pAnys[1] <<= xAdapter;
684 // TODO: Convert String -> ?
685 // else
688 rxMethod->invoke( aObject, args );
690 catch( const InvocationTargetException& )
692 throw IntrospectionException();
695 break;
696 // else...
697 // Anything else is not supported
700 return xRet;
703 Sequence< Reference<XEventListener> > EventAttacherImpl::attachListeners(
704 const Reference<XInterface>& xObject,
705 const Sequence< Reference<XAllListener> >& AllListeners,
706 const Sequence<com::sun::star::script::EventListener>& aListeners )
708 sal_Int32 nCount = aListeners.getLength();
709 if (nCount != AllListeners.getLength())
710 // This is a prerequisite!
711 throw RuntimeException();
713 if (!xObject.is())
714 throw IllegalArgumentException();
716 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = getInvocationAdapterService();
717 if( !xInvocationAdapterFactory.is() )
718 throw ServiceNotRegisteredException();
720 Reference< XIdlReflection > xReflection = getReflection();
721 if( !xReflection.is() )
722 throw ServiceNotRegisteredException();
724 // Sign in, Call the fitting addListener method
725 // First Introspection, as the Methods can be analyzed in the same way
726 // For better performance it is implemented here again or make the Impl-Method
727 // of the Introspection configurable for this purpose.
728 Reference< XIntrospection > xIntrospection = getIntrospection();
729 if( !xIntrospection.is() )
730 return Sequence< Reference<XEventListener> >();
732 // Inspect Introspection
733 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get() );
735 Reference<XIntrospectionAccess> xAccess = xIntrospection->inspect(aObjAny);
736 if (!xAccess.is())
737 return Sequence< Reference<XEventListener> >();
739 Sequence< Reference<XEventListener> > aRet(nCount);
740 Reference<XEventListener>* pArray = aRet.getArray();
742 for (sal_Int32 i = 0; i < nCount; ++i)
744 pArray[i] = attachListenerForTarget(
745 xAccess, xInvocationAdapterFactory, AllListeners[ i ],
746 aObjAny, aListeners[i].Helper, aListeners[i].ListenerType, aListeners[i].AddListenerParam);
749 return aRet;
752 // XEventAttacher
753 Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
755 const Reference< XInterface >& xObject,
756 const Reference< XAllListener >& AllListener,
757 const Any& Helper,
758 const OUString& ListenerType,
759 const OUString& AddListenerParam,
760 const OUString& EventMethod
762 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException, std::exception )
764 // Subscribe FilterListener
765 Reference< XAllListener > aFilterListener = (XAllListener*)
766 new FilterAllListenerImpl( this, EventMethod, AllListener );
767 return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam);
770 // XEventAttacher
771 void EventAttacherImpl::removeListener
773 const Reference< XInterface >& xObject,
774 const OUString& ListenerType,
775 const OUString& AddListenerParam,
776 const Reference< XEventListener >& aToRemoveListener
778 throw( IllegalArgumentException, IntrospectionException, RuntimeException, std::exception )
780 if( !xObject.is() || !aToRemoveListener.is() )
781 throw IllegalArgumentException();
783 Reference< XIdlReflection > xReflection = getReflection();
784 if( !xReflection.is() )
785 throw IntrospectionException();
787 // Sign off, Call the fitting removeListener method
788 // First Introspection, as the Methods can be analyzed in the same way
789 // For better performance it is implemented here again or make the Impl-Method
790 // of the Introspection configurable for this purpose.
791 Reference< XIntrospection > xIntrospection = getIntrospection();
792 if( !xIntrospection.is() )
793 throw IntrospectionException();
795 //Inspect Introspection
796 Any aObjAny( &xObject, cppu::UnoType<XInterface>::get());
797 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
798 if( !xAccess.is() )
799 throw IntrospectionException();
801 // Create name of the removeListener-Method
802 OUString aRemoveListenerName;
803 OUString aListenerName( ListenerType );
804 sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
805 // set index to the interface name without package name
806 if( nIndex == -1 )
807 // not found
808 nIndex = 0;
809 else
810 nIndex++;
811 if( aListenerName[nIndex] == 'X' )
812 // erase X from the interface name
813 aListenerName = aListenerName.copy( nIndex +1 );
814 aRemoveListenerName = "remove" + aListenerName;
816 // Search methods for the correct removeListener method
817 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
818 sal_uInt32 i, nLen = aMethodSeq.getLength();
819 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
820 for( i = 0 ; i < nLen ; i++ )
822 // Call Methode
823 const Reference< XIdlMethod >& rxMethod = pMethods[i];
825 // Is it the right method?
826 if( aRemoveListenerName == rxMethod->getName() )
828 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
829 sal_uInt32 nParamCount = params.getLength();
831 // Just the Listener as parameter?
832 if( nParamCount == 1 )
834 Sequence< Any > args( 1 );
835 args.getArray()[0] <<= aToRemoveListener;
838 rxMethod->invoke( aObjAny, args );
840 catch( const InvocationTargetException& )
842 throw IntrospectionException();
845 // Else pass the other parameter
846 else if( nParamCount == 2 )
848 Sequence< Any > args( 2 );
849 Any* pAnys = args.getArray();
851 // Check the type of the 1st parameter
852 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
853 if( xParamClass->getTypeClass() == TypeClass_STRING )
854 pAnys[0] <<= AddListenerParam;
856 // 2nd parameter == Listener? TODO: Test!
857 pAnys[1] <<= aToRemoveListener;
859 // TODO: Convert String -> ?
860 // else
863 rxMethod->invoke( aObjAny, args );
865 catch( const InvocationTargetException& )
867 throw IntrospectionException();
870 break;
875 Sequence< Reference<XEventListener> > EventAttacherImpl::attachMultipleEventListeners(
876 const Reference<XInterface>& xObject, const Sequence<com::sun::star::script::EventListener>& aListeners )
877 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException, std::exception )
879 sal_Int32 nCount = aListeners.getLength();
880 Sequence< Reference<XAllListener> > aFilterListeners(nCount);
881 for (sal_Int32 i = 0; i < nCount; ++i)
883 aFilterListeners[i] = (XAllListener*)
884 new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener);
887 return attachListeners(xObject, aFilterListeners, aListeners);
892 extern "C"
894 SAL_DLLPUBLIC_EXPORT void * SAL_CALL evtatt_component_getFactory(
895 const sal_Char * pImplName, void * pServiceManager, void * )
897 void * pRet = 0;
899 if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
901 Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory(
902 static_cast< XMultiServiceFactory * >( pServiceManager ),
903 OUString( IMPLNAME ),
904 ::comp_EventAttacher::EventAttacherImpl_CreateInstance,
905 ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) );
907 if (xFactory.is())
909 xFactory->acquire();
910 pRet = xFactory.get();
914 return pRet;
920 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */