Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / eventattacher / source / eventattacher.cxx
blobe6c97bd21aebe804e6163713a3318e4cfc2fe8f7
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/Introspection.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/XInvocationAdapterFactory.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>
42 using namespace com::sun::star::uno;
43 using namespace com::sun::star::registry;
44 using namespace com::sun::star::lang;
45 using namespace com::sun::star::beans;
46 using namespace com::sun::star::script;
47 using namespace com::sun::star::reflection;
48 using namespace cppu;
49 using namespace osl;
51 using ::rtl::OUString;
54 #define SERVICENAME "com.sun.star.script.EventAttacher"
55 #define IMPLNAME "com.sun.star.comp.EventAttacher"
57 namespace comp_EventAttacher {
59 //*************************************************************************
60 // class InvocationToAllListenerMapper
61 // helper class to map XInvocation to XAllListener
62 //*************************************************************************
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(void) throw( RuntimeException );
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 );
73 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value)
74 throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException );
75 virtual Any SAL_CALL getValue(const OUString& PropertyName) throw( UnknownPropertyException, RuntimeException );
76 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException );
77 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException );
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< XInvocationAdapterFactory >& 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 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, aListenerType );
104 return xAdapter;
108 //--------------------------------------------------------------------------------------------------
109 // InvocationToAllListenerMapper
110 InvocationToAllListenerMapper::InvocationToAllListenerMapper
111 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
112 : m_xAllListener( AllListener )
113 , m_xListenerType( ListenerType )
114 , m_Helper( Helper )
118 //*************************************************************************
119 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void)
120 throw( RuntimeException )
122 return Reference< XIntrospectionAccess >();
125 //*************************************************************************
126 Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
127 Sequence< sal_Int16 >& , Sequence< Any >& )
128 throw( IllegalArgumentException, CannotConvertException,
129 InvocationTargetException, RuntimeException )
131 Any aRet;
133 // Check if to firing or approveFiring has to be called
134 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
135 sal_Bool bApproveFiring = sal_False;
136 if( !xMethod.is() )
137 return aRet;
138 Reference< XIdlClass > xReturnType = xMethod->getReturnType();
139 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
140 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
141 aExceptionSeq.getLength() > 0 )
143 bApproveFiring = sal_True;
145 else
147 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
148 sal_uInt32 nParamCount = aParamSeq.getLength();
149 if( nParamCount > 1 )
151 const ParamInfo* pInfos = aParamSeq.getConstArray();
152 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
154 if( pInfos[ i ].aMode != ParamMode_IN )
156 bApproveFiring = sal_True;
157 break;
163 AllEventObject aAllEvent;
164 aAllEvent.Source = (OWeakObject*) this;
165 aAllEvent.Helper = m_Helper;
166 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName());
167 aAllEvent.MethodName = FunctionName;
168 aAllEvent.Arguments = Params;
169 if( bApproveFiring )
170 aRet = m_xAllListener->approveFiring( aAllEvent );
171 else
172 m_xAllListener->firing( aAllEvent );
173 return aRet;
176 //*************************************************************************
177 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& , const Any& )
178 throw( UnknownPropertyException, CannotConvertException,
179 InvocationTargetException, RuntimeException )
183 //*************************************************************************
184 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& )
185 throw( UnknownPropertyException, RuntimeException )
187 return Any();
190 //*************************************************************************
191 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
192 throw( RuntimeException )
194 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
195 return xMethod.is();
198 //*************************************************************************
199 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
200 throw( RuntimeException )
202 Reference< XIdlField > xField = m_xListenerType->getField( Name );
203 return xField.is();
206 //*************************************************************************
207 // class EventAttacherImpl
208 // represents an implementation of the EventAttacher service
209 //*************************************************************************
210 class EventAttacherImpl : public WeakImplHelper3 < XEventAttacher2, XInitialization, XServiceInfo >
212 public:
213 EventAttacherImpl( const Reference< XMultiServiceFactory >& );
214 ~EventAttacherImpl();
216 // XServiceInfo
217 virtual OUString SAL_CALL getImplementationName( ) throw(RuntimeException);
218 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
219 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(RuntimeException);
220 static OUString SAL_CALL getImplementationName_Static( );
221 static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static( );
223 // XInitialization
224 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments )
225 throw( Exception, RuntimeException);
227 // Methoden von XEventAttacher
228 virtual Reference< XEventListener > SAL_CALL attachListener(const Reference< XInterface >& xObject,
229 const Reference< XAllListener >& AllListener, const Any& Helper,
230 const OUString& ListenerType, const OUString& AddListenerParam)
231 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException );
232 virtual Reference< XEventListener > SAL_CALL attachSingleEventListener(const Reference< XInterface >& xObject,
233 const Reference< XAllListener >& AllListener, const Any& Helper,
234 const OUString& ListenerType, const OUString& AddListenerParam,
235 const OUString& EventMethod)
236 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException );
237 virtual void SAL_CALL removeListener(const Reference< XInterface >& xObject,
238 const OUString& ListenerType, const OUString& AddListenerParam,
239 const Reference< XEventListener >& aToRemoveListener)
240 throw( IllegalArgumentException, IntrospectionException, RuntimeException );
242 // XEventAttacher2
243 virtual Sequence< Reference<XEventListener> > SAL_CALL attachMultipleEventListeners(
244 const Reference<XInterface>& xObject, const Sequence<com::sun::star::script::EventListener>& aListeners )
245 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException );
247 // used by FilterAllListener_Impl
248 Reference< XTypeConverter > getConverter() throw( Exception );
250 friend class FilterAllListenerImpl;
252 private:
253 Reference<XEventListener> attachListenerForTarget(
254 const Reference<XIntrospectionAccess>& xAccess,
255 const Reference<XInvocationAdapterFactory>& xInvocationAdapterFactory,
256 const Reference<XAllListener>& xAllListener,
257 const Any& aObject,
258 const Any& aHelper,
259 const OUString& aListenerType,
260 const OUString& aAddListenerParam );
262 Sequence< Reference<XEventListener> > attachListeners(
263 const Reference<XInterface>& xObject,
264 const Sequence< Reference<XAllListener> >& AllListeners,
265 const Sequence<com::sun::star::script::EventListener>& aListeners );
267 private:
268 Mutex m_aMutex;
269 Reference< XMultiServiceFactory > m_xSMgr;
271 // Save Services
272 Reference< XIntrospection > m_xIntrospection;
273 Reference< XIdlReflection > m_xReflection;
274 Reference< XTypeConverter > m_xConverter;
275 Reference< XInvocationAdapterFactory > m_xInvocationAdapterFactory;
277 // needed services
278 Reference< XIntrospection > getIntrospection() throw( Exception );
279 Reference< XIdlReflection > getReflection() throw( Exception );
280 Reference< XInvocationAdapterFactory > getInvocationAdapterService() throw( Exception );
284 //*************************************************************************
285 EventAttacherImpl::EventAttacherImpl( const Reference< XMultiServiceFactory >& rSMgr )
286 : m_xSMgr( rSMgr )
290 //*************************************************************************
291 EventAttacherImpl::~EventAttacherImpl()
295 //*************************************************************************
296 Reference< XInterface > SAL_CALL EventAttacherImpl_CreateInstance( const Reference< XMultiServiceFactory >& rSMgr ) throw( Exception )
298 Reference< XInterface > xRet;
299 XEventAttacher *pEventAttacher = (XEventAttacher*) new EventAttacherImpl(rSMgr);
301 if (pEventAttacher)
303 xRet = Reference<XInterface>::query(pEventAttacher);
306 return xRet;
309 //*************************************************************************
310 OUString SAL_CALL EventAttacherImpl::getImplementationName( )
311 throw(RuntimeException)
313 return OUString( IMPLNAME );
316 //*************************************************************************
317 sal_Bool SAL_CALL EventAttacherImpl::supportsService( const OUString& ServiceName )
318 throw(RuntimeException)
320 Sequence< OUString > aSNL = getSupportedServiceNames();
321 const OUString * pArray = aSNL.getArray();
322 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
323 if( pArray[i] == ServiceName )
324 return sal_True;
325 return sal_False;
328 //*************************************************************************
329 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames( )
330 throw(RuntimeException)
332 return getSupportedServiceNames_Static();
335 //*************************************************************************
336 Sequence<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames_Static( )
338 OUString aStr( SERVICENAME );
339 return Sequence< OUString >( &aStr, 1 );
342 //*************************************************************************
343 void SAL_CALL EventAttacherImpl::initialize(const Sequence< Any >& Arguments) throw( Exception, RuntimeException )
345 // get services from the argument list
346 const Any * pArray = Arguments.getConstArray();
347 for( sal_Int32 i = 0; i < Arguments.getLength(); i++ )
349 if( pArray[i].getValueType().getTypeClass() != TypeClass_INTERFACE )
350 throw IllegalArgumentException();
352 // InvocationAdapter service ?
353 Reference< XInvocationAdapterFactory > xALAS;
354 pArray[i] >>= xALAS;
355 if( xALAS.is() )
357 Guard< Mutex > aGuard( m_aMutex );
358 m_xInvocationAdapterFactory = xALAS;
360 // Introspection service ?
361 Reference< XIntrospection > xI;
362 pArray[i] >>= xI;
363 if( xI.is() )
365 Guard< Mutex > aGuard( m_aMutex );
366 m_xIntrospection = xI;
368 // Reflection service ?
369 Reference< XIdlReflection > xIdlR;
370 pArray[i] >>= xIdlR;
371 if( xIdlR.is() )
373 Guard< Mutex > aGuard( m_aMutex );
374 m_xReflection = xIdlR;
376 // Converter Service ?
377 Reference< XTypeConverter > xC;
378 pArray[i] >>= xC;
379 if( xC.is() )
381 Guard< Mutex > aGuard( m_aMutex );
382 m_xConverter = xC;
385 // no right interface
386 if( !xALAS.is() && !xI.is() && !xIdlR.is() && !xC.is() )
387 throw IllegalArgumentException();
391 //*************************************************************************
392 //*** Private helper methods ***
393 Reference< XIntrospection > EventAttacherImpl::getIntrospection() throw( Exception )
395 Guard< Mutex > aGuard( m_aMutex );
396 if( !m_xIntrospection.is() )
398 m_xIntrospection = Introspection::create( comphelper::getComponentContext(m_xSMgr) );
400 return m_xIntrospection;
403 //*************************************************************************
404 //*** Private helper methods ***
405 Reference< XIdlReflection > EventAttacherImpl::getReflection() throw( Exception )
407 Guard< Mutex > aGuard( m_aMutex );
408 if( !m_xReflection.is() )
410 m_xReflection = theCoreReflection::get(comphelper::getComponentContext(m_xSMgr));
412 return m_xReflection;
415 //*************************************************************************
416 //*** Private helper methods ***
417 Reference< XInvocationAdapterFactory > EventAttacherImpl::getInvocationAdapterService() throw( Exception )
419 Guard< Mutex > aGuard( m_aMutex );
420 if( !m_xInvocationAdapterFactory.is() )
422 Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString("com.sun.star.script.InvocationAdapterFactory") ) );
423 m_xInvocationAdapterFactory = Reference< XInvocationAdapterFactory >( xIFace, UNO_QUERY );
425 return m_xInvocationAdapterFactory;
429 //*************************************************************************
430 //*** Private helper methods ***
431 Reference< XTypeConverter > EventAttacherImpl::getConverter() throw( Exception )
433 Guard< Mutex > aGuard( m_aMutex );
434 if( !m_xConverter.is() )
436 m_xConverter = Converter::create(comphelper::getComponentContext(m_xSMgr));
438 return m_xConverter;
441 //------------------------------------------------------------------------
442 //------------------------------------------------------------------------
443 //------------------------------------------------------------------------
444 // Implementation of an EventAttacher-related AllListeners, which brings
445 // a few Events to a general AllListener
446 class FilterAllListenerImpl : public WeakImplHelper1< XAllListener >
448 public:
449 FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
450 const Reference< XAllListener >& AllListener_ );
452 // XAllListener
453 virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException );
454 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException );
456 // XEventListener
457 virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
459 private:
460 // convert
461 void convertToEventReturn( Any & rRet, const Type& rRetType )
462 throw( CannotConvertException );
464 EventAttacherImpl * m_pEA;
465 Reference< XInterface > m_xEAHold;
466 OUString m_EventMethod;
467 Reference< XAllListener > m_AllListener;
470 //*************************************************************************
471 FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_,
472 const Reference< XAllListener >& AllListener_ )
473 : m_pEA( pEA_ )
474 , m_xEAHold( *pEA_ )
475 , m_EventMethod( EventMethod_ )
476 , m_AllListener( AllListener_ )
480 //*************************************************************************
481 void SAL_CALL FilterAllListenerImpl::firing(const AllEventObject& Event)
482 throw( RuntimeException )
484 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
485 m_AllListener->firing( Event );
488 //*************************************************************************
489 // Convert to the standard event return
490 void FilterAllListenerImpl::convertToEventReturn( Any & rRet, const Type & rRetType )
491 throw( CannotConvertException )
493 // no return value? Set to the specified values
494 if( rRet.getValueType().getTypeClass() == TypeClass_VOID )
496 switch( rRetType.getTypeClass() )
498 case TypeClass_INTERFACE:
500 rRet <<= Reference< XInterface >();
502 break;
504 case TypeClass_BOOLEAN:
505 rRet <<= sal_True;
506 break;
508 case TypeClass_STRING:
509 rRet <<= OUString();
510 break;
512 case TypeClass_FLOAT: rRet <<= float(0); break;
513 case TypeClass_DOUBLE: rRet <<= double(0.0); break;
514 case TypeClass_BYTE: rRet <<= sal_uInt8( 0 ); break;
515 case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break;
516 case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break;
517 case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break;
518 case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break;
519 default:
520 break;
523 else if( !rRet.getValueType().equals( rRetType ) )
525 Reference< XTypeConverter > xConverter = m_pEA->getConverter();
526 if( xConverter.is() )
527 rRet = xConverter->convertTo( rRet, rRetType );
528 else
529 throw CannotConvertException(); // TODO TypeConversionException
533 //*************************************************************************
534 Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event )
535 throw( InvocationTargetException, RuntimeException )
537 Any aRet;
539 if( Event.MethodName == m_EventMethod && m_AllListener.is() )
540 aRet = m_AllListener->approveFiring( Event );
541 else
543 // Convert to the standard event return
546 Reference< XIdlClass > xListenerType = m_pEA->getReflection()->
547 forName( Event.ListenerType.getTypeName() );
548 Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName );
549 if( xMeth.is() )
551 Reference< XIdlClass > xRetType = xMeth->getReturnType();
552 Type aRetType( xRetType->getTypeClass(), xRetType->getName() );
553 convertToEventReturn( aRet, aRetType );
556 catch( const CannotConvertException& e )
558 throw InvocationTargetException( OUString(), Reference< XInterface >(), Any(&e, ::getCppuType( (CannotConvertException*)0)) );
561 return aRet;
564 //*************************************************************************
565 void FilterAllListenerImpl::disposing(const EventObject& )
566 throw( RuntimeException )
568 // TODO: ???
572 //*************************************************************************
573 Reference< XEventListener > EventAttacherImpl::attachListener
575 const Reference< XInterface >& xObject,
576 const Reference< XAllListener >& AllListener,
577 const Any& Helper,
578 const OUString& ListenerType,
579 const OUString& AddListenerParam
581 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException )
583 if( !xObject.is() || !AllListener.is() )
584 throw IllegalArgumentException();
586 Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = getInvocationAdapterService();
587 if( !xInvocationAdapterFactory.is() )
588 throw ServiceNotRegisteredException();
590 Reference< XIdlReflection > xReflection = getReflection();
591 if( !xReflection.is() )
592 throw ServiceNotRegisteredException();
594 // Sign in, Call the fitting addListener method
595 // First Introspection, as the Methods can be analyzed in the same way
596 // For better perfomance it is implemented here again or make the Impl-Method
597 // of the Introspection configurable for this purpose.
598 Reference< XIntrospection > xIntrospection = getIntrospection();
599 if( !xIntrospection.is() )
600 return Reference<XEventListener>();
602 // Inspect Introspection
603 Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) );
605 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
606 if( !xAccess.is() )
607 return Reference<XEventListener>();
609 return attachListenerForTarget(
610 xAccess, xInvocationAdapterFactory, AllListener, aObjAny, Helper,
611 ListenerType, AddListenerParam);
614 Reference<XEventListener> EventAttacherImpl::attachListenerForTarget(
615 const Reference<XIntrospectionAccess>& xAccess,
616 const Reference<XInvocationAdapterFactory>& xInvocationAdapterFactory,
617 const Reference<XAllListener>& xAllListener,
618 const Any& aObject,
619 const Any& aHelper,
620 const OUString& aListenerType,
621 const OUString& aAddListenerParam)
623 Reference< XEventListener > xRet = NULL;
625 // Construct the name of the addListener-Method.
626 sal_Int32 nIndex = aListenerType.lastIndexOf('.');
627 // set index to the interface name without package name
628 if( nIndex == -1 )
629 // not found
630 nIndex = 0;
631 else
632 nIndex++;
634 OUString aListenerName = (aListenerType[nIndex] == 'X') ? aListenerType.copy(nIndex+1) : aListenerType;
635 OUString aAddListenerName = OUString("add") + aListenerName;
637 // Send Methods to the correct addListener-Method
638 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
639 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
640 for (sal_Int32 i = 0, n = aMethodSeq.getLength(); i < n ; ++i)
642 const Reference< XIdlMethod >& rxMethod = pMethods[i];
644 // Is it the correct method?
645 OUString aMethName = rxMethod->getName();
647 if (aAddListenerName != aMethName)
648 continue;
650 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
651 sal_uInt32 nParamCount = params.getLength();
653 Reference< XIdlClass > xListenerType;
654 if( nParamCount == 1 )
655 xListenerType = params.getConstArray()[0];
656 else if( nParamCount == 2 )
657 xListenerType = params.getConstArray()[1];
659 // Request Adapter for the actual Listener type
660 Reference< XInterface > xAdapter = createAllListenerAdapter(
661 xInvocationAdapterFactory, xListenerType, xAllListener, aHelper );
663 if( !xAdapter.is() )
664 throw CannotCreateAdapterException();
665 xRet = Reference< XEventListener >( xAdapter, UNO_QUERY );
667 // Just the Listener as parameter?
668 if( nParamCount == 1 )
670 Sequence< Any > args( 1 );
671 args.getArray()[0] <<= xAdapter;
674 rxMethod->invoke( aObject, args );
676 catch( const InvocationTargetException& )
678 throw IntrospectionException();
681 // Else, pass the other parameter now
682 else if( nParamCount == 2 )
684 Sequence< Any > args( 2 );
685 Any* pAnys = args.getArray();
687 // Check the type of the 1st parameter
688 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
689 if( xParamClass->getTypeClass() == TypeClass_STRING )
691 pAnys[0] <<= aAddListenerParam;
694 // 2nd Parameter == Listener? TODO: Test!
695 pAnys[1] <<= xAdapter;
697 // TODO: Convert String -> ?
698 // else
701 rxMethod->invoke( aObject, args );
703 catch( const InvocationTargetException& )
705 throw IntrospectionException();
708 break;
709 // else...
710 // Anything else is not supported
713 return xRet;
716 Sequence< Reference<XEventListener> > EventAttacherImpl::attachListeners(
717 const Reference<XInterface>& xObject,
718 const Sequence< Reference<XAllListener> >& AllListeners,
719 const Sequence<com::sun::star::script::EventListener>& aListeners )
721 sal_Int32 nCount = aListeners.getLength();
722 if (nCount != AllListeners.getLength())
723 // This is a prerequisite!
724 throw RuntimeException();
726 if (!xObject.is())
727 throw IllegalArgumentException();
729 Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = getInvocationAdapterService();
730 if( !xInvocationAdapterFactory.is() )
731 throw ServiceNotRegisteredException();
733 Reference< XIdlReflection > xReflection = getReflection();
734 if( !xReflection.is() )
735 throw ServiceNotRegisteredException();
737 // Sign in, Call the fitting addListener method
738 // First Introspection, as the Methods can be analyzed in the same way
739 // For better perfomance it is implemented here again or make the Impl-Method
740 // of the Introspection configurable for this purpose.
741 Reference< XIntrospection > xIntrospection = getIntrospection();
742 if( !xIntrospection.is() )
743 return Sequence< Reference<XEventListener> >();
745 // Inspect Introspection
746 Any aObjAny( &xObject, ::getCppuType(static_cast<const Reference<XInterface>*>(0)) );
748 Reference<XIntrospectionAccess> xAccess = xIntrospection->inspect(aObjAny);
749 if (!xAccess.is())
750 return Sequence< Reference<XEventListener> >();
752 Sequence< Reference<XEventListener> > aRet(nCount);
753 Reference<XEventListener>* pArray = aRet.getArray();
755 for (sal_Int32 i = 0; i < nCount; ++i)
757 pArray[i] = attachListenerForTarget(
758 xAccess, xInvocationAdapterFactory, AllListeners[ i ],
759 aObjAny, aListeners[i].Helper, aListeners[i].ListenerType, aListeners[i].AddListenerParam);
762 return aRet;
765 // XEventAttacher
766 Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
768 const Reference< XInterface >& xObject,
769 const Reference< XAllListener >& AllListener,
770 const Any& Helper,
771 const OUString& ListenerType,
772 const OUString& AddListenerParam,
773 const OUString& EventMethod
775 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException )
777 // Subscribe FilterListener
778 Reference< XAllListener > aFilterListener = (XAllListener*)
779 new FilterAllListenerImpl( this, EventMethod, AllListener );
780 return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam);
783 // XEventAttacher
784 void EventAttacherImpl::removeListener
786 const Reference< XInterface >& xObject,
787 const OUString& ListenerType,
788 const OUString& AddListenerParam,
789 const Reference< XEventListener >& aToRemoveListener
791 throw( IllegalArgumentException, IntrospectionException, RuntimeException )
793 if( !xObject.is() || !aToRemoveListener.is() )
794 throw IllegalArgumentException();
796 Reference< XIdlReflection > xReflection = getReflection();
797 if( !xReflection.is() )
798 throw IntrospectionException();
800 // Sign off, Call the fitting removeListener method
801 // First Introspection, as the Methods can be analyzed in the same way
802 // For better perfomance it is implemented here again or make the Impl-Method
803 // of the Introspection configurable for this purpose.
804 Reference< XIntrospection > xIntrospection = getIntrospection();
805 if( !xIntrospection.is() )
806 throw IntrospectionException();
808 //Inspect Introspection
809 Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) );
810 Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
811 if( !xAccess.is() )
812 throw IntrospectionException();
814 // Create name of the removeListener-Method
815 OUString aRemoveListenerName;
816 OUString aListenerName( ListenerType );
817 sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
818 // set index to the interface name without package name
819 if( nIndex == -1 )
820 // not found
821 nIndex = 0;
822 else
823 nIndex++;
824 if( aListenerName[nIndex] == 'X' )
825 // erase X from the interface name
826 aListenerName = aListenerName.copy( nIndex +1 );
827 aRemoveListenerName = OUString( "remove" ) + aListenerName;
829 // Search methods for the correct removeListener method
830 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
831 sal_uInt32 i, nLen = aMethodSeq.getLength();
832 const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
833 for( i = 0 ; i < nLen ; i++ )
835 // Call Methode
836 const Reference< XIdlMethod >& rxMethod = pMethods[i];
838 // Is it the right method?
839 if( aRemoveListenerName == rxMethod->getName() )
841 Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
842 sal_uInt32 nParamCount = params.getLength();
844 // Just the Listener as parameter?
845 if( nParamCount == 1 )
847 Sequence< Any > args( 1 );
848 args.getArray()[0] <<= aToRemoveListener;
851 rxMethod->invoke( aObjAny, args );
853 catch( const InvocationTargetException& )
855 throw IntrospectionException();
858 // Else pass the other parameter
859 else if( nParamCount == 2 )
861 Sequence< Any > args( 2 );
862 Any* pAnys = args.getArray();
864 // Check the type of the 1st parameter
865 Reference< XIdlClass > xParamClass = params.getConstArray()[0];
866 if( xParamClass->getTypeClass() == TypeClass_STRING )
867 pAnys[0] <<= AddListenerParam;
869 // 2nd parameter == Listener? TODO: Test!
870 pAnys[1] <<= aToRemoveListener;
872 // TODO: Convert String -> ?
873 // else
876 rxMethod->invoke( aObjAny, args );
878 catch( const InvocationTargetException& )
880 throw IntrospectionException();
883 break;
888 Sequence< Reference<XEventListener> > EventAttacherImpl::attachMultipleEventListeners(
889 const Reference<XInterface>& xObject, const Sequence<com::sun::star::script::EventListener>& aListeners )
890 throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException )
892 sal_Int32 nCount = aListeners.getLength();
893 Sequence< Reference<XAllListener> > aFilterListeners(nCount);
894 for (sal_Int32 i = 0; i < nCount; ++i)
896 aFilterListeners[i] = (XAllListener*)
897 new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener);
900 return attachListeners(xObject, aFilterListeners, aListeners);
905 extern "C"
907 SAL_DLLPUBLIC_EXPORT void * SAL_CALL evtatt_component_getFactory(
908 const sal_Char * pImplName, void * pServiceManager, void * )
910 void * pRet = 0;
912 if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
914 Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory(
915 reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
916 OUString( IMPLNAME ),
917 ::comp_EventAttacher::EventAttacherImpl_CreateInstance,
918 ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) );
920 if (xFactory.is())
922 xFactory->acquire();
923 pRet = xFactory.get();
927 return pRet;
933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */