update dev300-m58
[ooovba.git] / ucb / source / ucp / tdoc / tdoc_docmgr.cxx
blob0d1b236397f8607ad5c3a6e4e5977da8dafb3d09
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tdoc_docmgr.cxx,v $
10 * $Revision: 1.19.24.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
33 /**************************************************************************
34 TODO
35 **************************************************************************
37 - filter unwanted models notified by global document event broadcaster
38 - help documents
39 - others, which I don't know yet
41 *************************************************************************/
43 #include "osl/diagnose.h"
44 #include "rtl/ref.hxx"
45 #include "cppuhelper/weak.hxx"
47 #include "comphelper/namedvaluecollection.hxx"
48 #include "comphelper/documentinfo.hxx"
50 #include "com/sun/star/beans/XPropertySet.hpp"
51 #include "com/sun/star/container/XEnumerationAccess.hpp"
52 #include "com/sun/star/frame/XStorable.hpp"
53 #include "com/sun/star/lang/DisposedException.hpp"
54 #include "com/sun/star/document/XStorageBasedDocument.hpp"
55 #include "com/sun/star/awt/XTopWindow.hpp"
57 #include "tdoc_docmgr.hxx"
59 using namespace com::sun::star;
60 using namespace tdoc_ucp;
61 using ::comphelper::DocumentInfo;
63 //=========================================================================
64 //=========================================================================
66 // OfficeDocumentsManager Implementation.
68 //=========================================================================
69 //=========================================================================
71 OfficeDocumentsManager::OfficeDocumentsManager(
72 const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
73 OfficeDocumentsEventListener * pDocEventListener )
74 : m_xSMgr( xSMgr ),
75 m_xDocEvtNotifier( createDocumentEventNotifier( xSMgr ) ),
76 m_pDocEventListener( pDocEventListener )
78 if ( m_xDocEvtNotifier.is() )
80 // Order is important (multithreaded environment)
81 m_xDocEvtNotifier->addEventListener( this );
82 buildDocumentsList();
86 //=========================================================================
87 // virtual
88 OfficeDocumentsManager::~OfficeDocumentsManager()
90 OSL_ENSURE( m_aDocs.empty(), "document list not empty!" );
93 //=========================================================================
94 void OfficeDocumentsManager::destroy()
96 if ( m_xDocEvtNotifier.is() )
97 m_xDocEvtNotifier->removeEventListener( this );
100 //=========================================================================
101 static rtl::OUString
102 getDocumentId( const uno::Reference< uno::XInterface > & xDoc )
104 rtl::OUString aId;
106 // Try to get the UID directly from the document.
107 uno::Reference< beans::XPropertySet > xPropSet( xDoc, uno::UNO_QUERY );
108 if ( xPropSet.is() )
112 uno::Any aValue = xPropSet->getPropertyValue(
113 rtl::OUString(
114 RTL_CONSTASCII_USTRINGPARAM( "RuntimeUID" ) ) );
115 aValue >>= aId;
117 catch ( beans::UnknownPropertyException const & )
119 // Not actually an error. Property is optional.
121 catch ( lang::WrappedTargetException const & )
123 OSL_ENSURE( false, "Caught WrappedTargetException!" );
127 if ( aId.getLength() == 0 )
129 // fallback: generate UID from document's this pointer.
130 // normalize the interface pointer first. Else, calls with different
131 // interfaces to the same object (say, XFoo and XBar) will produce
132 // different IDs
133 uno::Reference< uno::XInterface > xNormalizedIFace( xDoc, uno::UNO_QUERY );
134 sal_Int64 nId = reinterpret_cast< sal_Int64 >( xNormalizedIFace.get() );
135 aId = rtl::OUString::valueOf( nId );
138 OSL_ENSURE( aId.getLength() > 0, "getDocumentId - Empty id!" );
139 return aId;
142 //=========================================================================
144 // document::XEventListener
146 //=========================================================================
148 // virtual
149 void SAL_CALL OfficeDocumentsManager::notifyEvent(
150 const document::EventObject & Event )
151 throw ( uno::RuntimeException )
154 Events documentation: OOo Developer's Guide / Writing UNO Components / Jobs
157 if ( Event.EventName.equalsAsciiL(
158 RTL_CONSTASCII_STRINGPARAM( "OnLoadFinished" ) ) // document loaded
159 || Event.EventName.equalsAsciiL(
160 RTL_CONSTASCII_STRINGPARAM( "OnCreate" ) ) ) // document created
162 if ( isOfficeDocument( Event.Source ) )
164 osl::MutexGuard aGuard( m_aMtx );
166 uno::Reference< frame::XModel >
167 xModel( Event.Source, uno::UNO_QUERY );
168 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
170 DocumentList::const_iterator it = m_aDocs.begin();
171 while ( it != m_aDocs.end() )
173 if ( (*it).second.xModel == xModel )
175 // already known.
176 break;
178 ++it;
181 if ( it == m_aDocs.end() )
183 // new document
185 uno::Reference< document::XStorageBasedDocument >
186 xDoc( Event.Source, uno::UNO_QUERY );
187 OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" );
189 uno::Reference< embed::XStorage > xStorage
190 = xDoc->getDocumentStorage();
191 OSL_ENSURE( xStorage.is(), "Got no document storage!" );
193 rtl:: OUString aDocId = getDocumentId( Event.Source );
194 rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
196 m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel );
198 // Propagate document closure.
199 OSL_ENSURE( m_pDocEventListener,
200 "OnLoadFinished/OnCreate event: no owner for insert event propagation!" );
202 if ( m_pDocEventListener )
203 m_pDocEventListener->notifyDocumentOpened( aDocId );
207 else if ( Event.EventName.equalsAsciiL(
208 RTL_CONSTASCII_STRINGPARAM( "OnUnload" ) ) )
210 if ( isOfficeDocument( Event.Source ) )
212 // Document has been closed (unloaded)
214 osl::MutexGuard aGuard( m_aMtx );
216 uno::Reference< frame::XModel >
217 xModel( Event.Source, uno::UNO_QUERY );
218 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
220 DocumentList::iterator it = m_aDocs.begin();
221 while ( it != m_aDocs.end() )
223 if ( (*it).second.xModel == xModel )
225 // Propagate document closure.
226 OSL_ENSURE( m_pDocEventListener,
227 "OnUnload event: no owner for close event propagation!" );
229 if ( m_pDocEventListener )
231 rtl::OUString aDocId( (*it).first );
232 m_pDocEventListener->notifyDocumentClosed( aDocId );
236 break;
238 ++it;
241 OSL_ENSURE( it != m_aDocs.end(),
242 "OnUnload event notified for unknown document!" );
244 if( it != m_aDocs.end() )
245 m_aDocs.erase( it );
248 else if ( Event.EventName.equalsAsciiL(
249 RTL_CONSTASCII_STRINGPARAM( "OnSaveDone" ) ) )
251 if ( isOfficeDocument( Event.Source ) )
253 osl::MutexGuard aGuard( m_aMtx );
255 uno::Reference< frame::XModel >
256 xModel( Event.Source, uno::UNO_QUERY );
257 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
259 DocumentList::iterator it = m_aDocs.begin();
260 while ( it != m_aDocs.end() )
262 if ( (*it).second.xModel == xModel )
264 // Storage gets exchanged while saving.
265 uno::Reference< document::XStorageBasedDocument >
266 xDoc( Event.Source, uno::UNO_QUERY );
267 OSL_ENSURE( xDoc.is(),
268 "Got no document::XStorageBasedDocument!" );
270 uno::Reference< embed::XStorage > xStorage
271 = xDoc->getDocumentStorage();
272 OSL_ENSURE( xStorage.is(), "Got no document storage!" );
274 (*it).second.xStorage = xStorage;
275 break;
277 ++it;
280 OSL_ENSURE( it != m_aDocs.end(),
281 "OnSaveDone event notified for unknown document!" );
284 else if ( Event.EventName.equalsAsciiL(
285 RTL_CONSTASCII_STRINGPARAM( "OnSaveAsDone" ) ) )
287 if ( isOfficeDocument( Event.Source ) )
289 osl::MutexGuard aGuard( m_aMtx );
291 uno::Reference< frame::XModel >
292 xModel( Event.Source, uno::UNO_QUERY );
293 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
295 DocumentList::iterator it = m_aDocs.begin();
296 while ( it != m_aDocs.end() )
298 if ( (*it).second.xModel == xModel )
300 // Storage gets exchanged while saving.
301 uno::Reference< document::XStorageBasedDocument >
302 xDoc( Event.Source, uno::UNO_QUERY );
303 OSL_ENSURE( xDoc.is(),
304 "Got no document::XStorageBasedDocument!" );
306 uno::Reference< embed::XStorage > xStorage
307 = xDoc->getDocumentStorage();
308 OSL_ENSURE( xStorage.is(), "Got no document storage!" );
310 (*it).second.xStorage = xStorage;
312 // Adjust title.
313 (*it).second.aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
314 break;
316 ++it;
319 OSL_ENSURE( it != m_aDocs.end(),
320 "OnSaveAsDone event notified for unknown document!" );
323 else if ( Event.EventName.equalsAsciiL(
324 RTL_CONSTASCII_STRINGPARAM( "OnTitleChanged" ) ) )
326 if ( isOfficeDocument( Event.Source ) )
328 osl::MutexGuard aGuard( m_aMtx );
330 uno::Reference< frame::XModel >
331 xModel( Event.Source, uno::UNO_QUERY );
332 OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
334 DocumentList::iterator it = m_aDocs.begin();
335 while ( it != m_aDocs.end() )
337 if ( (*it).second.xModel == xModel )
339 // Adjust title.
340 rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
341 (*it).second.aTitle = aTitle;
343 // Adjust storage.
344 uno::Reference< document::XStorageBasedDocument >
345 xDoc( Event.Source, uno::UNO_QUERY );
346 OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" );
348 uno::Reference< embed::XStorage > xStorage
349 = xDoc->getDocumentStorage();
350 OSL_ENSURE( xDoc.is(), "Got no document storage!" );
352 rtl:: OUString aDocId = getDocumentId( Event.Source );
354 m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel );
355 break;
357 ++it;
360 OSL_ENSURE( it != m_aDocs.end(),
361 "TitleChanged event notified for unknown document!" );
366 //=========================================================================
368 // lang::XEventListener (base of document::XEventListener)
370 //=========================================================================
372 // virtual
373 void SAL_CALL OfficeDocumentsManager::disposing(
374 const lang::EventObject& /*Source*/ )
375 throw ( uno::RuntimeException )
379 //=========================================================================
381 // Non-interface.
383 //=========================================================================
385 // static
386 uno::Reference< document::XEventBroadcaster >
387 OfficeDocumentsManager::createDocumentEventNotifier(
388 const uno::Reference< lang::XMultiServiceFactory >& rXSMgr )
390 uno::Reference< uno::XInterface > xIfc;
393 xIfc = rXSMgr->createInstance(
394 rtl::OUString(
395 RTL_CONSTASCII_USTRINGPARAM(
396 "com.sun.star.frame.GlobalEventBroadcaster" ) ) );
398 catch ( uno::Exception const & )
400 // handled below.
403 OSL_ENSURE(
404 xIfc.is(),
405 "Could not instanciate com.sun.star.frame.GlobalEventBroadcaster" );
407 if ( xIfc.is() )
409 uno::Reference< document::XEventBroadcaster > xBC(
410 xIfc, uno::UNO_QUERY );
412 OSL_ENSURE(
413 xBC.is(),
414 "com.sun.star.frame.GlobalEventBroadcaster does not implement "
415 "interface com.sun.star.document.XEventBroadcaster!" );
417 return xBC;
419 else
420 return uno::Reference< document::XEventBroadcaster >();
423 //=========================================================================
424 void OfficeDocumentsManager::buildDocumentsList()
426 OSL_ENSURE( m_xDocEvtNotifier.is(),
427 "OfficeDocumentsManager::buildDocumentsList - "
428 "No document event notifier!" );
430 uno::Reference< container::XEnumerationAccess > xEnumAccess(
431 m_xDocEvtNotifier, uno::UNO_QUERY_THROW );
433 uno::Reference< container::XEnumeration > xEnum
434 = xEnumAccess->createEnumeration();
436 osl::MutexGuard aGuard( m_aMtx );
438 while ( xEnum->hasMoreElements() )
440 uno::Any aValue = xEnum->nextElement();
441 // container::NoSuchElementException
442 // lang::WrappedTargetException
446 uno::Reference< frame::XModel > xModel;
447 aValue >>= xModel;
449 if ( xModel.is() )
451 if ( isOfficeDocument( xModel ) )
453 DocumentList::const_iterator it = m_aDocs.begin();
454 while ( it != m_aDocs.end() )
456 if ( (*it).second.xModel == xModel )
458 // already known.
459 break;
461 ++it;
464 if ( it == m_aDocs.end() )
466 // new document
467 rtl::OUString aDocId = getDocumentId( xModel );
468 rtl::OUString aTitle = DocumentInfo::getDocumentTitle( xModel );
470 uno::Reference< document::XStorageBasedDocument >
471 xDoc( xModel, uno::UNO_QUERY );
472 OSL_ENSURE( xDoc.is(),
473 "Got no document::XStorageBasedDocument!" );
475 uno::Reference< embed::XStorage > xStorage
476 = xDoc->getDocumentStorage();
477 OSL_ENSURE( xDoc.is(), "Got no document storage!" );
479 m_aDocs[ aDocId ]
480 = StorageInfo( aTitle, xStorage, xModel );
485 catch ( lang::DisposedException const & )
487 // Note: Due to race conditions the XEnumeration can
488 // contains docs that already have been closed
493 //=========================================================================
494 uno::Reference< embed::XStorage >
495 OfficeDocumentsManager::queryStorage( const rtl::OUString & rDocId )
497 osl::MutexGuard aGuard( m_aMtx );
499 DocumentList::const_iterator it = m_aDocs.find( rDocId );
500 if ( it == m_aDocs.end() )
501 return uno::Reference< embed::XStorage >();
503 return (*it).second.xStorage;
506 //=========================================================================
507 rtl::OUString OfficeDocumentsManager::queryDocumentId(
508 const uno::Reference< frame::XModel > & xModel )
510 return getDocumentId( xModel );
513 //=========================================================================
514 uno::Reference< frame::XModel >
515 OfficeDocumentsManager::queryDocumentModel( const rtl::OUString & rDocId )
517 osl::MutexGuard aGuard( m_aMtx );
519 DocumentList::const_iterator it = m_aDocs.find( rDocId );
520 if ( it == m_aDocs.end() )
521 return uno::Reference< frame::XModel >();
523 return (*it).second.xModel;
526 //=========================================================================
527 uno::Sequence< rtl::OUString > OfficeDocumentsManager::queryDocuments()
529 osl::MutexGuard aGuard( m_aMtx );
531 uno::Sequence< rtl::OUString > aRet( m_aDocs.size() );
532 sal_Int32 nPos = 0;
534 DocumentList::const_iterator it = m_aDocs.begin();
535 while ( it != m_aDocs.end() )
537 aRet[ nPos ] = (*it).first;
538 ++it;
539 ++nPos;
541 return aRet;
544 //=========================================================================
545 rtl::OUString
546 OfficeDocumentsManager::queryStorageTitle( const rtl::OUString & rDocId )
548 osl::MutexGuard aGuard( m_aMtx );
550 DocumentList::const_iterator it = m_aDocs.find( rDocId );
551 if ( it == m_aDocs.end() )
552 return rtl::OUString();
554 return (*it).second.aTitle;
557 //=========================================================================
558 bool OfficeDocumentsManager::isDocumentPreview(
559 const uno::Reference< frame::XModel > & xModel )
561 if ( !xModel.is() )
562 return false;
564 ::comphelper::NamedValueCollection aArgs(
565 xModel->getArgs() );
566 sal_Bool bIsPreview = aArgs.getOrDefault( "Preview", sal_False );
567 return bIsPreview;
570 //=========================================================================
571 bool OfficeDocumentsManager::isHelpDocument(
572 const uno::Reference< frame::XModel > & xModel )
574 if ( !xModel.is() )
575 return false;
577 ::rtl::OUString sURL( xModel->getURL() );
578 if ( sURL.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.help://" ) ) )
579 return true;
581 return false;
584 //=========================================================================
585 bool OfficeDocumentsManager::isWithoutOrInTopLevelFrame(
586 const uno::Reference< frame::XModel > & xModel )
588 if ( !xModel.is() )
589 return false;
591 uno::Reference< frame::XController > xController
592 = xModel->getCurrentController();
593 if ( xController.is() )
595 uno::Reference< frame::XFrame > xFrame
596 = xController->getFrame();
597 if ( xFrame.is() )
599 // don't use XFrame::isTop here. This nowadays excludes
600 // "sub documents" such as forms embedded in database documents
601 uno::Reference< awt::XTopWindow > xFrameContainer(
602 xFrame->getContainerWindow(), uno::UNO_QUERY );
603 if ( !xFrameContainer.is() )
604 return false;
608 return true;
611 //=========================================================================
612 bool OfficeDocumentsManager::isBasicIDE(
613 const uno::Reference< frame::XModel > & xModel )
615 if ( !m_xModuleMgr.is() )
617 osl::MutexGuard aGuard( m_aMtx );
618 if ( !m_xModuleMgr.is() )
622 m_xModuleMgr
623 = uno::Reference<
624 frame::XModuleManager >(
625 m_xSMgr->createInstance(
626 rtl::OUString(
627 RTL_CONSTASCII_USTRINGPARAM(
628 "com.sun.star.frame.ModuleManager" ) ) ),
629 uno::UNO_QUERY );
631 catch ( uno::Exception const & )
633 // handled below.
636 OSL_ENSURE( m_xModuleMgr .is(),
637 "Could not instanciate ModuleManager service!" );
641 if ( m_xModuleMgr.is() )
643 rtl::OUString aModule;
646 aModule = m_xModuleMgr->identify( xModel );
648 catch ( lang::IllegalArgumentException const & )
650 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
652 catch ( frame::UnknownModuleException const & )
654 OSL_ENSURE( false, "Caught UnknownModuleException!" );
657 if ( aModule.getLength() > 0 )
659 // Filter unwanted items, that are no real documents.
660 if ( aModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
661 "com.sun.star.script.BasicIDE" ) ) )
663 return true;
668 return false;
671 //=========================================================================
672 bool OfficeDocumentsManager::isOfficeDocument(
673 const uno::Reference< uno::XInterface > & xDoc )
675 uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY );
676 uno::Reference< document::XStorageBasedDocument >
677 xStorageBasedDoc( xModel, uno::UNO_QUERY );
678 if ( !xStorageBasedDoc.is() )
679 return false;
681 if ( !isWithoutOrInTopLevelFrame( xModel ) )
682 return false;
684 if ( isDocumentPreview( xModel ) )
685 return false;
687 if ( isHelpDocument( xModel ) )
688 return false;
690 if ( isBasicIDE( xModel ) )
691 return false;
693 return true;