/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: databasedocument.cxx,v $ * * $Revision: 1.29 $ * * last change: $Author: hr $ $Date: 2006-06-20 02:44:17 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 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 * ************************************************************************/ #ifndef _DBA_COREDATAACCESS_DATASOURCE_HXX_ #include "datasource.hxx" #endif #ifndef _DBA_COREDATAACCESS_DATABASEDOCUMENT_HXX_ #include "databasedocument.hxx" #endif #ifndef DBACCESS_SHARED_DBASTRINGS_HRC #include "dbastrings.hrc" #endif #include #ifndef _COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_ #include #endif #ifndef _COM_SUN_STAR_IO_XACTIVEDATASOURCE_HPP_ #include #endif #ifndef _COM_SUN_STAR_IO_XSEEKABLE_HPP_ #include #endif #ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATOR_HPP_ #include #endif #ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATORFACTORY_HPP_ #include #endif #ifndef _COM_SUN_STAR_DOCUMENT_XEXPORTER_HPP_ #include #endif #ifndef _COM_SUN_STAR_DOCUMENT_XFILTER_HPP_ #include #endif #ifndef _COM_SUN_STAR_TASK_ERRORCODEIOEXCEPTION_HPP_ #include #endif #ifndef _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HPP_ #include #endif #ifndef _DBA_COREDATAACCESS_DOCUMENTCONTAINER_HXX_ #include "documentcontainer.hxx" #endif #ifndef _DBA_COREDATAACCESS_DATABASECONTEXT_HXX_ #include "databasecontext.hxx" #endif #ifndef _URLOBJ_HXX #include #endif #ifndef _ERRCODE_HXX #include #endif #ifndef _COMPHELPER_MEDIADESCRIPTOR_HXX_ #include #endif #ifndef _COM_SUN_STAR_UI_XUICONFIGURATIONSTORAGE_HPP_ #include #endif #ifndef _COM_SUN_STAR_EMBED_XTRANSACTIONBROADCASTER_HPP_ #include #endif #ifndef _COM_SUN_STAR_EMBED_XEMBEDPERSIST_HPP_ #include #endif #ifndef _COM_SUN_STAR_EMBED_ENTRYINITMODES_HPP_ #include #endif #ifndef _COM_SUN_STAR_VIEW_XSELECTIONSUPPLIER_HPP_ #include #endif #ifndef _COM_SUN_STAR_DOCUMENT_XIMPORTER_HPP_ #include #endif #ifndef _TOOLS_DEBUG_HXX #include #endif #ifndef _CPPUHELPER_EXC_HLP_HXX_ #include #endif #ifndef BOOST_BIND_HPP_INCLUDED #include #endif namespace css = ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::frame; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::container; using namespace ::com::sun::star::document; using namespace ::com::sun::star::io; using namespace ::com::sun::star::util; using namespace ::com::sun::star::embed; using namespace ::com::sun::star::task; using namespace ::com::sun::star::view; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star; using namespace ::com::sun::star::xml::sax; using namespace ::cppu; using namespace ::osl; namespace css = ::com::sun::star; //........................................................................ namespace dbaccess { //........................................................................ //============================================================ //= ODatabaseContext //============================================================ DBG_NAME(ODatabaseDocument) //-------------------------------------------------------------------------- extern "C" void SAL_CALL createRegistryInfo_ODatabaseDocument() { static OMultiInstanceAutoRegistration< ODatabaseDocument > aAutoRegistration; } //-------------------------------------------------------------------------- Reference< XInterface > ODatabaseDocument_CreateInstance(const Reference< XMultiServiceFactory >& _rxFactory) { ODatabaseContext* pContext = NULL; try { Reference xUnoTunnel(_rxFactory->createInstance(SERVICE_SDB_DATABASECONTEXT),UNO_QUERY); if ( xUnoTunnel.is() ) pContext = reinterpret_cast(xUnoTunnel->getSomething(ODatabaseContext::getUnoTunnelImplementationId())); } catch(Exception) { } ::rtl::Reference pImpl(new ODatabaseModelImpl(_rxFactory)); pImpl->m_pDBContext = pContext; Reference< XModel > xModel( pImpl->createNewModel_deliverOwnership() ); return xModel.get(); } //-------------------------------------------------------------------------- ODatabaseDocument::ODatabaseDocument(const ::rtl::Reference& _pImpl ) :ModelDependentComponent( _pImpl ) ,ODatabaseDocument_OfficeDocument( getMutex() ) ,m_aModifyListeners( getMutex() ) ,m_aCloseListener( getMutex() ) ,m_aDocEventListeners( getMutex() ) { DBG_CTOR(ODatabaseDocument,NULL); osl_incrementInterlockedCount( &m_refCount ); { impl_reparent_nothrow( m_xForms ); impl_reparent_nothrow( m_xReports ); impl_reparent_nothrow( m_pImpl->m_xTableDefinitions ); impl_reparent_nothrow( m_pImpl->m_xCommandDefinitions ); } osl_decrementInterlockedCount( &m_refCount ); } //-------------------------------------------------------------------------- ODatabaseDocument::~ODatabaseDocument() { DBG_DTOR(ODatabaseDocument,NULL); if ( !ODatabaseDocument_OfficeDocument::rBHelper.bInDispose && !ODatabaseDocument_OfficeDocument::rBHelper.bDisposed ) { acquire(); dispose(); } } // ----------------------------------------------------------------------------- // local functions // ----------------------------------------------------------------------------- void lcl_stripLoadArguments( ::comphelper::MediaDescriptor& _rDescriptor, Sequence< PropertyValue >& _rArgs ) { _rDescriptor.erase( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StatusIndicator" ) ) ); _rDescriptor.erase( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InteractionHandler" ) ) ); _rDescriptor.erase( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) ) ); _rDescriptor >> _rArgs; } // ----------------------------------------------------------------------------- void lcl_extractAndStartStatusIndicator( const ::comphelper::MediaDescriptor& _rDescriptor, Reference< XStatusIndicator >& _rxStatusIndicator, Sequence< Any >& _rCallArgs ) { try { _rxStatusIndicator = _rDescriptor.getUnpackedValueOrDefault( _rDescriptor.PROP_STATUSINDICATOR(), _rxStatusIndicator ); if ( _rxStatusIndicator.is() ) { _rxStatusIndicator->start( ::rtl::OUString(), (sal_Int32)1000000 ); sal_Int32 nLength = _rCallArgs.getLength(); _rCallArgs.realloc( nLength + 1 ); _rCallArgs[ nLength ] <<= _rxStatusIndicator; } } catch( const Exception& ) { OSL_ENSURE( sal_False, "lcl_extractAndStartStatusIndicator: caught an exception!" ); } } // ----------------------------------------------------------------------------- // XModel // ATTENTION: The Application controller attaches the same resource to force a reload. sal_Bool SAL_CALL ODatabaseDocument::attachResource( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _aArguments ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); try { m_pImpl->clearConnections(); m_pImpl->disposeStorages(); if ( m_pImpl->m_bOwnStorage ) ::comphelper::disposeComponent(m_pImpl->m_xStorage); clearObjectContainer( m_xForms); clearObjectContainer( m_xReports); clearObjectContainer( m_pImpl->m_xTableDefinitions); clearObjectContainer( m_pImpl->m_xCommandDefinitions); m_pImpl->m_aContainer.clear(); m_pImpl->lateInit(); } catch(const Exception&) { m_pImpl->m_xStorage = NULL; } m_pImpl->m_bDocumentReadOnly = sal_False; ::comphelper::MediaDescriptor aDescriptor( _aArguments ); lcl_stripLoadArguments( aDescriptor, m_pImpl->m_aArgs ); m_pImpl->m_sFileURL = _rURL; m_pImpl->m_sRealFileURL = aDescriptor.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SalvagedFile" ) ), _rURL ); if ( !m_pImpl->m_sRealFileURL.getLength() ) m_pImpl->m_sRealFileURL = m_pImpl->m_sFileURL; if ( !m_pImpl->m_sName.getLength() ) m_pImpl->m_sName = m_pImpl->m_sRealFileURL; m_pImpl->getStorage(); try { Sequence aFilterArgs; Reference xStatusIndicator; lcl_extractAndStartStatusIndicator( aDescriptor, xStatusIndicator, aFilterArgs ); Reference xImporter( m_pImpl->m_xServiceFactory->createInstanceWithArguments( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.sdb.DBFilter" ) ), aFilterArgs ), UNO_QUERY ); if ( xImporter.is() ) { Reference xComponent(*this,UNO_QUERY); xImporter->setTargetDocument(xComponent); Reference xFilter(xImporter,UNO_QUERY); xFilter->filter(_aArguments); if ( xStatusIndicator.is() ) xStatusIndicator->end(); } else return sal_False; } catch(const RuntimeException& e) { throw e; } catch(const Exception&) { return sal_False; } if ( m_pImpl->m_pDBContext && m_pImpl->m_sRealFileURL.getLength() ) { m_pImpl->m_pDBContext->registerPrivate(m_pImpl->m_sRealFileURL,m_pImpl); m_pImpl->setModified(sal_False); } return sal_True; } // ----------------------------------------------------------------------------- ::rtl::OUString SAL_CALL ODatabaseDocument::getURL( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); return m_pImpl->m_sRealFileURL; } // ----------------------------------------------------------------------------- Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getArgs( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); return m_pImpl->m_aArgs; } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::connectController( const Reference< XController >& _xController ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); m_pImpl->m_aControllers.push_back(_xController); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::disconnectController( const Reference< XController >& _xController ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); 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; if ( m_pImpl->m_aControllers.empty() ) { // if this was the last view, close the document as a whole // #i51157# / 2006-03-16 / frank.schoenheit@sun.com try { close( sal_True ); } catch( const CloseVetoException& ) { // okay, somebody vetoed and took ownership } } } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::lockControllers( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); ++m_pImpl->m_nControllerLockCount; } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::unlockControllers( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); --m_pImpl->m_nControllerLockCount; } // ----------------------------------------------------------------------------- sal_Bool SAL_CALL ODatabaseDocument::hasControllersLocked( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); return m_pImpl->m_nControllerLockCount != 0; } // ----------------------------------------------------------------------------- Reference< XController > SAL_CALL ODatabaseDocument::getCurrentController() throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); return m_pImpl->m_xCurrentController.is() ? m_pImpl->m_xCurrentController : ( m_pImpl->m_aControllers.empty() ? Reference< XController >() : *m_pImpl->m_aControllers.begin() ); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::setCurrentController( const Reference< XController >& _xController ) throw (NoSuchElementException, RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); m_pImpl->m_xCurrentController = _xController; } // ----------------------------------------------------------------------------- Reference< XInterface > SAL_CALL ODatabaseDocument::getCurrentSelection( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); Reference< XInterface > xRet; Reference< XSelectionSupplier > xDocView( getCurrentController(), UNO_QUERY ); if ( xDocView.is() ) xRet.set(xDocView->getSelection(),UNO_QUERY); return xRet; } // ----------------------------------------------------------------------------- // XStorable sal_Bool SAL_CALL ODatabaseDocument::hasLocation( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); return m_pImpl->m_sRealFileURL.getLength() != 0; } // ----------------------------------------------------------------------------- ::rtl::OUString SAL_CALL ODatabaseDocument::getLocation( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); return m_pImpl->m_sRealFileURL; } // ----------------------------------------------------------------------------- sal_Bool SAL_CALL ODatabaseDocument::isReadonly( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); return m_pImpl->m_bDocumentReadOnly; } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::store( ) throw (IOException, RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); if ( m_pImpl->m_sFileURL == m_pImpl->m_sRealFileURL ) store( m_pImpl->m_sFileURL, m_pImpl->m_aArgs ); else storeAsURL( m_pImpl->m_sRealFileURL, m_pImpl->m_aArgs ); impl_notifyEvent( "OnSaveDone", aGuard ); } // ----------------------------------------------------------------------------- void ODatabaseDocument::store(const ::rtl::OUString& _rURL ,const Sequence< PropertyValue >& _rArguments) { OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); if ( m_pImpl->m_bDocumentReadOnly ) throw IOException(); m_pImpl->commitStorages(); Reference xMyStorage = m_pImpl->getStorage(); OSL_ENSURE( xMyStorage.is(), "ODatabaseDocument::storeToURL: no own storage?" ); if ( !xMyStorage.is() ) { IOException aError; aError.Message = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Internal error: no source storage available." ) ); aError.Context = *this; throw IOException( aError ); } writeStorage(_rURL,_rArguments,xMyStorage); m_pImpl->commitRootStorage(); setModified(sal_False); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::storeAsURL( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); Reference< XSingleServiceFactory > xStorageFactory( m_pImpl->createStorageFactory() ); if ( !xStorageFactory.is() ) throw RuntimeException(); // don't use _rURL - we might be recovering/salvaging a file currently ... // #i45314# / 2005-03-21 / frank.schoenheit@sun.com ::comphelper::MediaDescriptor aDescriptor( _rArguments ); sal_Bool bLocationChanged = ( _rURL != m_pImpl->m_sFileURL ); if ( bLocationChanged ) { Sequence aParam(2); aParam[0] <<= _rURL; aParam[1] <<= ElementModes::READWRITE | ElementModes::TRUNCATE; Reference xStorage; ::rtl::OUString sOriginalExceptionType; ::rtl::OUString sOriginalExceptionMessage; try { xStorage.set(xStorageFactory->createInstanceWithArguments( aParam ),UNO_QUERY); } catch ( const Exception& e ) { Any aException( ::cppu::getCaughtException() ); sOriginalExceptionType = aException.getValueTypeName(); sOriginalExceptionMessage = e.Message; } if ( !xStorage.is() ) { // TODO: localize this ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii( "Could not store the database document to '" ); sMessage += _rURL; sMessage += ::rtl::OUString::createFromAscii( "'." ); if ( sOriginalExceptionMessage.getLength() ) { sMessage += ::rtl::OUString::createFromAscii( "\noriginal error message: " ); sMessage += sOriginalExceptionMessage; } if ( sOriginalExceptionType.getLength() ) { sMessage += ::rtl::OUString::createFromAscii( "\noriginal error type: " ); sMessage += sOriginalExceptionType; } throw IOException( sMessage, *this ); } if ( m_pImpl->isEmbeddedDatabase() ) m_pImpl->clearConnections(); m_pImpl->commitEmbeddedStorage(); Reference xMyStorage = m_pImpl->getStorage(); if ( xMyStorage.is() ) { m_pImpl->commitStorages(); xMyStorage->copyToStorage( xStorage ); } m_pImpl->disposeStorages(); m_pImpl->m_xStorage = xStorage; if ( m_pImpl->m_bOwnStorage ) ::comphelper::disposeComponent(xMyStorage); else m_pImpl->m_bOwnStorage = sal_True; m_pImpl->m_bDocumentReadOnly = sal_False; if ( _rURL != m_pImpl->m_sRealFileURL ) { if ( m_pImpl->m_pDBContext ) { if ( m_pImpl->m_sRealFileURL.getLength() ) m_pImpl->m_pDBContext->nameChangePrivate(m_pImpl->m_sRealFileURL,_rURL); else m_pImpl->m_pDBContext->registerPrivate(_rURL,m_pImpl); } INetURLObject aURL( _rURL ); if( aURL.GetProtocol() != INET_PROT_NOT_VALID ) m_pImpl->m_sName = _rURL; } m_pImpl->m_sRealFileURL = m_pImpl->m_sFileURL = _rURL; } lcl_stripLoadArguments( aDescriptor, m_pImpl->m_aArgs ); store(m_pImpl->m_sFileURL,_rArguments); impl_notifyEvent( "OnSaveAsDone", aGuard ); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::storeToURL( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); Reference< XSingleServiceFactory > xStorageFactory( m_pImpl->createStorageFactory() ); Sequence aParam(2); aParam[0] <<= _rURL; aParam[1] <<= ElementModes::READWRITE | ElementModes::TRUNCATE; Reference xStorage; if ( xStorageFactory.is() ) xStorage = xStorage.query( xStorageFactory->createInstanceWithArguments( aParam ) ); OSL_ENSURE( xStorage.is(), "ODatabaseDocument::storeToURL: no storage factory!" ); if ( !xStorage.is() ) { IOException aError; aError.Message = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not create a target storage." ) ); aError.Context = *this; throw IOException( aError ); } Reference xMyStorage = m_pImpl->getStorage(); OSL_ENSURE( xMyStorage.is(), "ODatabaseDocument::storeToURL: no own storage?" ); if ( !xMyStorage.is() ) { IOException aError; aError.Message = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Internal error: no source storage available." ) ); aError.Context = *this; throw IOException( aError ); } m_pImpl->commitEmbeddedStorage(); xMyStorage->copyToStorage( xStorage ); writeStorage(_rURL,_rArguments,xStorage); try { Reference xTransact(xStorage,UNO_QUERY); if ( xTransact.is() ) xTransact->commit(); } catch(Exception) { OSL_ENSURE(0,"Exception Caught: Could not store database!"); throw IOException(); } } // ----------------------------------------------------------------------------- // XModifyBroadcaster void SAL_CALL ODatabaseDocument::addModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException) { ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); m_aModifyListeners.addInterface(_xListener); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::removeModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException) { ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); m_aModifyListeners.removeInterface(_xListener); } // ----------------------------------------------------------------------------- // XModifiable sal_Bool SAL_CALL ODatabaseDocument::isModified( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); return m_pImpl->m_bModified; } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::setModified( sal_Bool _bModified ) throw (PropertyVetoException, RuntimeException) { ModelMethodGuard aGuard( *this ); if ( m_pImpl->m_bModified == _bModified ) return; m_pImpl->m_bModified = _bModified; lang::EventObject aEvt( *this ); aGuard.clear(); m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt ); aGuard.reset(); impl_notifyEvent( "OnModifyChanged", aGuard ); } // ::com::sun::star::document::XEventBroadcaster void SAL_CALL ODatabaseDocument::addEventListener(const css::uno::Reference< css::document::XEventListener >& _xListener ) throw (css::uno::RuntimeException) { ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); m_aDocEventListeners.addInterface(_xListener); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::removeEventListener( const css::uno::Reference< css::document::XEventListener >& _xListener ) throw (css::uno::RuntimeException) { ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); m_aDocEventListeners.removeInterface(_xListener); } // ----------------------------------------------------------------------------- // ::com::sun::star::document::XEventListener void SAL_CALL ODatabaseDocument::notifyEvent( const css::document::EventObject& aEvent ) throw (css::uno::RuntimeException) { ModelMethodGuard aGuard( *this ); // used only to forward external events (e.g. for doc creation) from the frame loader // to the global event broadcaster and all other interested doc event listener. impl_notifyEvent( aEvent.EventName, aGuard ); } // ----------------------------------------------------------------------------- // ::com::sun::star::view::XPrintable Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getPrinter( ) throw (RuntimeException) { DBG_ERROR( "ODatabaseDocument::getPrinter: not supported!" ); return Sequence< PropertyValue >(); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::setPrinter( const Sequence< PropertyValue >& /*aPrinter*/ ) throw (IllegalArgumentException, RuntimeException) { DBG_ERROR( "ODatabaseDocument::setPrinter: not supported!" ); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::print( const Sequence< PropertyValue >& /*xOptions*/ ) throw (IllegalArgumentException, RuntimeException) { DBG_ERROR( "ODatabaseDocument::print: not supported!" ); } // ----------------------------------------------------------------------------- void ODatabaseDocument::impl_reparent_nothrow( const WeakReference< XNameAccess >& _rxContainer ) { Reference< XChild > xChild( _rxContainer.get(), UNO_QUERY ); if ( xChild.is() ) xChild->setParent( *this ); } // ----------------------------------------------------------------------------- void ODatabaseDocument::clearObjectContainer( WeakReference< XNameAccess >& _rxContainer) { Reference< XNameAccess > xContainer = _rxContainer; ::comphelper::disposeComponent( xContainer ); Reference< XChild > xChild( _rxContainer.get(),UNO_QUERY ); if ( xChild.is() ) xChild->setParent( NULL ); _rxContainer = Reference< XNameAccess >(); } // ----------------------------------------------------------------------------- Reference< XNameAccess > ODatabaseDocument::impl_getDocumentContainer_throw( ODatabaseModelImpl::ObjectType _eType ) { ModelMethodGuard aGuard( *this ); OSL_POSTCOND( m_pImpl.is(), "ODatabaseDocument::impl_getDocumentContainer_throw: Impl is NULL" ); if ( ( _eType != ODatabaseModelImpl::E_FORM ) && ( _eType != ODatabaseModelImpl::E_REPORT ) ) throw IllegalArgumentException(); bool bFormsContainer = _eType == ODatabaseModelImpl::E_FORM; WeakReference< XNameAccess >& rContainerRef( bFormsContainer ? m_xForms : m_xReports ); Reference< XNameAccess > xContainer = rContainerRef; if ( !xContainer.is() ) { if ( !m_pImpl->m_aContainer[ _eType ].get() ) { m_pImpl->m_aContainer[ _eType ] = TContentPtr( new ODefinitionContainer_Impl ); m_pImpl->m_aContainer[ _eType ]->m_pDataSource = m_pImpl.get(); m_pImpl->m_aContainer[ _eType ]->m_aProps.aTitle = ::rtl::OUString::createFromAscii( bFormsContainer ? "forms" : "reports" ); } rContainerRef = xContainer = new ODocumentContainer( m_pImpl->m_xServiceFactory, *this, m_pImpl->m_aContainer[ _eType ], bFormsContainer ); impl_reparent_nothrow( xContainer ); } return xContainer; } // ----------------------------------------------------------------------------- void ODatabaseDocument::impl_closeControllerFrames( sal_Bool _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 ) { if ( aIter->is() ) { try { Reference< XCloseable> xFrame( (*aIter)->getFrame(), UNO_QUERY ); if ( xFrame.is() ) xFrame->close( _bDeliverOwnership ); } catch( const CloseVetoException& ) { throw; } catch( const Exception& ) { OSL_ENSURE( sal_False, "ODatabaseDocument::impl_closeControllerFrames: caught an unexpected exception!" ); } } } } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw (::com::sun::star::util::CloseVetoException, RuntimeException) { ModelMethodGuard aGuard( *this ); lang::EventObject aEvent( *this ); { aGuard.clear(); m_aCloseListener.forEach< XCloseListener >( boost::bind( &XCloseListener::queryClosing, _1, boost::cref( aEvent ), boost::cref( _bDeliverOwnership ) ) ); aGuard.reset(); } impl_closeControllerFrames( _bDeliverOwnership ); { aGuard.clear(); m_aCloseListener.notifyEach( &XCloseListener::notifyClosing, aEvent ); aGuard.reset(); } dispose(); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::addCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) { ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); m_aCloseListener.addInterface(Listener); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::removeCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) { ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); m_aCloseListener.removeInterface(Listener); } // ----------------------------------------------------------------------------- Reference< XNameAccess > SAL_CALL ODatabaseDocument::getFormDocuments( ) throw (RuntimeException) { return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_FORM ); } // ----------------------------------------------------------------------------- Reference< XNameAccess > SAL_CALL ODatabaseDocument::getReportDocuments( ) throw (RuntimeException) { return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_REPORT ); } // ----------------------------------------------------------------------------- sal_Bool ODatabaseDocument::WriteThroughComponent( const Reference & xComponent, const sal_Char* pStreamName, const sal_Char* pServiceName, const Sequence & rArguments, const Sequence & rMediaDesc, sal_Bool bPlainStream ,const Reference& _xStorageToSaveTo) { OSL_ENSURE( NULL != pStreamName, "Need stream name!" ); OSL_ENSURE( NULL != pServiceName, "Need service name!" ); Reference xMyStorage = _xStorageToSaveTo; // open stream ::rtl::OUString sStreamName = ::rtl::OUString::createFromAscii( pStreamName ); Reference xStream = xMyStorage->openStreamElement( sStreamName,ElementModes::READWRITE | ElementModes::TRUNCATE ); if ( !xStream.is() ) return sal_False; Reference xOutputStream = xStream->getOutputStream(); OSL_ENSURE(xOutputStream.is(), "Can't create output stream in package!"); if ( ! xOutputStream.is() ) return sal_False; Reference xStreamProp(xOutputStream,UNO_QUERY); OSL_ENSURE(xStreamProp.is(),"No valid preoperty set for the output stream!"); Reference xSeek(xStreamProp,UNO_QUERY); if ( xSeek.is() ) { OSL_TRACE("Length of stream %i",(int)xSeek->getPosition()); xSeek->seek(0); } String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); ::rtl::OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); Any aAny; aAny <<= aMime; xStreamProp->setPropertyValue( aPropName, aAny ); if( bPlainStream ) { sal_Bool bFalse = sal_False; aAny.setValue( &bFalse, ::getBooleanCppuType() ); xStreamProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Compressed") ), aAny ); } else { sal_Bool bTrue = sal_True; aAny.setValue( &bTrue, ::getBooleanCppuType() ); xStreamProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Encrypted") ), aAny ); } // set buffer and create outputstream // write the stuff sal_Bool bRet = WriteThroughComponent( xOutputStream, xComponent, pServiceName, rArguments, rMediaDesc ); // finally, commit stream. return bRet; } sal_Bool ODatabaseDocument::WriteThroughComponent( const Reference & xOutputStream, const Reference & xComponent, const sal_Char* pServiceName, const Sequence & rArguments, const Sequence & rMediaDesc) { OSL_ENSURE( xOutputStream.is(), "I really need an output stream!" ); OSL_ENSURE( xComponent.is(), "Need component!" ); OSL_ENSURE( NULL != pServiceName, "Need component name!" ); // get component Reference< XActiveDataSource > xSaxWriter( m_pImpl->m_xServiceFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer"))), UNO_QUERY ); OSL_ENSURE( xSaxWriter.is(), "can't instantiate XML com.sun.star.xml.sax.Writer" ); if(!xSaxWriter.is()) return sal_False; // connect XML writer to output stream xSaxWriter->setOutputStream( xOutputStream ); // prepare arguments (prepend doc handler to given arguments) Reference xDocHandler( xSaxWriter,UNO_QUERY); Sequence aArgs( 1 + rArguments.getLength() ); aArgs[0] <<= xDocHandler; for(sal_Int32 i = 0; i < rArguments.getLength(); i++) aArgs[i+1] = rArguments[i]; // get filter component Reference< XExporter > xExporter( m_pImpl->m_xServiceFactory->createInstanceWithArguments( ::rtl::OUString::createFromAscii(pServiceName), aArgs), UNO_QUERY); OSL_ENSURE( xExporter.is(), "can't instantiate export filter component" ); if( !xExporter.is() ) return sal_False; // connect model and filter xExporter->setSourceDocument( xComponent ); // filter! Reference xFilter( xExporter, UNO_QUERY ); return xFilter->filter( rMediaDesc ); } // ----------------------------------------------------------------------------- void ODatabaseDocument::writeStorage(const ::rtl::OUString& _rURL ,const Sequence< PropertyValue >& _rArguments ,const Reference& _xStorageToSaveTo) { // create XStatusIndicator Reference xStatusIndicator; Sequence< Any > aDelegatorArguments; ::comphelper::MediaDescriptor aDescriptor( _rArguments ); lcl_extractAndStartStatusIndicator( aDescriptor, xStatusIndicator, aDelegatorArguments ); // properties Sequence < PropertyValue > aProps( _rURL.getLength() ? 1 : 0 ); if( _rURL.getLength() ) { PropertyValue *pProps = aProps.getArray(); pProps->Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FileName") ); (pProps++)->Value <<= _rURL; } // export sub streams for package, else full stream into a file sal_Bool bWarn = sal_False, bErr = sal_False; String sWarnFile, sErrFile; Reference xProp(_xStorageToSaveTo,UNO_QUERY); if ( xProp.is() ) { static const ::rtl::OUString sPropName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MediaType")); Any aAny; aAny <<= MIMETYPE_OASIS_OPENDOCUMENT_DATABASE; xProp->setPropertyValue( sPropName, aAny ); } Reference xCom(static_cast(this),UNO_QUERY); if( !bErr ) { if( !WriteThroughComponent( xCom, "settings.xml", "com.sun.star.comp.sdb.XMLSettingsExporter", aDelegatorArguments, aProps, sal_True,_xStorageToSaveTo ) ) { if( !bWarn ) { bWarn = sal_True; sWarnFile = String( RTL_CONSTASCII_STRINGPARAM("settings.xml"), RTL_TEXTENCODING_ASCII_US ); } } } if ( !bErr ) { if( !WriteThroughComponent( xCom, "content.xml", "com.sun.star.comp.sdb.DBExportFilter", aDelegatorArguments, aProps, sal_True,_xStorageToSaveTo ) ) { bErr = sal_True; sErrFile = String( RTL_CONSTASCII_STRINGPARAM("content.xml"), RTL_TEXTENCODING_ASCII_US ); } } if ( xStatusIndicator.is() ) xStatusIndicator->end(); } // ----------------------------------------------------------------------------- Reference< ::com::sun::star::ui::XUIConfigurationManager > SAL_CALL ODatabaseDocument::getUIConfigurationManager( ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); if ( !m_xUIConfigurationManager.is() ) { m_xUIConfigurationManager = Reference< ::com::sun::star::ui::XUIConfigurationManager >( m_pImpl->m_xServiceFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ui.UIConfigurationManager" )), UNO_QUERY ); Reference< ::com::sun::star::ui::XUIConfigurationStorage > xUIConfigStorage( m_xUIConfigurationManager, UNO_QUERY ); if ( xUIConfigStorage.is() ) { rtl::OUString aUIConfigFolderName( RTL_CONSTASCII_USTRINGPARAM( "Configurations2" )); Reference< XStorage > xConfigStorage; // First try to open with READWRITE and then READ xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READWRITE ); if ( xConfigStorage.is() ) { rtl::OUString aMediaTypeProp( RTL_CONSTASCII_USTRINGPARAM( "MediaType" )); rtl::OUString aUIConfigMediaType( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.xml.ui.configuration" )); rtl::OUString aMediaType; Reference< XPropertySet > xPropSet( xConfigStorage, UNO_QUERY ); Any a = xPropSet->getPropertyValue( aMediaTypeProp ); if ( !( a >>= aMediaType ) || ( aMediaType.getLength() == 0 )) { a <<= aUIConfigMediaType; xPropSet->setPropertyValue( aMediaTypeProp, a ); } } else xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READ ); // initialize ui configuration manager with document substorage xUIConfigStorage->setStorage( xConfigStorage ); } } return m_xUIConfigurationManager; } // ----------------------------------------------------------------------------- Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentSubStorage( const ::rtl::OUString& aStorageName, sal_Int32 nMode ) throw (RuntimeException) { ModelMethodGuard aGuard( *this ); Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() ); return xStorageAccess->getDocumentSubStorage( aStorageName, nMode ); } // ----------------------------------------------------------------------------- Sequence< ::rtl::OUString > SAL_CALL ODatabaseDocument::getDocumentSubStoragesNames( ) throw (::com::sun::star::io::IOException, RuntimeException) { Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() ); return xStorageAccess->getDocumentSubStoragesNames(); } // ----------------------------------------------------------------------------- void ODatabaseDocument::impl_notifyEvent( const ::rtl::OUString& _sEventName, ::osl::ClearableMutexGuard& _rGuard ) { try { css::document::EventObject aEvt(*this, _sEventName); _rGuard.clear(); m_aDocEventListeners.notifyEach( &css::document::XEventListener::notifyEvent, aEvt ); } catch(Exception&) { } } //------------------------------------------------------------------------------ void ODatabaseDocument::disposing() { if ( !m_pImpl.is() ) { // this means that we're already disposed DBG_ASSERT( ODatabaseDocument_OfficeDocument::rBHelper.bDisposed, "ODatabaseDocument::disposing: no impl anymore, but not yet disposed!" ); return; } DBG_ASSERT( m_pImpl->m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); // normally, nobody should explicitly dispose, but only XCloseable::close the document.An upon // closing, our controllers are closed, too m_pImpl->m_aControllers.clear(); Reference< XModel > xHoldAlive( this ); { { ::osl::ClearableMutexGuard aGuard( getMutex() ); impl_notifyEvent( "OnUnload", aGuard ); } css::lang::EventObject aDisposeEvent(static_cast(this)); m_aModifyListeners.disposeAndClear( aDisposeEvent ); m_aCloseListener.disposeAndClear( aDisposeEvent ); m_aDocEventListeners.disposeAndClear( aDisposeEvent ); m_xUIConfigurationManager = NULL; clearObjectContainer( m_xForms); clearObjectContainer( m_xReports); m_pImpl->modelIsDisposing( ODatabaseModelImpl::ResetModelAccess() ); } m_pImpl.clear(); } // ----------------------------------------------------------------------------- // XComponent void SAL_CALL ODatabaseDocument::dispose( ) throw (RuntimeException) { ::cppu::WeakComponentImplHelperBase::dispose(); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::addEventListener( const Reference< css::lang::XEventListener >& _xListener ) throw (RuntimeException) { ::cppu::WeakComponentImplHelperBase::addEventListener(_xListener); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::removeEventListener( const Reference< css::lang::XEventListener >& _xListener ) throw (RuntimeException) { ::cppu::WeakComponentImplHelperBase::removeEventListener(_xListener); } // XServiceInfo //------------------------------------------------------------------------------ rtl::OUString ODatabaseDocument::getImplementationName( ) throw(RuntimeException) { return getImplementationName_Static(); } //------------------------------------------------------------------------------ rtl::OUString ODatabaseDocument::getImplementationName_Static( ) throw(RuntimeException) { return rtl::OUString::createFromAscii("com.sun.star.comp.dba.ODatabaseDocument"); } //------------------------------------------------------------------------------ Sequence< ::rtl::OUString > ODatabaseDocument::getSupportedServiceNames( ) throw (RuntimeException) { return getSupportedServiceNames_Static(); } //------------------------------------------------------------------------------ Reference< XInterface > ODatabaseDocument::Create(const Reference< XMultiServiceFactory >& _rxFactory) { return ODatabaseDocument_CreateInstance(_rxFactory); } //------------------------------------------------------------------------------ Sequence< ::rtl::OUString > ODatabaseDocument::getSupportedServiceNames_Static( ) throw (RuntimeException) { Sequence< ::rtl::OUString > aSNS( 2 ); aSNS[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.OfficeDatabaseDocument")); aSNS[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.OfficeDocument")); return aSNS; } //------------------------------------------------------------------------------ sal_Bool ODatabaseDocument::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) { return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; } // ----------------------------------------------------------------------------- Reference< XDataSource > SAL_CALL ODatabaseDocument::getDataSource() throw (RuntimeException) { ModelMethodGuard aGuard( *this ); OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); return m_pImpl->getDataSource(); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException) { if ( m_pImpl.is() ) m_pImpl->disposing(Source); } //------------------------------------------------------------------ Reference< XInterface > ODatabaseDocument::getThis() { return *this; } //------------------------------------------------------------------ //........................................................................ } // namespace dbaccess //........................................................................