diff options
author | Mikhail Voytenko <mav@openoffice.org> | 2010-08-30 09:45:08 +0200 |
---|---|---|
committer | Mikhail Voytenko <mav@openoffice.org> | 2010-08-30 09:45:08 +0200 |
commit | e20d0e3eb6dbd05da364c8ec3b71ff4f118dbf48 (patch) | |
tree | 0ce41d7bb4a27d6f909fc7379e8c93f68de898a0 /basic/source/classes | |
parent | c211b684d02ef787f38a1e419bc0c9ed10244ef8 (diff) |
mib19: #163217# let the basic listeners stop listening on termination, patch from AB
Diffstat (limited to 'basic/source/classes')
-rwxr-xr-x | basic/source/classes/sb.cxx | 4 | ||||
-rwxr-xr-x | basic/source/classes/sbunoobj.cxx | 161 | ||||
-rwxr-xr-x | basic/source/classes/sbxmod.cxx | 5 |
3 files changed, 166 insertions, 4 deletions
diff --git a/basic/source/classes/sb.cxx b/basic/source/classes/sb.cxx index f509647e08a1..fbbf132c07d3 100755 --- a/basic/source/classes/sb.cxx +++ b/basic/source/classes/sb.cxx @@ -761,6 +761,8 @@ void StarBASIC::SetModified( BOOL b ) SbxBase::SetModified( b ); } +void disposeComVariablesForBasic( StarBASIC* pBasic ); + StarBASIC::~StarBASIC() { if( !--GetSbData()->nInst ) @@ -803,6 +805,8 @@ StarBASIC::~StarBASIC() } xUnoListeners = NULL; } + + disposeComVariablesForBasic( this ); } // Override new() operator, so that everyone can create a new instance diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx index c9123b06341b..53a7c5c18930 100755 --- a/basic/source/classes/sbunoobj.cxx +++ b/basic/source/classes/sbunoobj.cxx @@ -36,9 +36,11 @@ #include <svl/hint.hxx> #include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> #include <cppuhelper/exc_hlp.hxx> #include <cppuhelper/typeprovider.hxx> #include <cppuhelper/extract.hxx> +#include <cppuhelper/interfacecontainer.hxx> #include <comphelper/processfactory.hxx> #include <rtl/ustrbuf.hxx> @@ -4170,14 +4172,26 @@ void RTL_Impl_CreateUnoValue( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) //========================================================================== -typedef WeakImplHelper1< XInvocation > ModuleInvocationProxyHelper; +namespace { +class OMutexBasis +{ +protected: + // this mutex is necessary for OInterfaceContainerHelper + ::osl::Mutex m_aMutex; +}; +}; -class ModuleInvocationProxy : public ModuleInvocationProxyHelper +typedef WeakImplHelper2< XInvocation, XComponent > ModuleInvocationProxyHelper; + +class ModuleInvocationProxy : public OMutexBasis, + public ModuleInvocationProxyHelper { ::rtl::OUString m_aPrefix; SbxObjectRef m_xScopeObj; bool m_bProxyIsClassModuleObject; + ::cppu::OInterfaceContainerHelper m_aListeners; + public: ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ); ~ModuleInvocationProxy() @@ -4197,11 +4211,17 @@ public: Sequence< sal_Int16 >& rOutParamIndex, Sequence< Any >& rOutParam ) throw( CannotConvertException, InvocationTargetException ); + + // XComponent + virtual void SAL_CALL dispose() throw(RuntimeException); + virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException); + virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) throw (RuntimeException); }; ModuleInvocationProxy::ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ) : m_aPrefix( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_") ) ) , m_xScopeObj( xScopeObj ) + , m_aListeners( m_aMutex ) { m_bProxyIsClassModuleObject = xScopeObj.Is() ? xScopeObj->ISA(SbClassModuleObject) : false; } @@ -4298,13 +4318,14 @@ Any SAL_CALL ModuleInvocationProxy::invoke( const ::rtl::OUString& rFunction, NAMESPACE_VOS(OGuard) guard( Application::GetSolarMutex() ); Any aRet; - if( !m_xScopeObj.Is() ) + SbxObjectRef xScopeObj = m_xScopeObj; + if( !xScopeObj.Is() ) return aRet; ::rtl::OUString aFunctionName = m_aPrefix; aFunctionName += rFunction; - SbxVariable* p = m_xScopeObj->Find( aFunctionName, SbxCLASS_METHOD ); + SbxVariable* p = xScopeObj->Find( aFunctionName, SbxCLASS_METHOD ); SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL; if( pMeth == NULL ) { @@ -4341,6 +4362,30 @@ Any SAL_CALL ModuleInvocationProxy::invoke( const ::rtl::OUString& rFunction, return aRet; } +void SAL_CALL ModuleInvocationProxy::dispose() + throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + EventObject aEvent( (XComponent*)this ); + m_aListeners.disposeAndClear( aEvent ); + + m_xScopeObj = NULL; +} + +void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener ) + throw (RuntimeException) +{ + m_aListeners.addInterface( xListener ); +} + +void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener ) + throw (RuntimeException) +{ + m_aListeners.removeInterface( xListener ); +} + + Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl::OUString& aVBAType, const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ) { @@ -4370,6 +4415,97 @@ Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl:: return xRet; } +typedef std::vector< WeakReference< XComponent > > ComponentRefVector; + +struct StarBasicDisposeItem +{ + StarBASIC* m_pBasic; + SbxArrayRef m_pRegisteredVariables; + ComponentRefVector m_vComImplementsObjects; + + StarBasicDisposeItem( StarBASIC* pBasic ) + : m_pBasic( pBasic ) + { + m_pRegisteredVariables = new SbxArray(); + } +}; + +typedef std::vector< StarBasicDisposeItem* > DisposeItemVector; + +static DisposeItemVector GaDisposeItemVector; + +DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC* pBasic ) +{ + DisposeItemVector::iterator it; + for( it = GaDisposeItemVector.begin() ; it != GaDisposeItemVector.end() ; ++it ) + { + StarBasicDisposeItem* pItem = *it; + if( pItem->m_pBasic == pBasic ) + return it; + } + return GaDisposeItemVector.end(); +} + +StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic ) +{ + DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); + StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : NULL; + if( pItem == NULL ) + { + pItem = new StarBasicDisposeItem( pBasic ); + GaDisposeItemVector.push_back( pItem ); + } + return pItem; +} + +void lcl_registerComponentToBeDisposedForBasic + ( Reference< XComponent > xComponent, StarBASIC* pBasic ) +{ + StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); + pItem->m_vComImplementsObjects.push_back( xComponent ); +} + +void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic ) +{ + StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); + SbxArray* pArray = pItem->m_pRegisteredVariables; + pArray->Put( pVar, pArray->Count() ); +} + +void disposeComVariablesForBasic( StarBASIC* pBasic ) +{ + DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); + if( it != GaDisposeItemVector.end() ) + { + StarBasicDisposeItem* pItem = *it; + + SbxArray* pArray = pItem->m_pRegisteredVariables; + USHORT nCount = pArray->Count(); + for( USHORT i = 0 ; i < nCount ; ++i ) + { + SbxVariable* pVar = pArray->Get( i ); + pVar->ClearComListener(); + } + + ComponentRefVector& rv = pItem->m_vComImplementsObjects; + ComponentRefVector::iterator itCRV; + for( itCRV = rv.begin() ; itCRV != rv.end() ; ++itCRV ) + { + try + { + Reference< XComponent > xComponent( (*itCRV).get(), UNO_QUERY_THROW ); + xComponent->dispose(); + } + catch( Exception& ) + {} + } + + delete pItem; + GaDisposeItemVector.erase( it ); + } +} + + // Handle module implements mechanism for OLE types bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject ) { @@ -4423,6 +4559,23 @@ bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pP if( bSuccess ) { + Reference< XComponent > xComponent( xProxy, UNO_QUERY ); + if( xComponent.is() ) + { + StarBASIC* pParentBasic = NULL; + SbxObject* pCurObject = this; + do + { + SbxObject* pParent = pCurObject->GetParent(); + pParentBasic = PTR_CAST(StarBASIC,pParent); + pCurObject = pParent; + } + while( pParentBasic == NULL && pCurObject != NULL ); + + OSL_ASSERT( pParentBasic != NULL ); + lcl_registerComponentToBeDisposedForBasic( xComponent, pParentBasic ); + } + o_rRetAny <<= xRet; break; } diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx index 2b3849169fd9..46a1488844c1 100755 --- a/basic/source/classes/sbxmod.cxx +++ b/basic/source/classes/sbxmod.cxx @@ -2072,6 +2072,11 @@ SbObjModule::SbObjModule( const String& rName, const com::sun::star::script::Mod else if ( mInfo.ModuleObject.is() ) SetUnoObject( uno::makeAny( mInfo.ModuleObject ) ); } + +SbObjModule::~SbObjModule() +{ +} + void SbObjModule::SetUnoObject( const uno::Any& aObj ) throw ( uno::RuntimeException ) { |