summaryrefslogtreecommitdiff
path: root/ucb/source/ucp/tdoc/tdoc_docmgr.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'ucb/source/ucp/tdoc/tdoc_docmgr.cxx')
-rw-r--r--ucb/source/ucp/tdoc/tdoc_docmgr.cxx691
1 files changed, 691 insertions, 0 deletions
diff --git a/ucb/source/ucp/tdoc/tdoc_docmgr.cxx b/ucb/source/ucp/tdoc/tdoc_docmgr.cxx
new file mode 100644
index 000000000000..46aa1ae69ec3
--- /dev/null
+++ b/ucb/source/ucp/tdoc/tdoc_docmgr.cxx
@@ -0,0 +1,691 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ - filter unwanted models notified by global document event broadcaster
+ - help documents
+ - others, which I don't know yet
+
+ *************************************************************************/
+
+#include "osl/diagnose.h"
+#include "rtl/ref.hxx"
+#include "cppuhelper/weak.hxx"
+
+#include "comphelper/namedvaluecollection.hxx"
+#include "comphelper/documentinfo.hxx"
+
+#include "com/sun/star/beans/XPropertySet.hpp"
+#include "com/sun/star/container/XEnumerationAccess.hpp"
+#include "com/sun/star/frame/XStorable.hpp"
+#include "com/sun/star/lang/DisposedException.hpp"
+#include "com/sun/star/document/XStorageBasedDocument.hpp"
+#include "com/sun/star/awt/XTopWindow.hpp"
+
+#include "tdoc_docmgr.hxx"
+
+using namespace com::sun::star;
+using namespace tdoc_ucp;
+using ::comphelper::DocumentInfo;
+
+//=========================================================================
+//=========================================================================
+//
+// OfficeDocumentsManager Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+OfficeDocumentsManager::OfficeDocumentsManager(
+ const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
+ OfficeDocumentsEventListener * pDocEventListener )
+: m_xSMgr( xSMgr ),
+ m_xDocEvtNotifier( createDocumentEventNotifier( xSMgr ) ),
+ m_pDocEventListener( pDocEventListener )
+{
+ if ( m_xDocEvtNotifier.is() )
+ {
+ // Order is important (multithreaded environment)
+ m_xDocEvtNotifier->addEventListener( this );
+ buildDocumentsList();
+ }
+}
+
+//=========================================================================
+// virtual
+OfficeDocumentsManager::~OfficeDocumentsManager()
+{
+ OSL_ENSURE( m_aDocs.empty(), "document list not empty!" );
+}
+
+//=========================================================================
+void OfficeDocumentsManager::destroy()
+{
+ if ( m_xDocEvtNotifier.is() )
+ m_xDocEvtNotifier->removeEventListener( this );
+}
+
+//=========================================================================
+static rtl::OUString
+getDocumentId( const uno::Reference< uno::XInterface > & xDoc )
+{
+ rtl::OUString aId;
+
+ // Try to get the UID directly from the document.
+ uno::Reference< beans::XPropertySet > xPropSet( xDoc, uno::UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ try
+ {
+ uno::Any aValue = xPropSet->getPropertyValue(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "RuntimeUID" ) ) );
+ aValue >>= aId;
+ }
+ catch ( beans::UnknownPropertyException const & )
+ {
+ // Not actually an error. Property is optional.
+ }
+ catch ( lang::WrappedTargetException const & )
+ {
+ OSL_ENSURE( false, "Caught WrappedTargetException!" );
+ }
+ }
+
+ if ( aId.getLength() == 0 )
+ {
+ // fallback: generate UID from document's this pointer.
+ // normalize the interface pointer first. Else, calls with different
+ // interfaces to the same object (say, XFoo and XBar) will produce
+ // different IDs
+ uno::Reference< uno::XInterface > xNormalizedIFace( xDoc, uno::UNO_QUERY );
+ sal_Int64 nId = reinterpret_cast< sal_Int64 >( xNormalizedIFace.get() );
+ aId = rtl::OUString::valueOf( nId );
+ }
+
+ OSL_ENSURE( aId.getLength() > 0, "getDocumentId - Empty id!" );
+ return aId;
+}
+
+//=========================================================================
+//
+// document::XEventListener
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL OfficeDocumentsManager::notifyEvent(
+ const document::EventObject & Event )
+ throw ( uno::RuntimeException )
+{
+/*
+ Events documentation: OOo Developer's Guide / Writing UNO Components / Jobs
+*/
+
+ if ( Event.EventName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "OnLoadFinished" ) ) // document loaded
+ || Event.EventName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "OnCreate" ) ) ) // document created
+ {
+ if ( isOfficeDocument( Event.Source ) )
+ {
+ osl::MutexGuard aGuard( m_aMtx );
+
+ uno::Reference< frame::XModel >
+ xModel( Event.Source, uno::UNO_QUERY );
+ OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
+
+ DocumentList::const_iterator it = m_aDocs.begin();
+ while ( it != m_aDocs.end() )
+ {
+ if ( (*it).second.xModel == xModel )
+ {
+ // already known.
+ break;
+ }
+ ++it;
+ }
+
+ if ( it == m_aDocs.end() )
+ {
+ // new document
+
+ uno::Reference< document::XStorageBasedDocument >
+ xDoc( Event.Source, uno::UNO_QUERY );
+ OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" );
+
+ uno::Reference< embed::XStorage > xStorage
+ = xDoc->getDocumentStorage();
+ OSL_ENSURE( xStorage.is(), "Got no document storage!" );
+
+ rtl:: OUString aDocId = getDocumentId( Event.Source );
+ rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
+
+ m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel );
+
+ // Propagate document closure.
+ OSL_ENSURE( m_pDocEventListener,
+ "OnLoadFinished/OnCreate event: no owner for insert event propagation!" );
+
+ if ( m_pDocEventListener )
+ m_pDocEventListener->notifyDocumentOpened( aDocId );
+ }
+ }
+ }
+ else if ( Event.EventName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "OnUnload" ) ) )
+ {
+ if ( isOfficeDocument( Event.Source ) )
+ {
+ // Document has been closed (unloaded)
+
+ osl::MutexGuard aGuard( m_aMtx );
+
+ uno::Reference< frame::XModel >
+ xModel( Event.Source, uno::UNO_QUERY );
+ OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
+
+ DocumentList::iterator it = m_aDocs.begin();
+ while ( it != m_aDocs.end() )
+ {
+ if ( (*it).second.xModel == xModel )
+ {
+ // Propagate document closure.
+ OSL_ENSURE( m_pDocEventListener,
+ "OnUnload event: no owner for close event propagation!" );
+
+ if ( m_pDocEventListener )
+ {
+ rtl::OUString aDocId( (*it).first );
+ m_pDocEventListener->notifyDocumentClosed( aDocId );
+ }
+
+
+ break;
+ }
+ ++it;
+ }
+
+ OSL_ENSURE( it != m_aDocs.end(),
+ "OnUnload event notified for unknown document!" );
+
+ if( it != m_aDocs.end() )
+ m_aDocs.erase( it );
+ }
+ }
+ else if ( Event.EventName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "OnSaveDone" ) ) )
+ {
+ if ( isOfficeDocument( Event.Source ) )
+ {
+ osl::MutexGuard aGuard( m_aMtx );
+
+ uno::Reference< frame::XModel >
+ xModel( Event.Source, uno::UNO_QUERY );
+ OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
+
+ DocumentList::iterator it = m_aDocs.begin();
+ while ( it != m_aDocs.end() )
+ {
+ if ( (*it).second.xModel == xModel )
+ {
+ // Storage gets exchanged while saving.
+ uno::Reference< document::XStorageBasedDocument >
+ xDoc( Event.Source, uno::UNO_QUERY );
+ OSL_ENSURE( xDoc.is(),
+ "Got no document::XStorageBasedDocument!" );
+
+ uno::Reference< embed::XStorage > xStorage
+ = xDoc->getDocumentStorage();
+ OSL_ENSURE( xStorage.is(), "Got no document storage!" );
+
+ (*it).second.xStorage = xStorage;
+ break;
+ }
+ ++it;
+ }
+
+ OSL_ENSURE( it != m_aDocs.end(),
+ "OnSaveDone event notified for unknown document!" );
+ }
+ }
+ else if ( Event.EventName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "OnSaveAsDone" ) ) )
+ {
+ if ( isOfficeDocument( Event.Source ) )
+ {
+ osl::MutexGuard aGuard( m_aMtx );
+
+ uno::Reference< frame::XModel >
+ xModel( Event.Source, uno::UNO_QUERY );
+ OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
+
+ DocumentList::iterator it = m_aDocs.begin();
+ while ( it != m_aDocs.end() )
+ {
+ if ( (*it).second.xModel == xModel )
+ {
+ // Storage gets exchanged while saving.
+ uno::Reference< document::XStorageBasedDocument >
+ xDoc( Event.Source, uno::UNO_QUERY );
+ OSL_ENSURE( xDoc.is(),
+ "Got no document::XStorageBasedDocument!" );
+
+ uno::Reference< embed::XStorage > xStorage
+ = xDoc->getDocumentStorage();
+ OSL_ENSURE( xStorage.is(), "Got no document storage!" );
+
+ (*it).second.xStorage = xStorage;
+
+ // Adjust title.
+ (*it).second.aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
+ break;
+ }
+ ++it;
+ }
+
+ OSL_ENSURE( it != m_aDocs.end(),
+ "OnSaveAsDone event notified for unknown document!" );
+ }
+ }
+ else if ( Event.EventName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "OnTitleChanged" ) ) )
+ {
+ if ( isOfficeDocument( Event.Source ) )
+ {
+ osl::MutexGuard aGuard( m_aMtx );
+
+ uno::Reference< frame::XModel >
+ xModel( Event.Source, uno::UNO_QUERY );
+ OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
+
+ DocumentList::iterator it = m_aDocs.begin();
+ while ( it != m_aDocs.end() )
+ {
+ if ( (*it).second.xModel == xModel )
+ {
+ // Adjust title.
+ rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
+ (*it).second.aTitle = aTitle;
+
+ // Adjust storage.
+ uno::Reference< document::XStorageBasedDocument >
+ xDoc( Event.Source, uno::UNO_QUERY );
+ OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" );
+
+ uno::Reference< embed::XStorage > xStorage
+ = xDoc->getDocumentStorage();
+ OSL_ENSURE( xDoc.is(), "Got no document storage!" );
+
+ rtl:: OUString aDocId = getDocumentId( Event.Source );
+
+ m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel );
+ break;
+ }
+ ++it;
+ }
+
+ OSL_ENSURE( it != m_aDocs.end(),
+ "TitleChanged event notified for unknown document!" );
+ }
+ }
+}
+
+//=========================================================================
+//
+// lang::XEventListener (base of document::XEventListener)
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL OfficeDocumentsManager::disposing(
+ const lang::EventObject& /*Source*/ )
+ throw ( uno::RuntimeException )
+{
+}
+
+//=========================================================================
+//
+// Non-interface.
+//
+//=========================================================================
+
+// static
+uno::Reference< document::XEventBroadcaster >
+OfficeDocumentsManager::createDocumentEventNotifier(
+ const uno::Reference< lang::XMultiServiceFactory >& rXSMgr )
+{
+ uno::Reference< uno::XInterface > xIfc;
+ try
+ {
+ xIfc = rXSMgr->createInstance(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.frame.GlobalEventBroadcaster" ) ) );
+ }
+ catch ( uno::Exception const & )
+ {
+ // handled below.
+ }
+
+ OSL_ENSURE(
+ xIfc.is(),
+ "Could not instanciate com.sun.star.frame.GlobalEventBroadcaster" );
+
+ if ( xIfc.is() )
+ {
+ uno::Reference< document::XEventBroadcaster > xBC(
+ xIfc, uno::UNO_QUERY );
+
+ OSL_ENSURE(
+ xBC.is(),
+ "com.sun.star.frame.GlobalEventBroadcaster does not implement "
+ "interface com.sun.star.document.XEventBroadcaster!" );
+
+ return xBC;
+ }
+ else
+ return uno::Reference< document::XEventBroadcaster >();
+}
+
+//=========================================================================
+void OfficeDocumentsManager::buildDocumentsList()
+{
+ OSL_ENSURE( m_xDocEvtNotifier.is(),
+ "OfficeDocumentsManager::buildDocumentsList - "
+ "No document event notifier!" );
+
+ uno::Reference< container::XEnumerationAccess > xEnumAccess(
+ m_xDocEvtNotifier, uno::UNO_QUERY_THROW );
+
+ uno::Reference< container::XEnumeration > xEnum
+ = xEnumAccess->createEnumeration();
+
+ osl::MutexGuard aGuard( m_aMtx );
+
+ while ( xEnum->hasMoreElements() )
+ {
+ uno::Any aValue = xEnum->nextElement();
+ // container::NoSuchElementException
+ // lang::WrappedTargetException
+
+ try
+ {
+ uno::Reference< frame::XModel > xModel;
+ aValue >>= xModel;
+
+ if ( xModel.is() )
+ {
+ if ( isOfficeDocument( xModel ) )
+ {
+ DocumentList::const_iterator it = m_aDocs.begin();
+ while ( it != m_aDocs.end() )
+ {
+ if ( (*it).second.xModel == xModel )
+ {
+ // already known.
+ break;
+ }
+ ++it;
+ }
+
+ if ( it == m_aDocs.end() )
+ {
+ // new document
+ rtl::OUString aDocId = getDocumentId( xModel );
+ rtl::OUString aTitle = DocumentInfo::getDocumentTitle( xModel );
+
+ uno::Reference< document::XStorageBasedDocument >
+ xDoc( xModel, uno::UNO_QUERY );
+ OSL_ENSURE( xDoc.is(),
+ "Got no document::XStorageBasedDocument!" );
+
+ uno::Reference< embed::XStorage > xStorage
+ = xDoc->getDocumentStorage();
+ OSL_ENSURE( xDoc.is(), "Got no document storage!" );
+
+ m_aDocs[ aDocId ]
+ = StorageInfo( aTitle, xStorage, xModel );
+ }
+ }
+ }
+ }
+ catch ( lang::DisposedException const & )
+ {
+ // Note: Due to race conditions the XEnumeration can
+ // contains docs that already have been closed
+ }
+ }
+}
+
+//=========================================================================
+uno::Reference< embed::XStorage >
+OfficeDocumentsManager::queryStorage( const rtl::OUString & rDocId )
+{
+ osl::MutexGuard aGuard( m_aMtx );
+
+ DocumentList::const_iterator it = m_aDocs.find( rDocId );
+ if ( it == m_aDocs.end() )
+ return uno::Reference< embed::XStorage >();
+
+ return (*it).second.xStorage;
+}
+
+//=========================================================================
+rtl::OUString OfficeDocumentsManager::queryDocumentId(
+ const uno::Reference< frame::XModel > & xModel )
+{
+ return getDocumentId( xModel );
+}
+
+//=========================================================================
+uno::Reference< frame::XModel >
+OfficeDocumentsManager::queryDocumentModel( const rtl::OUString & rDocId )
+{
+ osl::MutexGuard aGuard( m_aMtx );
+
+ DocumentList::const_iterator it = m_aDocs.find( rDocId );
+ if ( it == m_aDocs.end() )
+ return uno::Reference< frame::XModel >();
+
+ return (*it).second.xModel;
+}
+
+//=========================================================================
+uno::Sequence< rtl::OUString > OfficeDocumentsManager::queryDocuments()
+{
+ osl::MutexGuard aGuard( m_aMtx );
+
+ uno::Sequence< rtl::OUString > aRet( m_aDocs.size() );
+ sal_Int32 nPos = 0;
+
+ DocumentList::const_iterator it = m_aDocs.begin();
+ while ( it != m_aDocs.end() )
+ {
+ aRet[ nPos ] = (*it).first;
+ ++it;
+ ++nPos;
+ }
+ return aRet;
+}
+
+//=========================================================================
+rtl::OUString
+OfficeDocumentsManager::queryStorageTitle( const rtl::OUString & rDocId )
+{
+ osl::MutexGuard aGuard( m_aMtx );
+
+ DocumentList::const_iterator it = m_aDocs.find( rDocId );
+ if ( it == m_aDocs.end() )
+ return rtl::OUString();
+
+ return (*it).second.aTitle;
+}
+
+//=========================================================================
+bool OfficeDocumentsManager::isDocumentPreview(
+ const uno::Reference< frame::XModel > & xModel )
+{
+ if ( !xModel.is() )
+ return false;
+
+ ::comphelper::NamedValueCollection aArgs(
+ xModel->getArgs() );
+ sal_Bool bIsPreview = aArgs.getOrDefault( "Preview", sal_False );
+ return bIsPreview;
+}
+
+//=========================================================================
+bool OfficeDocumentsManager::isHelpDocument(
+ const uno::Reference< frame::XModel > & xModel )
+{
+ if ( !xModel.is() )
+ return false;
+
+ ::rtl::OUString sURL( xModel->getURL() );
+ if ( sURL.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.help://" ) ) )
+ return true;
+
+ return false;
+}
+
+//=========================================================================
+bool OfficeDocumentsManager::isWithoutOrInTopLevelFrame(
+ const uno::Reference< frame::XModel > & xModel )
+{
+ if ( !xModel.is() )
+ return false;
+
+ uno::Reference< frame::XController > xController
+ = xModel->getCurrentController();
+ if ( xController.is() )
+ {
+ uno::Reference< frame::XFrame > xFrame
+ = xController->getFrame();
+ if ( xFrame.is() )
+ {
+ // don't use XFrame::isTop here. This nowadays excludes
+ // "sub documents" such as forms embedded in database documents
+ uno::Reference< awt::XTopWindow > xFrameContainer(
+ xFrame->getContainerWindow(), uno::UNO_QUERY );
+ if ( !xFrameContainer.is() )
+ return false;
+ }
+ }
+
+ return true;
+}
+
+//=========================================================================
+bool OfficeDocumentsManager::isBasicIDE(
+ const uno::Reference< frame::XModel > & xModel )
+{
+ if ( !m_xModuleMgr.is() )
+ {
+ osl::MutexGuard aGuard( m_aMtx );
+ if ( !m_xModuleMgr.is() )
+ {
+ try
+ {
+ m_xModuleMgr
+ = uno::Reference<
+ frame::XModuleManager >(
+ m_xSMgr->createInstance(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.frame.ModuleManager" ) ) ),
+ uno::UNO_QUERY );
+ }
+ catch ( uno::Exception const & )
+ {
+ // handled below.
+ }
+
+ OSL_ENSURE( m_xModuleMgr .is(),
+ "Could not instanciate ModuleManager service!" );
+ }
+ }
+
+ if ( m_xModuleMgr.is() )
+ {
+ rtl::OUString aModule;
+ try
+ {
+ aModule = m_xModuleMgr->identify( xModel );
+ }
+ catch ( lang::IllegalArgumentException const & )
+ {
+ OSL_ENSURE( false, "Caught IllegalArgumentException!" );
+ }
+ catch ( frame::UnknownModuleException const & )
+ {
+ OSL_ENSURE( false, "Caught UnknownModuleException!" );
+ }
+
+ if ( aModule.getLength() > 0 )
+ {
+ // Filter unwanted items, that are no real documents.
+ if ( aModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
+ "com.sun.star.script.BasicIDE" ) ) )
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+//=========================================================================
+bool OfficeDocumentsManager::isOfficeDocument(
+ const uno::Reference< uno::XInterface > & xDoc )
+{
+ uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY );
+ uno::Reference< document::XStorageBasedDocument >
+ xStorageBasedDoc( xModel, uno::UNO_QUERY );
+ if ( !xStorageBasedDoc.is() )
+ return false;
+
+ if ( !isWithoutOrInTopLevelFrame( xModel ) )
+ return false;
+
+ if ( isDocumentPreview( xModel ) )
+ return false;
+
+ if ( isHelpDocument( xModel ) )
+ return false;
+
+ if ( isBasicIDE( xModel ) )
+ return false;
+
+ return true;
+}