1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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 /**************************************************************************
35 **************************************************************************
37 - filter unwanted models notified by global document event broadcaster
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
)
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 );
86 //=========================================================================
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 //=========================================================================
102 getDocumentId( const uno::Reference
< uno::XInterface
> & xDoc
)
106 // Try to get the UID directly from the document.
107 uno::Reference
< beans::XPropertySet
> xPropSet( xDoc
, uno::UNO_QUERY
);
112 uno::Any aValue
= xPropSet
->getPropertyValue(
114 RTL_CONSTASCII_USTRINGPARAM( "RuntimeUID" ) ) );
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
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!" );
142 //=========================================================================
144 // document::XEventListener
146 //=========================================================================
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
)
181 if ( it
== m_aDocs
.end() )
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
);
241 OSL_ENSURE( it
!= m_aDocs
.end(),
242 "OnUnload event notified for unknown document!" );
244 if( it
!= m_aDocs
.end() )
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
;
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
;
313 (*it
).second
.aTitle
= DocumentInfo::getDocumentTitle( uno::Reference
< frame::XModel
>( Event
.Source
, uno::UNO_QUERY
) );
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
)
340 rtl:: OUString aTitle
= DocumentInfo::getDocumentTitle( uno::Reference
< frame::XModel
>( Event
.Source
, uno::UNO_QUERY
) );
341 (*it
).second
.aTitle
= aTitle
;
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
);
360 OSL_ENSURE( it
!= m_aDocs
.end(),
361 "TitleChanged event notified for unknown document!" );
366 //=========================================================================
368 // lang::XEventListener (base of document::XEventListener)
370 //=========================================================================
373 void SAL_CALL
OfficeDocumentsManager::disposing(
374 const lang::EventObject
& /*Source*/ )
375 throw ( uno::RuntimeException
)
379 //=========================================================================
383 //=========================================================================
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(
395 RTL_CONSTASCII_USTRINGPARAM(
396 "com.sun.star.frame.GlobalEventBroadcaster" ) ) );
398 catch ( uno::Exception
const & )
405 "Could not instanciate com.sun.star.frame.GlobalEventBroadcaster" );
409 uno::Reference
< document::XEventBroadcaster
> xBC(
410 xIfc
, uno::UNO_QUERY
);
414 "com.sun.star.frame.GlobalEventBroadcaster does not implement "
415 "interface com.sun.star.document.XEventBroadcaster!" );
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
;
451 if ( isOfficeDocument( xModel
) )
453 DocumentList::const_iterator it
= m_aDocs
.begin();
454 while ( it
!= m_aDocs
.end() )
456 if ( (*it
).second
.xModel
== xModel
)
464 if ( it
== m_aDocs
.end() )
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!" );
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() );
534 DocumentList::const_iterator it
= m_aDocs
.begin();
535 while ( it
!= m_aDocs
.end() )
537 aRet
[ nPos
] = (*it
).first
;
544 //=========================================================================
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
)
564 ::comphelper::NamedValueCollection
aArgs(
566 sal_Bool bIsPreview
= aArgs
.getOrDefault( "Preview", sal_False
);
570 //=========================================================================
571 bool OfficeDocumentsManager::isHelpDocument(
572 const uno::Reference
< frame::XModel
> & xModel
)
577 ::rtl::OUString
sURL( xModel
->getURL() );
578 if ( sURL
.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.help://" ) ) )
584 //=========================================================================
585 bool OfficeDocumentsManager::isWithoutOrInTopLevelFrame(
586 const uno::Reference
< frame::XModel
> & xModel
)
591 uno::Reference
< frame::XController
> xController
592 = xModel
->getCurrentController();
593 if ( xController
.is() )
595 uno::Reference
< frame::XFrame
> xFrame
596 = xController
->getFrame();
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() )
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() )
624 frame::XModuleManager
>(
625 m_xSMgr
->createInstance(
627 RTL_CONSTASCII_USTRINGPARAM(
628 "com.sun.star.frame.ModuleManager" ) ) ),
631 catch ( uno::Exception
const & )
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" ) ) )
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() )
681 if ( !isWithoutOrInTopLevelFrame( xModel
) )
684 if ( isDocumentPreview( xModel
) )
687 if ( isHelpDocument( xModel
) )
690 if ( isBasicIDE( xModel
) )