/************************************************************************* * * $RCSfile: eventattacher.cxx,v $ * * $Revision: 1.4 $ * * last change: $Author: vg $ $Date: 2003-06-12 09:48:10 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library 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 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #ifndef _OSL_DIAGNOSE_H_ #include #endif #ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ #include #endif #ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_ #include #endif #ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_ #include #endif #ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_ #include #endif #ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HPP_ #include #endif #ifndef _COM_SUN_STAR_BEANS_XINTROSPECTION_HPP_ #include #endif #ifndef _COM_SUN_STAR_BEANS_METHODCONCEPT_HPP_ #include #endif #ifndef _COM_SUN_STAR_SCRIPT_XEVENTATTACHER_HPP_ #include #endif #ifndef _COM_SUN_STAR_SCRIPT_XTYPECONVERTER_HPP_ #include #endif #ifndef _COM_SUN_STAR_SCRIPT_XALLLISTENER_HPP_ #include #endif #ifndef _COM_SUN_STAR_SCRIPT_XINVOCATIONADAPTERFACTORY_HPP_ #include #endif #ifndef _COM_SUN_STAR_REFLECTION_XIDLREFLECTION_HPP_ #include #endif // InvocationToAllListenerMapper #ifndef _COM_SUN_STAR_SCRIPT_XINVOCATION_HPP_ #include #endif #ifndef _CPPUHELPER_WEAK_HXX_ #include #endif #ifndef _CPPUHELPER_FACTORY_HXX_ #include #endif #ifndef _CPPUHELPER_IMPLBASE1_HXX_ #include #endif #ifndef _CPPUHELPER_IMPLBASE3_HXX_ #include #endif 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 namespace rtl; #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_Helper( Helper ) , m_xListenerType( ListenerType ) { } //************************************************************************* 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 >& OutParamIndex, Sequence< Any >& OutParam) 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& PropertyName, const Any& Value) throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException ) { } //************************************************************************* Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& PropertyName) 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 < XEventAttacher, 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 ); // used by FilterAllListener_Impl Reference< XTypeConverter > getConverter() throw( Exception ); friend class FilterAllListenerImpl; private: Mutex m_aMutex; Reference< XMultiServiceFactory > m_xSMgr; // Services merken 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 Hilfs-Methoden *** Reference< XIntrospection > EventAttacherImpl::getIntrospection() throw( Exception ) { Guard< Mutex > aGuard( m_aMutex ); // Haben wir den Service schon? Sonst anlegen if( !m_xIntrospection.is() ) { Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString::createFromAscii("com.sun.star.beans.Introspection") ) ); m_xIntrospection = Reference< XIntrospection >( xIFace, UNO_QUERY ); } return m_xIntrospection; } //************************************************************************* //*** Private Hilfs-Methoden *** Reference< XIdlReflection > EventAttacherImpl::getReflection() throw( Exception ) { Guard< Mutex > aGuard( m_aMutex ); // Haben wir den Service schon? Sonst anlegen if( !m_xReflection.is() ) { Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString::createFromAscii("com.sun.star.reflection.CoreReflection") ) ); m_xReflection = Reference< XIdlReflection >( xIFace, UNO_QUERY); } return m_xReflection; } //************************************************************************* //*** Private Hilfs-Methoden *** Reference< XInvocationAdapterFactory > EventAttacherImpl::getInvocationAdapterService() throw( Exception ) { Guard< Mutex > aGuard( m_aMutex ); // Haben wir den Service schon? Sonst anlegen if( !m_xInvocationAdapterFactory.is() ) { Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString::createFromAscii("com.sun.star.script.InvocationAdapterFactory") ) ); m_xInvocationAdapterFactory = Reference< XInvocationAdapterFactory >( xIFace, UNO_QUERY ); } return m_xInvocationAdapterFactory; } //************************************************************************* //*** Private Hilfs-Methoden *** Reference< XTypeConverter > EventAttacherImpl::getConverter() throw( Exception ) { Guard< Mutex > aGuard( m_aMutex ); // Haben wir den Service schon? Sonst anlegen if( !m_xConverter.is() ) { Reference< XInterface > xIFace( m_xSMgr->createInstance( rtl::OUString::createFromAscii("com.sun.star.script.Converter") ) ); m_xConverter = Reference< XTypeConverter >( xIFace, UNO_QUERY ); } return m_xConverter; } //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ // Implementation eines EventAttacher-bezogenen AllListeners, der // nur einzelne Events an einen allgemeinen AllListener weiterleitet 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 ) { // Nur durchreichen, wenn es die richtige Methode ist 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; 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; // Nur durchreichen, wenn es die richtige Methode ist 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& Source) 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; // InvocationAdapterService holen Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = getInvocationAdapterService(); if( !xInvocationAdapterFactory.is() ) throw ServiceNotRegisteredException(); // Listener-Klasse per Reflection besorgen Reference< XIdlReflection > xReflection = getReflection(); if( !xReflection.is() ) throw ServiceNotRegisteredException(); // Anmelden, dazu passende addListener-Methode aufrufen // Zunaechst ueber Introspection gehen, da die Methoden in der gleichen // Weise analysiert werden koennen. Fuer bessere Performance entweder // hier nochmal implementieren oder die Impl-Methode der Introspection // fuer diesen Zweck konfigurierbar machen. // Introspection-Service holen Reference< XIntrospection > xIntrospection = getIntrospection(); if( !xIntrospection.is() ) return xRet; // und unspecten Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) ); Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny ); if( !xAccess.is() ) return xRet; // Name der addListener-Methode zusammenbasteln 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; // Methoden nach der passenden addListener-Methode durchsuchen 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++ ) { // Methode ansprechen const Reference< XIdlMethod >& rxMethod = pMethods[i]; // Ist es die richtige Methode? 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]; // Adapter zum eigentlichen Listener-Typ anfordern Reference< XInterface > xAdapter = createAllListenerAdapter ( xInvocationAdapterFactory, xListenerType, AllListener, Helper ); if( !xAdapter.is() ) throw CannotCreateAdapterException(); xRet = Reference< XEventListener >( xAdapter, UNO_QUERY ); // Nur der Listener als Parameter? if( nParamCount == 1 ) { Sequence< Any > args( 1 ); args.getArray()[0] <<= xAdapter; try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } // Sonst den Zusatzparameter mit uebergeben else if( nParamCount == 2 ) { Sequence< Any > args( 2 ); Any* pAnys = args.getArray(); // Typ des 1. Parameters pruefen Reference< XIdlClass > xParamClass = params.getConstArray()[0]; if( xParamClass->getTypeClass() == TypeClass_STRING ) { pAnys[0] <<= AddListenerParam; } // 2. Parameter == Listener? TODO: Pruefen! pAnys[1] <<= xAdapter; // TODO: Konvertierung String -> ? // else try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } break; // else... // Alles andere wird nicht unterstuetzt } } return xRet; } // 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 ) { // FilterListener anmelden 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(); // Listener-Klasse per Reflection besorgen Reference< XIdlReflection > xReflection = getReflection(); if( !xReflection.is() ) throw IntrospectionException(); // Abmelden, dazu passende removeListener-Methode aufrufen // Zunaechst ueber Introspection gehen, da die Methoden in der gleichen // Weise analysiert werden koennen. Fuer bessere Performance entweder // hier nochmal implementieren oder die Impl-Methode der Introspection // fuer diesen Zweck konfigurierbar machen. // Introspection-Service holen Reference< XIntrospection > xIntrospection = getIntrospection(); if( !xIntrospection.is() ) throw IntrospectionException(); // und inspecten Any aObjAny( &xObject, ::getCppuType( (const Reference< XInterface > *)0) ); Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny ); if( !xAccess.is() ) throw IntrospectionException(); // Name der removeListener-Methode zusammenbasteln 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; // Methoden nach der passenden addListener-Methode durchsuchen 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++ ) { // Methode ansprechen const Reference< XIdlMethod >& rxMethod = pMethods[i]; // Ist es die richtige Methode? if( aRemoveListenerName == rxMethod->getName() ) { Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes(); sal_uInt32 nParamCount = params.getLength(); // Nur der Listener als Parameter? if( nParamCount == 1 ) { Sequence< Any > args( 1 ); args.getArray()[0] <<= aToRemoveListener; try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } // Sonst den Zusatzparameter mit uebergeben else if( nParamCount == 2 ) { Sequence< Any > args( 2 ); Any* pAnys = args.getArray(); // Typ des 1. Parameters pruefen Reference< XIdlClass > xParamClass = params.getConstArray()[0]; if( xParamClass->getTypeClass() == TypeClass_STRING ) pAnys[0] <<= AddListenerParam; // 2. Parameter == Listener? TODO: Pruefen! pAnys[1] <<= aToRemoveListener; // TODO: Konvertierung String -> ? // else try { rxMethod->invoke( aObjAny, args ); } catch( InvocationTargetException& ) { throw IntrospectionException(); } } break; } } } } extern "C" { //================================================================================================== void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) { *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; } //================================================================================================== sal_Bool SAL_CALL component_writeInfo( void * pServiceManager, void * pRegistryKey ) { if (pRegistryKey) { try { // DefaultRegistry Reference< XRegistryKey > xNewKey( reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( OUString( RTL_CONSTASCII_USTRINGPARAM( "/" IMPLNAME "/UNO/SERVICES") ))); Sequence< OUString > aSNL ( ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ); const OUString * pArray = aSNL.getConstArray(); for ( sal_Int32 nPos = aSNL.getLength(); nPos--; ) xNewKey->createKey( pArray[nPos] ); return sal_True; } catch (InvalidRegistryException &) { OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); } } return sal_False; } //================================================================================================== void * SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) { void * pRet = 0; if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0) { Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory( reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), OUString( RTL_CONSTASCII_USTRINGPARAM( pImplName ) ), ::comp_EventAttacher::EventAttacherImpl_CreateInstance, ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static() ) ); if (xFactory.is()) { xFactory->acquire(); pRet = xFactory.get(); } } return pRet; } }