Bump for 3.6-28
[LibreOffice.git] / eventattacher / source / eventattacher.cxx
bloba0585f5b5bbab1207bd425d07e9b3f3fb6fb56f4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
28 #include <osl/diagnose.h>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/lang/XInitialization.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
33 #include <com/sun/star/registry/XRegistryKey.hpp>
34 #include <com/sun/star/beans/XIntrospection.hpp>
35 #include <com/sun/star/beans/MethodConcept.hpp>
36 #include <com/sun/star/script/XEventAttacher2.hpp>
37 #include <com/sun/star/script/XTypeConverter.hpp>
38 #include <com/sun/star/script/XAllListener.hpp>
39 #include <com/sun/star/script/XInvocationAdapterFactory.hpp>
40 #include <com/sun/star/reflection/XIdlReflection.hpp>
42 // InvocationToAllListenerMapper
43 #include <com/sun/star/script/XInvocation.hpp>
44 #include <cppuhelper/weak.hxx>
45 #include <cppuhelper/factory.hxx>
46 #include <cppuhelper/implbase1.hxx>
47 #include <cppuhelper/implbase3.hxx>
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::registry;
51 using namespace com::sun::star::lang;
52 using namespace com::sun::star::beans;
53 using namespace com::sun::star::script;
54 using namespace com::sun::star::reflection;
55 using namespace cppu;
56 using namespace osl;
58 using ::rtl::OUString;
61 #define SERVICENAME "com.sun.star.script.EventAttacher"
62 #define IMPLNAME "com.sun.star.comp.EventAttacher"
64 namespace comp_EventAttacher {
66 //*************************************************************************
67 // class InvocationToAllListenerMapper
68 // helper class to map XInvocation to XAllListener
69 //*************************************************************************
70 class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation >
72 public:
73 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
74 const Reference< XAllListener >& AllListener, const Any& Helper );
76 // XInvocation
77 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void) throw( RuntimeException );
78 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
79 throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException );
80 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value)
81 throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException );
82 virtual Any SAL_CALL getValue(const OUString& PropertyName) throw( UnknownPropertyException, RuntimeException );
83 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException );
84 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException );
86 private:
87 Reference< XIdlReflection > m_xCoreReflection;
88 Reference< XAllListener > m_xAllListener;
89 Reference< XIdlClass > m_xListenerType;
90 Any m_Helper;
94 // Function to replace AllListenerAdapterService::createAllListerAdapter
95 Reference< XInterface > createAllListenerAdapter
97 const Reference< XInvocationAdapterFactory >& xInvocationAdapterFactory,
98 const Reference< XIdlClass >& xListenerType,
99 const Reference< XAllListener >& xListener,
100 const Any& Helper
103 Reference< XInterface > xAdapter;
104 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
106 Reference< XInvocation > xInvocationToAllListenerMapper =
107 (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper );
108 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName());
109 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, aListenerType );
111 return xAdapter;
115 //--------------------------------------------------------------------------------------------------
116 // InvocationToAllListenerMapper
117 InvocationToAllListenerMapper::InvocationToAllListenerMapper
118 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
119 : m_xAllListener( AllListener )
120 , m_xListenerType( ListenerType )
121 , m_Helper( Helper )
125 //*************************************************************************
126 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void)
127 throw( RuntimeException )
129 return Reference< XIntrospectionAccess >();
132 //*************************************************************************
133 Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
134 Sequence< sal_Int16 >& , Sequence< Any >& )
135 throw( IllegalArgumentException, CannotConvertException,
136 InvocationTargetException, RuntimeException )
138 Any aRet;
140 // Check if to firing or approveFiring has to be called
141 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
142 sal_Bool bApproveFiring = sal_False;
143 if( !xMethod.is() )
144 return aRet;
145 Reference< XIdlClass > xReturnType = xMethod->getReturnType();
146 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
147 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
148 aExceptionSeq.getLength() > 0 )
150 bApproveFiring = sal_True;
152 else
154 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
155 sal_uInt32 nParamCount = aParamSeq.getLength();
156 if( nParamCount > 1 )
158 const ParamInfo* pInfos = aParamSeq.getConstArray();
159 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
161 if( pInfos[ i ].aMode != ParamMode_IN )
163 bApproveFiring = sal_True;
164 break;
170 AllEventObject aAllEvent;
171 aAllEvent.Source = (OWeakObject*) this;
172 aAllEvent.Helper = m_Helper;
173 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName());
174 aAllEvent.MethodName = FunctionName;
175 aAllEvent.Arguments = Params;
176 if( bApproveFiring )
177 aRet = m_xAllListener->approveFiring( aAllEvent );
178 else
179 m_xAllListener->firing( aAllEvent );
180 return aRet;
183 //*************************************************************************
184 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& , const Any& )
185 throw( UnknownPropertyException, CannotConvertException,
186 InvocationTargetException, RuntimeException )
190 //*************************************************************************
191 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& )
192 throw( UnknownPropertyException, RuntimeException )
194 return Any();
197 //*************************************************************************
198 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
199 throw( RuntimeException )
201 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
202 return xMethod.is();
205 //*************************************************************************
206 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
207 throw( RuntimeException )
209 Reference< XIdlField > xField = m_xListenerType->getField( Name );
210 return xField.is();
213 //*************************************************************************
214 // class EventAttacherImpl
215 // represents an implementation of the EventAttacher service
216 //*************************************************************************
217 class EventAttacherImpl : public WeakImplHelper3 < XEventAttacher2, XInitialization, XServiceInfo >
219 public:
220 EventAttacherImpl( const Reference< XMultiServiceFactory >& );
221 ~EventAttacherImpl();
223 // XServiceInfo
224 virtual OUString SAL_CALL getImplementationName( ) throw(RuntimeException);
225 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
226 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(RuntimeException);
227 static OUString SAL_CALL getImplementationName_Static( );
228 static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static( );
230 // XInitialization
231 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments )
232 throw( Exception, RuntimeException);
234 // Methoden von XEventAttacher
235 virtual Reference< XEventListener > SAL_CALL attachListener(const Reference< XInterface >& xObject,
236 const Reference< XAllListener >& AllListener, const Any& Helper,
237 const OUString& ListenerType, const OUString& AddListenerParam)
238 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException );
239 virtual Reference< XEventListener > SAL_CALL attachSingleEventListener(const Reference< XInterface >& xObject,
240 const Reference< XAllListener >& AllListener, const Any& Helper,
241 const OUString& ListenerType, const OUString& AddListenerParam,
242 const OUString& EventMethod)
243 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException );
244 virtual void SAL_CALL removeListener(const Reference< XInterface >& xObject,
245 const OUString& ListenerType, const OUString& AddListenerParam,
246 const Reference< XEventListener >& aToRemoveListener)
247 throw( IllegalArgumentException, IntrospectionException, RuntimeException );
249 // XEventAttacher2
250 virtual Sequence< Reference<XEventListener> > SAL_CALL attachMultipleEventListeners(
251 const Reference<XInterface>& xObject, const Sequence<com::sun::star::script::EventListener>& aListeners )
252 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException );
254 // used by FilterAllListener_Impl
255 Reference< XTypeConverter > getConverter() throw( Exception );
257 friend class FilterAllListenerImpl;
259 private:
260 Reference<XEventListener> attachListenerForTarget(
261 const Reference<XIntrospectionAccess>& xAccess,
262 const Reference<XInvocationAdapterFactory>& xInvocationAdapterFactory,
263 const Reference<XAllListener>& xAllListener,
264 const Any& aObject,
265 const Any& aHelper,
266 const OUString& aListenerType,
267 const OUString& aAddListenerParam );
269 Sequence< Reference<XEventListener> > attachListeners(
270 const Reference<XInterface>& xObject,
271 const Sequence< Reference<XAllListener> >& AllListeners,
272 const Sequence<com::sun::star::script::EventListener>& aListeners );
274 private:
275 Mutex m_aMutex;
276 Reference< XMultiServiceFactory > m_xSMgr;
278 // Save Services
279 Reference< XIntrospection > m_xIntrospection;
280 Reference< XIdlReflection > m_xReflection;
281 Reference< XTypeConverter > m_xConverter;
282 Reference< XInvocationAdapterFactory > m_xInvocationAdapterFactory;
284 // needed services
285 Reference< XIntrospection > getIntrospection() throw( Exception );
286 Reference< XIdlReflection > getReflection() throw( Exception );
287 Reference< XInvocationAdapterFactory > getInvocationAdapterService() throw( Exception );
291 //*************************************************************************
292 EventAttacherImpl::EventAttacherImpl( const Reference< XMultiServiceFactory >& rSMgr )
293 : m_xSMgr( rSMgr )
297 //*************************************************************************
298 EventAttacherImpl::~EventAttacherImpl()
302 //*************************************************************************
303 Reference< XInterface > SAL_CALL EventAttacherImpl_CreateInstance( const Reference< XMultiServiceFactory >& rSMgr ) throw( Exception )
305 Reference< XInterface > xRet;
306 XEventAttacher *pEventAttacher = (XEventAttacher*) new EventAttacherImpl(rSMgr);
308 if (pEventAttacher)
310 xRet = Reference<XInterface>::query(pEventAttacher);
313 return xRet;
316 //*************************************************************************
317 OUString SAL_CALL EventAttacherImpl::getImplementationName( )
318 throw(RuntimeException)
320 return OUString( IMPLNAME );
323 //*************************************************************************
324 sal_Bool SAL_CALL EventAttacherImpl::supportsService( const OUString& ServiceName )
325 throw(RuntimeException)
327 Sequence< OUString > aSNL = getSupportedServiceNames();
328 const OUString * pArray = aSNL.getArray();
329 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
330 if( pArray[i] == ServiceName )
331 return sal_True;
332 return sal_False;
335 //*************************************************************************
336 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames( )
337 throw(RuntimeException)
339 return getSupportedServiceNames_Static();
342 //*************************************************************************
343 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames_Static( )
345 OUString aStr( SERVICENAME );
346 return Sequence< OUString >( &aStr, 1 );
349 //*************************************************************************
350 void SAL_CALL EventAttacherImpl::initialize(const Sequence< Any >& Arguments) throw( Exception, RuntimeException )
352 // get services from the argument list
353 const Any * pArray = Arguments.getConstArray();
354 for( sal_Int32 i = 0; i < Arguments.getLength(); i++ )
356 if( pArray[i].getValueType().getTypeClass() != TypeClass_INTERFACE )
357 throw IllegalArgumentException();
359 // InvocationAdapter service ?
360 Reference< XInvocationAdapterFactory > xALAS;
361 pArray[i] >>= xALAS;
362 if( xALAS.is() )
364 Guard< Mutex > aGuard( m_aMutex );
365 m_xInvocationAdapterFactory = xALAS;
367 // Introspection service ?
368 Reference< XIntrospection > xI;
369 pArray[i] >>= xI;
370 if( xI.is() )
372 Guard< Mutex > aGuard( m_aMutex );
373 m_xIntrospection = xI;
375 // Reflection service ?
376 Reference< XIdlReflection > xIdlR;
377 pArray[i] >>= xIdlR;
378 if( xIdlR.is() )
380 Guard< Mutex > aGuard( m_aMutex );
381 m_xReflection = xIdlR;
383 // Converter Service ?
384 Reference< XTypeConverter > xC;
385 pArray[i] >>= xC;
386 if( xC.is() )
388 Guard< Mutex > aGuard( m_aMutex );
389 m_xConverter = xC;
392 // no right interface
393 if( !xALAS.is() && !xI.is() && !xIdlR.is() && !xC.is() )
394 throw IllegalArgumentException();
398 //*************************************************************************
399 //*** Private helper methods ***
400 Reference< XIntrospection > EventAttacherImpl::getIntrospection() throw( Exception )
402 Guard< Mutex > aGuard( m_aMutex );
403 if( !m_xIntrospection.is() )
405 Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString("com.sun.star.beans.Introspection") ) );
406 m_xIntrospection = Reference< XIntrospection >( xIFace, UNO_QUERY );
408 return m_xIntrospection;
411 //*************************************************************************
412 //*** Private helper methods ***
413 Reference< XIdlReflection > EventAttacherImpl::getReflection() throw( Exception )
415 Guard< Mutex > aGuard( m_aMutex );
416 if( !m_xReflection.is() )
418 Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString("com.sun.star.reflection.CoreReflection") ) );
419 m_xReflection = Reference< XIdlReflection >( xIFace, UNO_QUERY);
421 return m_xReflection;
424 //*************************************************************************
425 //*** Private helper methods ***
426 Reference< XInvocationAdapterFactory > EventAttacherImpl::getInvocationAdapterService() throw( Exception )
428 Guard< Mutex > aGuard( m_aMutex );
429 if( !m_xInvocationAdapterFactory.is() )
431 Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString("com.sun.star.script.InvocationAdapterFactory") ) );
432 m_xInvocationAdapterFactory = Reference< XInvocationAdapterFactory >( xIFace, UNO_QUERY );
434 return m_xInvocationAdapterFactory;
438 //*************************************************************************
439 //*** Private helper methods ***
440 Reference< XTypeConverter > EventAttacherImpl::getConverter() throw( Exception )
442 Guard< Mutex > aGuard( m_aMutex );
443 if( !m_xConverter.is() )
445 Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString("com.sun.star.script.Converter") ) );
446 m_xConverter = Reference< XTypeConverter >( xIFace, UNO_QUERY );
448 return m_xConverter;
451 //------------------------------------------------------------------------
452 //------------------------------------------------------------------------
453 //------------------------------------------------------------------------
454 // Implementation of an EventAttacher-related AllListeners, which brings
455 // a few Events to a general AllListener
456 class FilterAllListenerImpl : public WeakImplHelper1< XAllListener >
458 public:
459 FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
460 const Reference< XAllListener >& AllListener_ );
462 // XAllListener
463 virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException );
464 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException );
466 // XEventListener
467 virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
469 private:
470 // convert
471 void convertToEventReturn( Any & rRet, const Type& rRetType )
472 throw( CannotConvertException );
474 EventAttacherImpl * m_pEA;
475 Reference< XInterface > m_xEAHold;
476 OUString m_EventMethod;
477 Reference< XAllListener > m_AllListener;
480 //*************************************************************************
481 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
482 const Reference< XAllListener >& AllListener_ )
483 : m_pEA( pEA_ )
484 , m_xEAHold( *pEA_ )
485 , m_EventMethod( EventMethod_ )
486 , m_AllListener( AllListener_ )
490 //*************************************************************************
491 void SAL_CALL FilterAllListenerImpl::firing(const AllEventObject& Event)
492 throw( RuntimeException )
494 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
495 m_AllListener->firing( Event );
498 //*************************************************************************
499 // Convert to the standard event return
500 void FilterAllListenerImpl::convertToEventReturn( Any & rRet, const Type & rRetType )
501 throw( CannotConvertException )
503 // no return value? Set to the specified values
504 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
506 switch( rRetType.getTypeClass() )
508 case TypeClass_INTERFACE:
510 rRet <<= Reference< XInterface >();
512 break;
514 case TypeClass_BOOLEAN:
515 rRet <<= sal_True;
516 break;
518 case TypeClass_STRING:
519 rRet <<= OUString();
520 break;
522 case TypeClass_FLOAT: rRet <<= float(0); break;
523 case TypeClass_DOUBLE: rRet <<= double(0.0); break;
524 case TypeClass_BYTE: rRet <<= sal_uInt8( 0 ); break;
525 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
526 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
527 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
528 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
529 default:
530 break;
533 else if( !rRet.getValueType().equals( rRetType ) )
535 Reference< XTypeConverter > xConverter = m_pEA->getConverter();
536 if( xConverter.is() )
537 rRet = xConverter->convertTo( rRet, rRetType );
538 else
539 throw CannotConvertException(); // TODO TypeConversionException
543 //*************************************************************************
544 Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event )
545 throw( InvocationTargetException, RuntimeException )
547 Any aRet;
549 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
550 aRet = m_AllListener->approveFiring( Event );
551 else
553 // Convert to the standard event return
556 Reference< XIdlClass > xListenerType = m_pEA->getReflection()->
557 forName( Event.ListenerType.getTypeName() );
558 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
559 if( xMeth.is() )
561 Reference< XIdlClass > xRetType = xMeth->getReturnType();
562 Type aRetType( xRetType->getTypeClass(), xRetType->getName() );
563 convertToEventReturn( aRet, aRetType );
566 catch( const CannotConvertException& e )
568 throw InvocationTargetException( OUString(), Reference< XInterface >(), Any(&e, ::getCppuType( (CannotConvertException*)0)) );
571 return aRet;
574 //*************************************************************************
575 void FilterAllListenerImpl::disposing(const EventObject& )
576 throw( RuntimeException )
578 // TODO: ???
582 //*************************************************************************
583 Reference< XEventListener > EventAttacherImpl::attachListener
585 const Reference< XInterface >& xObject,
586 const Reference< XAllListener >& AllListener,
587 const Any& Helper,
588 const OUString& ListenerType,
589 const OUString& AddListenerParam
591 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException )
593 if( !xObject.is() || !AllListener.is() )
594 throw IllegalArgumentException();
596 Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = getInvocationAdapterService();
597 if( !xInvocationAdapterFactory.is() )
598 throw ServiceNotRegisteredException();
600 Reference< XIdlReflection > xReflection = getReflection();
601 if( !xReflection.is() )
602 throw ServiceNotRegisteredException();
604 // Sign in, Call the fitting addListener method
605 // First Introspection, as the Methods can be analyzed in the same way
606 // For better perfomance it is implemented here again or make the Impl-Method
607 // of the Introspection configurable for this purpose.
608 Reference< XIntrospection > xIntrospection = getIntrospection();
609 if( !xIntrospection.is() )
610 return Reference<XEventListener>();
612 // Inspect Introspection
613 Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) );
615 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
616 if( !xAccess.is() )
617 return Reference<XEventListener>();
619 return attachListenerForTarget(
620 xAccess, xInvocationAdapterFactory, AllListener, aObjAny, Helper,
621 ListenerType, AddListenerParam);
624 Reference<XEventListener> EventAttacherImpl::attachListenerForTarget(
625 const Reference<XIntrospectionAccess>& xAccess,
626 const Reference<XInvocationAdapterFactory>& xInvocationAdapterFactory,
627 const Reference<XAllListener>& xAllListener,
628 const Any& aObject,
629 const Any& aHelper,
630 const OUString& aListenerType,
631 const OUString& aAddListenerParam)
633 Reference< XEventListener > xRet = NULL;
635 // Construct the name of the addListener-Method.
636 sal_Int32 nIndex = aListenerType.lastIndexOf('.');
637 // set index to the interface name without package name
638 if( nIndex == -1 )
639 // not found
640 nIndex = 0;
641 else
642 nIndex++;
644 OUString aListenerName = (aListenerType[nIndex] == 'X') ? aListenerType.copy(nIndex+1) : aListenerType;
645 OUString aAddListenerName = OUString("add") + aListenerName;
647 // Send Methods to the correct addListener-Method
648 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
649 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
650 for (sal_Int32 i = 0, n = aMethodSeq.getLength(); i < n ; ++i)
652 const Reference< XIdlMethod >& rxMethod = pMethods[i];
654 // Is it the correct method?
655 OUString aMethName = rxMethod->getName();
657 if (aAddListenerName != aMethName)
658 continue;
660 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
661 sal_uInt32 nParamCount = params.getLength();
663 Reference< XIdlClass > xListenerType;
664 if( nParamCount == 1 )
665 xListenerType = params.getConstArray()[0];
666 else if( nParamCount == 2 )
667 xListenerType = params.getConstArray()[1];
669 // Request Adapter for the actual Listener type
670 Reference< XInterface > xAdapter = createAllListenerAdapter(
671 xInvocationAdapterFactory, xListenerType, xAllListener, aHelper );
673 if( !xAdapter.is() )
674 throw CannotCreateAdapterException();
675 xRet = Reference< XEventListener >( xAdapter, UNO_QUERY );
677 // Just the Listener as parameter?
678 if( nParamCount == 1 )
680 Sequence< Any > args( 1 );
681 args.getArray()[0] <<= xAdapter;
684 rxMethod->invoke( aObject, args );
686 catch( const InvocationTargetException& )
688 throw IntrospectionException();
691 // Else, pass the other parameter now
692 else if( nParamCount == 2 )
694 Sequence< Any > args( 2 );
695 Any* pAnys = args.getArray();
697 // Check the type of the 1st parameter
698 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
699 if( xParamClass->getTypeClass() == TypeClass_STRING )
701 pAnys[0] <<= aAddListenerParam;
704 // 2nd Parameter == Listener? TODO: Test!
705 pAnys[1] <<= xAdapter;
707 // TODO: Convert String -> ?
708 // else
711 rxMethod->invoke( aObject, args );
713 catch( const InvocationTargetException& )
715 throw IntrospectionException();
718 break;
719 // else...
720 // Anything else is not supported
723 return xRet;
726 Sequence< Reference<XEventListener> > EventAttacherImpl::attachListeners(
727 const Reference<XInterface>& xObject,
728 const Sequence< Reference<XAllListener> >& AllListeners,
729 const Sequence<com::sun::star::script::EventListener>& aListeners )
731 sal_Int32 nCount = aListeners.getLength();
732 if (nCount != AllListeners.getLength())
733 // This is a prerequisite!
734 throw RuntimeException();
736 if (!xObject.is())
737 throw IllegalArgumentException();
739 Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = getInvocationAdapterService();
740 if( !xInvocationAdapterFactory.is() )
741 throw ServiceNotRegisteredException();
743 Reference< XIdlReflection > xReflection = getReflection();
744 if( !xReflection.is() )
745 throw ServiceNotRegisteredException();
747 // Sign in, Call the fitting addListener method
748 // First Introspection, as the Methods can be analyzed in the same way
749 // For better perfomance it is implemented here again or make the Impl-Method
750 // of the Introspection configurable for this purpose.
751 Reference< XIntrospection > xIntrospection = getIntrospection();
752 if( !xIntrospection.is() )
753 return Sequence< Reference<XEventListener> >();
755 // Inspect Introspection
756 Any aObjAny( &xObject, ::getCppuType(static_cast<const Reference<XInterface>*>(0)) );
758 Reference<XIntrospectionAccess> xAccess = xIntrospection->inspect(aObjAny);
759 if (!xAccess.is())
760 return Sequence< Reference<XEventListener> >();
762 Sequence< Reference<XEventListener> > aRet(nCount);
763 Reference<XEventListener>* pArray = aRet.getArray();
765 for (sal_Int32 i = 0; i < nCount; ++i)
767 pArray[i] = attachListenerForTarget(
768 xAccess, xInvocationAdapterFactory, AllListeners[ i ],
769 aObjAny, aListeners[i].Helper, aListeners[i].ListenerType, aListeners[i].AddListenerParam);
772 return aRet;
775 // XEventAttacher
776 Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
778 const Reference< XInterface >& xObject,
779 const Reference< XAllListener >& AllListener,
780 const Any& Helper,
781 const OUString& ListenerType,
782 const OUString& AddListenerParam,
783 const OUString& EventMethod
785 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException )
787 // Subscribe FilterListener
788 Reference< XAllListener > aFilterListener = (XAllListener*)
789 new FilterAllListenerImpl( this, EventMethod, AllListener );
790 return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam);
793 // XEventAttacher
794 void EventAttacherImpl::removeListener
796 const Reference< XInterface >& xObject,
797 const OUString& ListenerType,
798 const OUString& AddListenerParam,
799 const Reference< XEventListener >& aToRemoveListener
801 throw( IllegalArgumentException, IntrospectionException, RuntimeException )
803 if( !xObject.is() || !aToRemoveListener.is() )
804 throw IllegalArgumentException();
806 Reference< XIdlReflection > xReflection = getReflection();
807 if( !xReflection.is() )
808 throw IntrospectionException();
810 // Sign off, Call the fitting removeListener method
811 // First Introspection, as the Methods can be analyzed in the same way
812 // For better perfomance it is implemented here again or make the Impl-Method
813 // of the Introspection configurable for this purpose.
814 Reference< XIntrospection > xIntrospection = getIntrospection();
815 if( !xIntrospection.is() )
816 throw IntrospectionException();
818 //Inspect Introspection
819 Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) );
820 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
821 if( !xAccess.is() )
822 throw IntrospectionException();
824 // Create name of the removeListener-Method
825 OUString aRemoveListenerName;
826 OUString aListenerName( ListenerType );
827 sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
828 // set index to the interface name without package name
829 if( nIndex == -1 )
830 // not found
831 nIndex = 0;
832 else
833 nIndex++;
834 if( aListenerName[nIndex] == 'X' )
835 // erase X from the interface name
836 aListenerName = aListenerName.copy( nIndex +1 );
837 aRemoveListenerName = OUString( "remove" ) + aListenerName;
839 // Search methods for the correct removeListener method
840 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
841 sal_uInt32 i, nLen = aMethodSeq.getLength();
842 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
843 for( i = 0 ; i < nLen ; i++ )
845 // Call Methode
846 const Reference< XIdlMethod >& rxMethod = pMethods[i];
848 // Is it the right method?
849 if( aRemoveListenerName == rxMethod->getName() )
851 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
852 sal_uInt32 nParamCount = params.getLength();
854 // Just the Listener as parameter?
855 if( nParamCount == 1 )
857 Sequence< Any > args( 1 );
858 args.getArray()[0] <<= aToRemoveListener;
861 rxMethod->invoke( aObjAny, args );
863 catch( const InvocationTargetException& )
865 throw IntrospectionException();
868 // Else pass the other parameter
869 else if( nParamCount == 2 )
871 Sequence< Any > args( 2 );
872 Any* pAnys = args.getArray();
874 // Check the type of the 1st parameter
875 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
876 if( xParamClass->getTypeClass() == TypeClass_STRING )
877 pAnys[0] <<= AddListenerParam;
879 // 2nd parameter == Listener? TODO: Test!
880 pAnys[1] <<= aToRemoveListener;
882 // TODO: Convert String -> ?
883 // else
886 rxMethod->invoke( aObjAny, args );
888 catch( const InvocationTargetException& )
890 throw IntrospectionException();
893 break;
898 Sequence< Reference<XEventListener> > EventAttacherImpl::attachMultipleEventListeners(
899 const Reference<XInterface>& xObject, const Sequence<com::sun::star::script::EventListener>& aListeners )
900 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException )
902 sal_Int32 nCount = aListeners.getLength();
903 Sequence< Reference<XAllListener> > aFilterListeners(nCount);
904 for (sal_Int32 i = 0; i < nCount; ++i)
906 aFilterListeners[i] = (XAllListener*)
907 new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener);
910 return attachListeners(xObject, aFilterListeners, aListeners);
915 extern "C"
917 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
918 const sal_Char * pImplName, void * pServiceManager, void * )
920 void * pRet = 0;
922 if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
924 Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory(
925 reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
926 OUString( IMPLNAME ),
927 ::comp_EventAttacher::EventAttacherImpl_CreateInstance,
928 ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) );
930 if (xFactory.is())
932 xFactory->acquire();
933 pRet = xFactory.get();
937 return pRet;
943 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */