summaryrefslogtreecommitdiff
path: root/basic/source/classes
diff options
context:
space:
mode:
authorMikhail Voytenko <mav@openoffice.org>2010-08-30 09:45:08 +0200
committerMikhail Voytenko <mav@openoffice.org>2010-08-30 09:45:08 +0200
commite20d0e3eb6dbd05da364c8ec3b71ff4f118dbf48 (patch)
tree0ce41d7bb4a27d6f909fc7379e8c93f68de898a0 /basic/source/classes
parentc211b684d02ef787f38a1e419bc0c9ed10244ef8 (diff)
mib19: #163217# let the basic listeners stop listening on termination, patch from AB
Diffstat (limited to 'basic/source/classes')
-rwxr-xr-xbasic/source/classes/sb.cxx4
-rwxr-xr-xbasic/source/classes/sbunoobj.cxx161
-rwxr-xr-xbasic/source/classes/sbxmod.cxx5
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 )
{