diff options
Diffstat (limited to 'eventattacher/source/eventattacher.cxx')
-rw-r--r-- | eventattacher/source/eventattacher.cxx | 969 |
1 files changed, 969 insertions, 0 deletions
diff --git a/eventattacher/source/eventattacher.cxx b/eventattacher/source/eventattacher.cxx new file mode 100644 index 000000000000..266ae173f781 --- /dev/null +++ b/eventattacher/source/eventattacher.cxx @@ -0,0 +1,969 @@ +/************************************************************************* + * + * $RCSfile: eventattacher.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:15:25 $ + * + * 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 <osl/diagnose.h> +#endif + +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_ +#include <com/sun/star/lang/XInitialization.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_ +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_ +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HPP_ +#include <com/sun/star/registry/XRegistryKey.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XINTROSPECTION_HPP_ +#include <com/sun/star/beans/XIntrospection.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_METHODCONCEPT_HPP_ +#include <com/sun/star/beans/MethodConcept.hpp> +#endif +#ifndef _COM_SUN_STAR_SCRIPT_XEVENTATTACHER_HPP_ +#include <com/sun/star/script/XEventAttacher.hpp> +#endif +#ifndef _COM_SUN_STAR_SCRIPT_XTYPECONVERTER_HPP_ +#include <com/sun/star/script/XTypeConverter.hpp> +#endif +#ifndef _COM_SUN_STAR_SCRIPT_XALLLISTENER_HPP_ +#include <com/sun/star/script/XAllListener.hpp> +#endif +#ifndef _COM_SUN_STAR_SCRIPT_XINVOCATIONADAPTERFACTORY_HPP_ +#include <com/sun/star/script/XInvocationAdapterFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_REFLECTION_XIDLREFLECTION_HPP_ +#include <com/sun/star/reflection/XIdlReflection.hpp> +#endif + +// InvocationToAllListenerMapper +#ifndef _COM_SUN_STAR_SCRIPT_XINVOCATION_HPP_ +#include <com/sun/star/script/XInvocation.hpp> +#endif + +#ifndef _CPPUHELPER_WEAK_HXX_ +#include <cppuhelper/weak.hxx> +#endif +#ifndef _CPPUHELPER_FACTORY_HXX_ +#include <cppuhelper/factory.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE3_HXX_ +#include <cppuhelper/implbase3.hxx> +#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, ServiceNotRegisteredException, 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<XInterface>::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<OUString> SAL_CALL EventAttacherImpl::getSupportedServiceNames( ) + throw(RuntimeException) +{ + return getSupportedServiceNames_Static(); +} + +//************************************************************************* +Sequence<OUString> 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, ServiceNotRegisteredException, IntrospectionException, RuntimeException ) +{ + if( !xObject.is() || !aToRemoveListener.is() ) + throw IllegalArgumentException(); + + // Listener-Klasse per Reflection besorgen + Reference< XIdlReflection > xReflection = getReflection(); + if( !xReflection.is() ) + throw ServiceNotRegisteredException(); + + // 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 ServiceNotRegisteredException(); + + // 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 > & rSNL = + ::comp_EventAttacher::EventAttacherImpl::getSupportedServiceNames_Static(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + xNewKey->createKey( pArray[nPos] ); + + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSHURE( 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; +} +} + + + |