User: hr Date: 05/09/23 05:04:58 Modified: /dba/dbaccess/source/core/dataaccess/ databasedocument.cxx
Log: INTEGRATION: CWS dba201b (1.19.10); FILE MERGED 2005/09/21 07:01:01 oj 1.19.10.5: RESYNC: (1.20-1.21); FILE MERGED 2005/07/20 10:18:08 fs 1.19.10.4: #i52171# better control over model ownership 2005/07/11 13:37:00 fs 1.19.10.3: merging CWS dba201 into CWS dba201b 2005/07/11 07:18:20 oj 1.19.10.2: RESYNC: (1.19-1.20); FILE MERGED 2005/05/27 10:32:23 oj 1.19.10.1: #i49860# don't clear connection when storeToUrl is called File Changes: Directory: /dba/dbaccess/source/core/dataaccess/ ================================================ File [changed]: databasedocument.cxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/core/dataaccess/databasedocument.cxx?r1=1.21&r2=1.22 Delta lines: +42 -53 --------------------- --- databasedocument.cxx 8 Sep 2005 12:02:43 -0000 1.21 +++ databasedocument.cxx 23 Sep 2005 12:04:55 -0000 1.22 @@ -367,41 +367,6 @@ m_pImpl->m_aControllers.erase(::std::find(m_pImpl->m_aControllers.begin(),m_pImpl->m_aControllers.end(),_xController)); if ( m_pImpl->m_xCurrentController == _xController ) m_pImpl->m_xCurrentController = NULL; - - // TODO: The below fragment is conceptually wrong. - // - // There are more clients of a database document (aka XModel) than its controllers. - // In particular, people might programmatically obtain a DataSource from the - // DatabaseContext, script it, and at some point obtain the document from - // the data source (XDocumentDataSource::getDatabaseDocument). All this might happen - // without any controller being involved, which means the document gets never disposed, - // which imlpies a resource leak. - // - // You might argue that the scripter who obtained the model is responsible for disposing - // it. However, she cannot know whether the model she just got from getDatabaseDocument - // is really hers (since it was newly created), or already owned by somebody else. So, - // she cannot know whether she is really allowed to dispose it. - // - // There is a pattern which could prevent this dilemma: closing with ownership delivery - // (XCloseable::close). With this pattern, every client of a component (here: the model) - // adds itself as XCloseListener to the component. When the client dies, it tries to - // close the component, with the DeliverOwnership parameter set to <TRUE/>. If there is - // another client of the component, it will veto the closing, and take the ownership - // (and in turn do an own close attempt later on). If there is no other client, closing - // will succeed. - // - // We should implement this for models, too. Then, controllers would be clients of the - // model, and do a close attempt when they disconnect. The model would never dispose - // itself (as it does now), but it would automatically be closed when the last client - // dies (provided that all clients respect this pattern). It turn, it would not be - // allowed to dispose a model directly. - // - // #i50905# / 2005-06-21 / [EMAIL PROTECTED] - if ( m_pImpl.is() && m_pImpl->m_aControllers.empty() ) - { - aGuard.clear(); - dispose(); - } } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::lockControllers( ) throw (RuntimeException) @@ -717,32 +682,50 @@ { } // ----------------------------------------------------------------------------- -void SAL_CALL ODatabaseDocument::close( sal_Bool bDeliverOwnership ) throw (::com::sun::star::util::CloseVetoException, RuntimeException) +void ODatabaseDocument::impl_closeControllerFrames( sal_Bool _bDeliverOwnership ) { - ResettableMutexGuard _rGuard(m_aMutex); - ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); - - lang::EventObject aEvt( static_cast< ::cppu::OWeakObject* >( this ) ); - NOTIFY_LISTERNERS1(m_aCloseListener,com::sun::star::util::XCloseListener,queryClosing,bDeliverOwnership); - ::std::vector< Reference< XController> > aCopy = m_pImpl->m_aControllers; + ::std::vector< Reference< XController> >::iterator aIter = aCopy.begin(); ::std::vector< Reference< XController> >::iterator aEnd = aCopy.end(); - for (;aIter != aEnd ; ++aIter) + for ( ;aIter != aEnd ; ++aIter ) { if ( aIter->is() ) { - Reference< XCloseable> xFrame((*aIter)->getFrame(),UNO_QUERY); + try + { + Reference< XCloseable> xFrame( (*aIter)->getFrame(), UNO_QUERY ); if ( xFrame.is() ) - xFrame->close(bDeliverOwnership); + xFrame->close( _bDeliverOwnership ); } + catch( const CloseVetoException& ) { throw; } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ODatabaseDocument::impl_closeControllerFrames: caught an unexpected exception!" ); } - if ( m_pImpl.is() ) - m_pImpl->m_aControllers.clear(); - dispose(); + } + } +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw (::com::sun::star::util::CloseVetoException, RuntimeException) +{ + ResettableMutexGuard _rGuard(m_aMutex); + ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); + + lang::EventObject aEvt( static_cast< ::cppu::OWeakObject* >( this ) ); + { + NOTIFY_LISTERNERS1(m_aCloseListener,com::sun::star::util::XCloseListener,queryClosing,_bDeliverOwnership); + } + + DBG_ASSERT( m_pImpl->m_aControllers.empty(), "ODatabaseDocument::close: aren't controllers expected to veto the closing?" ); + impl_closeControllerFrames( _bDeliverOwnership ); + { NOTIFY_LISTERNERS(m_aCloseListener,com::sun::star::util::XCloseListener,notifyClosing); } + + dispose(); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::addCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) @@ -1073,6 +1056,12 @@ //------------------------------------------------------------------------------ void ODatabaseDocument::disposing() { + DBG_ASSERT( m_pImpl->m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); + // normally, nobody should explicitly dispose, but only XCloseable::close the document. And controllers + // are expected to veto the closing, so when we're here, there shouldn't be any controllers anymore. + if ( m_pImpl.is() ) + m_pImpl->m_aControllers.clear(); + Reference< XModel > xHoldAlive( this ); { notifyEvent(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnUnload"))); --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
