/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include // InvocationToAllListenerMapper #include #include #include #include #include using namespace com::sun::star::uno; using namespace com::sun::star::registry; using namespace com::sun::star::lang; using namespace com::sun::star::beans; using namespace com::sun::star::script; using namespace com::sun::star::reflection; using namespace cppu; using namespace osl; using ::rtl::OUString; #define SERVICENAME "com.sun.star.script.EventAttacher" #define IMPLNAME "com.sun.star.comp.EventAttacher" namespace comp_EventAttacher { //************************************************************************* // class InvocationToAllListenerMapper // helper class to map XInvocation to XAllListener //************************************************************************* class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation > { public: InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper ); // XInvocation virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void) throw( RuntimeException ); virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException ); virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException ); virtual Any SAL_CALL getValue(const OUString& PropertyName) throw( UnknownPropertyException, RuntimeException ); virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException ); virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException ); private: Reference< XIdlReflection > m_xCoreReflection; Reference< XAllListener > m_xAllListener; Reference< XIdlClass > m_xListenerType; Any m_Helper; }; // Function to replace AllListenerAdapterService::createAllListerAdapter Reference< XInterface > createAllListenerAdapter ( const Reference< XInvocationAdapterFactory >& xInvocationAdapterFactory, const Reference< XIdlClass >& xListenerType, const Reference< XAllListener >& xListener, const Any& Helper ) { Reference< XInterface > xAdapter; if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() ) { Reference< XInvocation > xInvocationToAllListenerMapper = (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper ); Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName()); xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, aListenerType ); } return xAdapter; } //-------------------------------------------------------------------------------------------------- // InvocationToAllListenerMapper InvocationToAllListenerMapper::InvocationToAllListenerMapper ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper ) : m_xAllListener( AllListener ) , m_xListenerType( ListenerType ) , m_Helper( Helper ) { } //************************************************************************* Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void) throw( RuntimeException ) { return Reference< XIntrospectionAccess >(); } //************************************************************************* Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& , Sequence< Any >& ) throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException ) { Any aRet; // Check if to firing or approveFiring has to be called Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName ); sal_Bool bApproveFiring = sal_False; if( !xMethod.is() ) return aRet; Reference< XIdlClass > xReturnType = xMethod->getReturnType(); Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes(); if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) || aExceptionSeq.getLength() > 0 ) { bApproveFiring = sal_True; } else { Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos(); sal_uInt32 nParamCount = aParamSeq.getLength(); if( nParamCount > 1 ) { const ParamInfo* pInfos = aParamSeq.getConstArray(); for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) { if( pInfos[ i ].aMode != ParamMode_IN ) { bApproveFiring = sal_True; break; } } } } AllEventObject aAllEvent; aAllEvent.Source = (OWeakObject*) this; aAllEvent.Helper = m_Helper; aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName()); aAllEvent.MethodName = FunctionName; aAllEvent.Arguments = Params; if( bApproveFiring ) aRet = m_xAllListener->approveFiring( aAllEvent ); else m_xAllListener->firing( aAllEvent ); return aRet; } //************************************************************************* void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& , const Any& ) throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException ) { } //************************************************************************* Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& ) throw( UnknownPropertyException, RuntimeException ) { return Any(); } //************************************************************************* sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name) throw( RuntimeException ) { Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name ); return xMethod.is(); } //************************************************************************* sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name) throw( RuntimeException ) { Reference< XIdlField > xField = m_xListenerType->getField( Name ); return xField.is(); } //************************************************************************* // class EventAttacherImpl // represents an implementation of the EventAttacher service //************************************************************************* class EventAttacherImpl : public WeakImplHelper3 < XEventAttacher2, XInitialization, XServiceInfo > { public: EventAttacherImpl( const Reference< XMultiServiceFactory >& ); ~EventAttacherImpl(); // XServiceInfo virtual OUString SAL_CALL getImplementationName( ) throw(RuntimeException); virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException); virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(RuntimeException); static OUString SAL_CALL getImplementationName_Static( ); static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static( ); // XInitialization virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw( Exception, RuntimeException); // Methoden von XEventAttacher virtual Reference< XEventListener > SAL_CALL attachListener(const Reference< XInterface >& xObject, const Reference< XAllListener >& AllListener, const Any& Helper, const OUString& ListenerType, const OUString& AddListenerParam) throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException ); virtual Reference< XEventListener > SAL_CALL attachSingleEventListener(const Reference< XInterface >& xObject, const Reference< XAllListener >& AllListener, const Any& Helper, const OUString& ListenerType, const OUString& AddListenerParam, const OUString& EventMethod) throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException ); virtual void SAL_CALL removeListener(const Reference< XInterface >& xObject, const OUString& ListenerType, const OUString& AddListenerParam, const Reference< XEventListener >& aToRemoveListener) throw( IllegalArgumentException, IntrospectionException, RuntimeException ); // XEventAttacher2 virtual Sequence< Reference > SAL_CALL attachMultipleEventListeners( const Reference& xObject, const Sequence& aListeners ) throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException ); // used by FilterAllListener_Impl Reference< XTypeConverter > getConverter() throw( Exception ); friend class FilterAllListenerImpl; private: Sequence< Reference > attachListeners( const Reference& xObject, const Sequence< Reference >& AllListeners, const Sequence& aListeners ); private: Mutex m_aMutex; Reference< XMultiServiceFactory > m_xSMgr; // Save Services Reference< XIntrospection > m_xIntrospection; Reference< XIdlReflection > m_xReflection; Reference< XTypeConverter > m_xConverter; Reference< XInvocationAdapterFactory > m_xInvocationAdapterFactory; // needed services Reference< XIntrospection > getIntrospection() throw( Exception ); Reference< XIdlReflection > getReflection() throw( Exception ); Reference< XInvocationAdapterFactory > getInvocationAdapterService() throw( Exception ); }; //************************************************************************* EventAttacherImpl::EventAttacherImpl( const Reference< XMultiServiceFactory >& rSMgr ) : m_xSMgr( rSMgr ) { } //************************************************************************* EventAttacherImpl::~EventAttacherImpl() { } //************************************************************************* Reference< XInterface > SAL_CALL EventAttacherImpl_CreateInstance( const Reference< XMultiServiceFactory >& rSMgr ) throw( Exception ) { Reference< XInterface > xRet; XEventAttacher *pEventAttacher = (XEventAttacher*) new EventAttacherImpl(rSMgr); if (pEventAttacher) { xRet = Reference::query(pEventAttacher); } return xRet; } //************************************************************************* OUString SAL_CALL EventAttacherImpl::getImplementationName( ) throw(RuntimeException) { return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); } //************************************************************************* sal_Bool SAL_CALL EventAttacherImpl::supportsService( const OUString& ServiceName ) throw(RuntimeException) { Sequence< OUString > aSNL = getSupportedServiceNames(); const OUString * pArray = aSNL.getArray(); for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) if( pArray[i] == ServiceName ) return sal_True; return sal_False; } //************************************************************************* Sequence SAL_CALL EventAttacherImpl::getSupportedServiceNames( ) throw(RuntimeException) { return getSupportedServiceNames_Static(); } //************************************************************************* Sequence SAL_CALL EventAttacherImpl::getSupportedServiceNames_Static( ) { OUString aStr( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME ) ); return Sequence< OUString >( &aStr, 1 ); } //************************************************************************* void SAL_CALL EventAttacherImpl::initialize(const Sequence< Any >& Arguments) throw( Exception, RuntimeException ) { // get services from the argument list const Any * pArray = Arguments.getConstArray(); for( sal_Int32 i = 0; i < Arguments.getLength(); i++ ) { if( pArray[i].getValueType().getTypeClass() != TypeClass_INTERFACE ) throw IllegalArgumentException(); // InvocationAdapter service ? Reference< XInvocationAdapterFactory > xALAS; pArray[i] >>= xALAS; if( xALAS.is() ) { Guard< Mutex > aGuard( m_aMutex ); m_xInvocationAdapterFactory = xALAS; } // Introspection service ? Reference< XIntrospection > xI; pArray[i] >>= xI; if( xI.is() ) { Guard< Mutex > aGuard( m_aMutex ); m_xIntrospection = xI; } // Reflection service ? Reference< XIdlReflection > xIdlR; pArray[i] >>= xIdlR; if( xIdlR.is() ) { Guard< Mutex > aGuard( m_aMutex ); m_xReflection = xIdlR; } // Converter Service ? Reference< XTypeConverter > xC; pArray[i] >>= xC; if( xC.is() ) { Guard< Mutex > aGuard( m_aMutex ); m_xConverter = xC; } // no right interface if( !xALAS.is() && !xI.is() && !xIdlR.is() && !xC.is() ) throw IllegalArgumentException(); } } //************************************************************************* //*** Private helper methods *** Reference< XIntrospection > EventAttacherImpl::getIntrospection() throw( Exception ) { Guard< Mutex > aGuard( m_aMutex ); if( !m_xIntrospection.is() ) { Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.Introspection")) ) ); m_xIntrospection = Reference< XIntrospection >( xIFace, UNO_QUERY ); } return m_xIntrospection; } //************************************************************************* //*** Private helper methods *** Reference< XIdlReflection > EventAttacherImpl::getReflection() throw( Exception ) { Guard< Mutex > aGuard( m_aMutex ); if( !m_xReflection.is() ) { Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.CoreReflection")) ) ); m_xReflection = Reference< XIdlReflection >( xIFace, UNO_QUERY); } return m_xReflection; } //************************************************************************* //*** Private helper methods *** Reference< XInvocationAdapterFactory > EventAttacherImpl::getInvocationAdapterService() throw( Exception ) { Guard< Mutex > aGuard( m_aMutex ); if( !m_xInvocationAdapterFactory.is() ) { Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.InvocationAdapterFactory")) ) ); m_xInvocationAdapterFactory = Reference< XInvocationAdapterFactory >( xIFace, UNO_QUERY ); } return m_xInvocationAdapterFactory; } //************************************************************************* //*** Private helper methods *** Reference< XTypeConverter > EventAttacherImpl::getConverter() throw( Exception ) { Guard< Mutex > aGuard( m_aMutex ); if( !m_xConverter.is() ) { Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter")) ) ); m_xConverter = Reference< XTypeConverter >( xIFace, UNO_QUERY ); } return m_xConverter; } //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ // Implementation of an EventAttacher-related AllListeners, which brings // a few Events to a general AllListener class FilterAllListenerImpl : public WeakImplHelper1< XAllListener > { public: FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_, const Reference< XAllListener >& AllListener_ ); // XAllListener virtual void SAL_CALL firing(const AllEventObject& Event) throw( RuntimeException ); virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw( InvocationTargetException, RuntimeException ); // XEventListener virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException ); private: // convert void convertToEventReturn( Any & rRet, const Type& rRetType ) throw( CannotConvertException ); EventAttacherImpl * m_pEA; Reference< XInterface > m_xEAHold; OUString m_EventMethod; Reference< XAllListener > m_AllListener; }; //************************************************************************* FilterAllListenerImpl::FilterAllListenerImpl( EventAttacherImpl * pEA_, const OUString& EventMethod_, const Reference< XAllListener >& AllListener_ ) : m_pEA( pEA_ ) , m_xEAHold( *pEA_ ) , m_EventMethod( EventMethod_ ) , m_AllListener( AllListener_ ) { } //************************************************************************* void SAL_CALL FilterAllListenerImpl::firing(const AllEventObject& Event) throw( RuntimeException ) { if( Event.MethodName == m_EventMethod && m_AllListener.is() ) m_AllListener->firing( Event ); } //************************************************************************* // Convert to the standard event return void FilterAllListenerImpl::convertToEventReturn( Any & rRet, const Type & rRetType ) throw( CannotConvertException ) { // no return value? Set to the specified values if( rRet.getValueType().getTypeClass() == TypeClass_VOID ) { switch( rRetType.getTypeClass() ) { case TypeClass_INTERFACE: { rRet <<= Reference< XInterface >(); } break; case TypeClass_BOOLEAN: rRet <<= sal_True; break; case TypeClass_STRING: rRet <<= OUString(); break; case TypeClass_FLOAT: rRet <<= float(0); break; case TypeClass_DOUBLE: rRet <<= double(0.0); break; case TypeClass_BYTE: rRet <<= sal_uInt8( 0 ); break; case TypeClass_SHORT: rRet <<= sal_Int16( 0 ); break; case TypeClass_LONG: rRet <<= sal_Int32( 0 ); break; case TypeClass_UNSIGNED_SHORT: rRet <<= sal_uInt16( 0 ); break; case TypeClass_UNSIGNED_LONG: rRet <<= sal_uInt32( 0 ); break; default: break; } } else if( !rRet.getValueType().equals( rRetType ) ) { Reference< XTypeConverter > xConverter = m_pEA->getConverter(); if( xConverter.is() ) rRet = xConverter->convertTo( rRet, rRetType ); else throw CannotConvertException(); // TODO TypeConversionException } } //************************************************************************* Any SAL_CALL FilterAllListenerImpl::approveFiring( const AllEventObject& Event ) throw( InvocationTargetException, RuntimeException ) { Any aRet; if( Event.MethodName == m_EventMethod && m_AllListener.is() ) aRet = m_AllListener->approveFiring( Event ); else { // Convert to the standard event return try { Reference< XIdlClass > xListenerType = m_pEA->getReflection()-> forName( Event.ListenerType.getTypeName() ); Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName ); if( xMeth.is() ) { Reference< XIdlClass > xRetType = xMeth->getReturnType(); Type aRetType( xRetType->getTypeClass(), xRetType->getName() ); convertToEventReturn( aRet, aRetType ); } } catch( CannotConvertException& e ) { throw InvocationTargetException( OUString(), Reference< XInterface >(), Any(&e, ::getCppuType( (CannotConvertException*)0)) ); } } return aRet; } //************************************************************************* void FilterAllListenerImpl::disposing(const EventObject& ) throw( RuntimeException ) { // TODO: ??? } //************************************************************************* Reference< XEventListener > EventAttacherImpl::attachListener ( const Reference< XInterface >& xObject, const Reference< XAllListener >& AllListener, const Any& Helper, const OUString& ListenerType, const OUString& AddListenerParam ) throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException ) { if( !xObject.is() || !AllListener.is() ) throw IllegalArgumentException(); Reference< XEventListener > xRet = NULL; Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = getInvocationAdapterService(); if( !xInvocationAdapterFactory.is() ) throw ServiceNotRegisteredException(); Reference< XIdlReflection > xReflection = getReflection(); if( !xReflection.is() ) throw ServiceNotRegisteredException(); // Sign in, Call the fitting addListener method // First Introspection, as the Methods can be analyzed in the same way // For better perfomance it is implemented here again or make the Impl-Method // of the Introspection configurable for this purpose. Reference< XIntrospection > xIntrospection = getIntrospection(); if( !xIntrospection.is() ) return xRet; // Inspect Introspection Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) ); Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny ); if( !xAccess.is() ) return xRet; // Construct the name of the addListener-Method. OUString aAddListenerName; OUString aListenerName( ListenerType ); sal_Int32 nIndex = aListenerName.lastIndexOf( '.' ); // set index to the interface name without package name if( nIndex == -1 ) // not found nIndex = 0; else nIndex++; if( aListenerName[nIndex] == 'X' ) // erase X from the interface name aListenerName = aListenerName.copy( nIndex +1 ); aAddListenerName = OUString( RTL_CONSTASCII_USTRINGPARAM( "add" ) ) + aListenerName; // Send Methods to the correct addListener-Method Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER ); sal_uInt32 i, nLen = aMethodSeq.getLength(); const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray(); for( i = 0 ; i < nLen ; i++ ) { const Reference< XIdlMethod >& rxMethod = pMethods[i]; // Is it the correct method? OUString aMethName = rxMethod->getName(); if( aAddListenerName == aMethName ) { Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes(); sal_uInt32 nParamCount = params.getLength(); Reference< XIdlClass > xListenerType; if( nParamCount == 1 ) xListenerType = params.getConstArray()[0]; else if( nParamCount == 2 ) xListenerType = params.getConstArray()[1]; // Request Adapter for the actual Listener type Reference< XInterface > xAdapter = createAllListenerAdapter ( xInvocationAdapterFactory, xListenerType, AllListener, Helper ); if( !xAdapter.is() ) throw CannotCreateAdapterException(); xRet = Reference< XEventListener >( xAdapter, UNO_QUERY ); // Just the Listener as parameter? if( nParamCount == 1 ) { Sequence< Any > args( 1 ); args.getArray()[0] <<= xAdapter; try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } // Else, pass the other parameter now else if( nParamCount == 2 ) { Sequence< Any > args( 2 ); Any* pAnys = args.getArray(); // Check the type of the 1st parameter Reference< XIdlClass > xParamClass = params.getConstArray()[0]; if( xParamClass->getTypeClass() == TypeClass_STRING ) { pAnys[0] <<= AddListenerParam; } // 2nd Parameter == Listener? TODO: Test! pAnys[1] <<= xAdapter; // TODO: Convert String -> ? // else try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } break; // else... // Anything else is not supported } } return xRet; } Sequence< Reference > EventAttacherImpl::attachListeners( const Reference& xObject, const Sequence< Reference >& AllListeners, const Sequence& aListeners ) { sal_Int32 nCount = aListeners.getLength(); if (nCount != AllListeners.getLength()) // This is a prerequisite! throw RuntimeException(); if (!xObject.is()) throw IllegalArgumentException(); Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = getInvocationAdapterService(); if( !xInvocationAdapterFactory.is() ) throw ServiceNotRegisteredException(); Reference< XIdlReflection > xReflection = getReflection(); if( !xReflection.is() ) throw ServiceNotRegisteredException(); // Sign in, Call the fitting addListener method // First Introspection, as the Methods can be analyzed in the same way // For better perfomance it is implemented here again or make the Impl-Method // of the Introspection configurable for this purpose. Reference< XIntrospection > xIntrospection = getIntrospection(); if( !xIntrospection.is() ) return Sequence< Reference >(); // Inspect Introspection Any aObjAny( &xObject, ::getCppuType(static_cast*>(0)) ); Reference xAccess = xIntrospection->inspect(aObjAny); if (!xAccess.is()) return Sequence< Reference >(); Sequence< Reference > aRet(nCount); Reference* pArray = aRet.getArray(); for (sal_Int32 i = 0; i < nCount; ++i) { Reference xRet = NULL; const Reference& AllListener = aListeners[i].AllListener; const Any& Helper = aListeners[i].Helper; const OUString& ListenerType = aListeners[i].ListenerType; const OUString& AddListenerParam = aListeners[i].AddListenerParam; // Construct the name of the addListener-Method. OUString aAddListenerName; OUString aListenerName( ListenerType ); sal_Int32 nIndex = aListenerName.lastIndexOf( '.' ); // set index to the interface name without package name if( nIndex == -1 ) // not found nIndex = 0; else nIndex++; if( aListenerName[nIndex] == 'X' ) // erase X from the interface name aListenerName = aListenerName.copy( nIndex +1 ); aAddListenerName = OUString( RTL_CONSTASCII_USTRINGPARAM( "add" ) ) + aListenerName; // Send Methods to the correct addListener-Method Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER ); sal_uInt32 j, nLen = aMethodSeq.getLength(); const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray(); for( j = 0 ; j < nLen ; j++ ) { const Reference< XIdlMethod >& rxMethod = pMethods[j]; // Is it the correct method? OUString aMethName = rxMethod->getName(); if( aAddListenerName == aMethName ) { Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes(); sal_uInt32 nParamCount = params.getLength(); Reference< XIdlClass > xListenerType; if( nParamCount == 1 ) xListenerType = params.getConstArray()[0]; else if( nParamCount == 2 ) xListenerType = params.getConstArray()[1]; // Request Adapter for the actual Listener type Reference< XInterface > xAdapter = createAllListenerAdapter ( xInvocationAdapterFactory, xListenerType, AllListener, Helper ); if( !xAdapter.is() ) throw CannotCreateAdapterException(); xRet = Reference< XEventListener >( xAdapter, UNO_QUERY ); // Just the Listener as parameter? if( nParamCount == 1 ) { Sequence< Any > args( 1 ); args.getArray()[0] <<= xAdapter; try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } // Else, pass the other parameter now else if( nParamCount == 2 ) { Sequence< Any > args( 2 ); Any* pAnys = args.getArray(); // Check the type of the 1st parameter Reference< XIdlClass > xParamClass = params.getConstArray()[0]; if( xParamClass->getTypeClass() == TypeClass_STRING ) { pAnys[0] <<= AddListenerParam; } // 2nd Parameter == Listener? TODO: Test! pAnys[1] <<= xAdapter; // TODO: Convert String -> ? // else try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } break; // else... // Anything else is not supported } } pArray[i] = xRet; } return aRet; } // XEventAttacher Reference< XEventListener > EventAttacherImpl::attachSingleEventListener ( const Reference< XInterface >& xObject, const Reference< XAllListener >& AllListener, const Any& Helper, const OUString& ListenerType, const OUString& AddListenerParam, const OUString& EventMethod ) throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException ) { // Subscribe FilterListener Reference< XAllListener > aFilterListener = (XAllListener*) new FilterAllListenerImpl( this, EventMethod, AllListener ); return attachListener( xObject, aFilterListener, Helper, ListenerType, AddListenerParam); } // XEventAttacher void EventAttacherImpl::removeListener ( const Reference< XInterface >& xObject, const OUString& ListenerType, const OUString& AddListenerParam, const Reference< XEventListener >& aToRemoveListener ) throw( IllegalArgumentException, IntrospectionException, RuntimeException ) { if( !xObject.is() || !aToRemoveListener.is() ) throw IllegalArgumentException(); Reference< XIdlReflection > xReflection = getReflection(); if( !xReflection.is() ) throw IntrospectionException(); // Sign off, Call the fitting removeListener method // First Introspection, as the Methods can be analyzed in the same way // For better perfomance it is implemented here again or make the Impl-Method // of the Introspection configurable for this purpose. Reference< XIntrospection > xIntrospection = getIntrospection(); if( !xIntrospection.is() ) throw IntrospectionException(); //Inspect Introspection Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) ); Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny ); if( !xAccess.is() ) throw IntrospectionException(); // Create name of the removeListener-Method OUString aRemoveListenerName; OUString aListenerName( ListenerType ); sal_Int32 nIndex = aListenerName.lastIndexOf( '.' ); // set index to the interface name without package name if( nIndex == -1 ) // not found nIndex = 0; else nIndex++; if( aListenerName[nIndex] == 'X' ) // erase X from the interface name aListenerName = aListenerName.copy( nIndex +1 ); aRemoveListenerName = OUString( RTL_CONSTASCII_USTRINGPARAM("remove") ) + aListenerName; // Search methods for the correct removeListener method Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER ); sal_uInt32 i, nLen = aMethodSeq.getLength(); const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray(); for( i = 0 ; i < nLen ; i++ ) { // Call Methode const Reference< XIdlMethod >& rxMethod = pMethods[i]; // Is it the right method? if( aRemoveListenerName == rxMethod->getName() ) { Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes(); sal_uInt32 nParamCount = params.getLength(); // Just the Listener as parameter? if( nParamCount == 1 ) { Sequence< Any > args( 1 ); args.getArray()[0] <<= aToRemoveListener; try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } // Else pass the other parameter else if( nParamCount == 2 ) { Sequence< Any > args( 2 ); Any* pAnys = args.getArray(); // Check the type of the 1st parameter Reference< XIdlClass > xParamClass = params.getConstArray()[0]; if( xParamClass->getTypeClass() == TypeClass_STRING ) pAnys[0] <<= AddListenerParam; // 2nd parameter == Listener? TODO: Test! pAnys[1] <<= aToRemoveListener; // TODO: Convert String -> ? // else try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } break; } } } Sequence< Reference > EventAttacherImpl::attachMultipleEventListeners( const Reference& xObject, const Sequence& aListeners ) throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException ) { sal_Int32 nCount = aListeners.getLength(); Sequence< Reference > aFilterListeners(nCount); for (sal_Int32 i = 0; i < nCount; ++i) { aFilterListeners[i] = (XAllListener*) new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener); } return attachListeners(xObject, aFilterListeners, aListeners); } } extern "C" { SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * ) { void * pRet = 0; if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0) { Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory( reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ), ::comp_EventAttacher::EventAttacherImpl_CreateInstance, ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) ); if (xFactory.is()) { xFactory->acquire(); pRet = xFactory.get(); } } return pRet; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */