1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_dbaccess.hxx" 30 31 #include "core_resource.hxx" 32 #include "core_resource.hrc" 33 #include "datasource.hxx" 34 #include "databasedocument.hxx" 35 #include "dbastrings.hrc" 36 #include "module_dba.hxx" 37 #include "documenteventexecutor.hxx" 38 #include "databasecontext.hxx" 39 #include "documentcontainer.hxx" 40 #include "sdbcoretools.hxx" 41 #include "recovery/dbdocrecovery.hxx" 42 43 /** === begin UNO includes === **/ 44 #include <com/sun/star/beans/Optional.hpp> 45 #include <com/sun/star/document/XExporter.hpp> 46 #include <com/sun/star/document/XFilter.hpp> 47 #include <com/sun/star/document/XImporter.hpp> 48 #include <com/sun/star/embed/EntryInitModes.hpp> 49 #include <com/sun/star/embed/XEmbedPersist.hpp> 50 #include <com/sun/star/embed/XTransactedObject.hpp> 51 #include <com/sun/star/embed/XTransactionBroadcaster.hpp> 52 #include <com/sun/star/io/XActiveDataSource.hpp> 53 #include <com/sun/star/io/XSeekable.hpp> 54 #include <com/sun/star/io/XOutputStream.hpp> 55 #include <com/sun/star/io/XTruncate.hpp> 56 #include <com/sun/star/script/provider/XScriptProviderFactory.hpp> 57 #include <com/sun/star/task/ErrorCodeIOException.hpp> 58 #include <com/sun/star/task/XStatusIndicator.hpp> 59 #include <com/sun/star/task/XStatusIndicatorFactory.hpp> 60 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 61 #include <com/sun/star/ui/XUIConfigurationStorage.hpp> 62 #include <com/sun/star/view/XSelectionSupplier.hpp> 63 #include <com/sun/star/xml/sax/XDocumentHandler.hpp> 64 #include <com/sun/star/ucb/XContent.hpp> 65 #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp> 66 /** === end UNO includes === **/ 67 68 #include <comphelper/documentconstants.hxx> 69 #include <comphelper/enumhelper.hxx> 70 #include <comphelper/genericpropertyset.hxx> 71 #include <comphelper/interaction.hxx> 72 #include <comphelper/mediadescriptor.hxx> 73 #include <comphelper/namedvaluecollection.hxx> 74 #include <comphelper/numberedcollection.hxx> 75 #include <comphelper/property.hxx> 76 #include <comphelper/storagehelper.hxx> 77 #include <comphelper/genericpropertyset.hxx> 78 #include <comphelper/property.hxx> 79 80 #include <connectivity/dbtools.hxx> 81 82 #include <cppuhelper/exc_hlp.hxx> 83 #include <framework/titlehelper.hxx> 84 #include <unotools/saveopt.hxx> 85 #include <tools/debug.hxx> 86 #include <tools/diagnose_ex.h> 87 #include <tools/errcode.hxx> 88 #include <tools/urlobj.hxx> 89 90 #include <boost/bind.hpp> 91 92 #include <algorithm> 93 #include <functional> 94 #include <list> 95 96 #define MAP_LEN(x) x, sizeof(x) - 1 97 98 #define MAP_LEN(x) x, sizeof(x) - 1 99 100 using namespace ::com::sun::star::uno; 101 using namespace ::com::sun::star::beans; 102 using namespace ::com::sun::star::frame; 103 using namespace ::com::sun::star::lang; 104 using namespace ::com::sun::star::container; 105 using namespace ::com::sun::star::document; 106 using namespace ::com::sun::star::io; 107 using namespace ::com::sun::star::util; 108 using namespace ::com::sun::star::embed; 109 using namespace ::com::sun::star::task; 110 using namespace ::com::sun::star::view; 111 using namespace ::com::sun::star::sdbc; 112 using namespace ::com::sun::star; 113 using namespace ::com::sun::star::xml::sax; 114 using namespace ::com::sun::star::script; 115 using namespace ::com::sun::star::script::provider; 116 using namespace ::com::sun::star::ui; 117 using namespace ::cppu; 118 using namespace ::osl; 119 120 using ::com::sun::star::awt::XWindow; 121 using ::com::sun::star::ucb::XContent; 122 using ::com::sun::star::sdb::application::XDatabaseDocumentUI; 123 124 //........................................................................ 125 namespace dbaccess 126 { 127 //........................................................................ 128 129 //============================================================ 130 //= ViewMonitor 131 //============================================================ 132 //-------------------------------------------------------------------------- 133 bool ViewMonitor::onControllerConnected( const Reference< XController >& _rxController ) 134 { 135 bool bFirstControllerEver = ( m_bEverHadController == false ); 136 m_bEverHadController = true; 137 138 m_xLastConnectedController = _rxController; 139 m_bLastIsFirstEverController = bFirstControllerEver; 140 141 return bFirstControllerEver; 142 } 143 144 //-------------------------------------------------------------------------- 145 bool ViewMonitor::onSetCurrentController( const Reference< XController >& _rxController ) 146 { 147 // we interpret this as "loading the document (including UI) is finished", 148 // if and only if this is the controller which was last connected, and it was the 149 // first controller ever connected 150 bool bLoadFinished = ( _rxController == m_xLastConnectedController ) && m_bLastIsFirstEverController; 151 152 // notify the respective events 153 if ( bLoadFinished ) 154 m_rEventNotifier.notifyDocumentEventAsync( m_bIsNewDocument ? "OnNew" : "OnLoad" ); 155 156 return bLoadFinished; 157 } 158 159 //============================================================ 160 //= ODatabaseDocument 161 //============================================================ 162 DBG_NAME(ODatabaseDocument) 163 //-------------------------------------------------------------------------- 164 extern "C" void SAL_CALL createRegistryInfo_ODatabaseDocument() 165 { 166 static ::dba::OAutoRegistration< ODatabaseDocument > aAutoRegistration; 167 } 168 169 //-------------------------------------------------------------------------- 170 ODatabaseDocument::ODatabaseDocument(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl ) 171 :ModelDependentComponent( _pImpl ) 172 ,ODatabaseDocument_OfficeDocument( getMutex() ) 173 ,m_aModifyListeners( getMutex() ) 174 ,m_aCloseListener( getMutex() ) 175 ,m_aStorageListeners( getMutex() ) 176 ,m_pEventContainer( new DocumentEvents( *this, getMutex(), _pImpl->getDocumentEvents() ) ) 177 ,m_pEventExecutor( NULL ) // initialized below, ref-count-protected 178 ,m_aEventNotifier( *this, getMutex() ) 179 ,m_aViewMonitor( m_aEventNotifier ) 180 ,m_eInitState( NotInitialized ) 181 ,m_bClosing( false ) 182 ,m_bAllowDocumentScripting( false ) 183 ,m_bHasBeenRecovered( false ) 184 { 185 DBG_CTOR(ODatabaseDocument,NULL); 186 OSL_TRACE( "DD: ctor: %p: %p", this, m_pImpl.get() ); 187 188 osl_incrementInterlockedCount( &m_refCount ); 189 { 190 impl_reparent_nothrow( m_xForms ); 191 impl_reparent_nothrow( m_xReports ); 192 impl_reparent_nothrow( m_pImpl->m_xTableDefinitions ); 193 impl_reparent_nothrow( m_pImpl->m_xCommandDefinitions ); 194 195 m_pEventExecutor = new DocumentEventExecutor( m_pImpl->m_aContext, this ); 196 } 197 osl_decrementInterlockedCount( &m_refCount ); 198 199 // if there previously was a document instance for the same Impl which was already initialized, 200 // then consider ourself initialized, too. 201 // #i94840# 202 if ( m_pImpl->hadInitializedDocument() ) 203 { 204 // Note we set our init-state to "Initializing", not "Initialized". We're created from inside the ModelImpl, 205 // which is expected to call attachResource in case there was a previous incarnation of the document, 206 // so we can properly finish our initialization then. 207 impl_setInitializing(); 208 209 if ( m_pImpl->getURL().getLength() ) 210 { 211 // if the previous incarnation of the DatabaseDocument already had an URL, then creating this incarnation 212 // here is effectively loading the document. 213 // #i105505# / 2009-10-01 / frank.schoenheit@sun.com 214 m_aViewMonitor.onLoadedDocument(); 215 } 216 } 217 } 218 219 //-------------------------------------------------------------------------- 220 ODatabaseDocument::~ODatabaseDocument() 221 { 222 OSL_TRACE( "DD: dtor: %p: %p", this, m_pImpl.get() ); 223 DBG_DTOR(ODatabaseDocument,NULL); 224 if ( !ODatabaseDocument_OfficeDocument::rBHelper.bInDispose && !ODatabaseDocument_OfficeDocument::rBHelper.bDisposed ) 225 { 226 acquire(); 227 dispose(); 228 } 229 230 delete m_pEventContainer, m_pEventContainer = NULL; 231 } 232 // ----------------------------------------------------------------------------- 233 Any SAL_CALL ODatabaseDocument::queryInterface( const Type& _rType ) throw (RuntimeException) 234 { 235 // strip XEmbeddedScripts and XScriptInvocationContext if we have any form/report 236 // which already contains macros. In this case, the database document itself is not 237 // allowed to contain macros, too. 238 if ( !m_bAllowDocumentScripting 239 && ( _rType.equals( XEmbeddedScripts::static_type() ) 240 || _rType.equals( XScriptInvocationContext::static_type() ) 241 ) 242 ) 243 return Any(); 244 245 Any aReturn = ODatabaseDocument_OfficeDocument::queryInterface(_rType); 246 if (!aReturn.hasValue()) 247 aReturn = ODatabaseDocument_Title::queryInterface(_rType); 248 return aReturn; 249 } 250 //------------------------------------------------------------------------------ 251 void SAL_CALL ODatabaseDocument::acquire( ) throw () 252 { 253 ODatabaseDocument_OfficeDocument::acquire(); 254 } 255 256 //------------------------------------------------------------------------------ 257 void SAL_CALL ODatabaseDocument::release( ) throw () 258 { 259 ODatabaseDocument_OfficeDocument::release(); 260 } 261 //------------------------------------------------------------------------------ 262 Sequence< Type > SAL_CALL ODatabaseDocument::getTypes( ) throw (RuntimeException) 263 { 264 Sequence< Type > aTypes = ::comphelper::concatSequences( 265 ODatabaseDocument_OfficeDocument::getTypes(), 266 ODatabaseDocument_Title::getTypes() 267 ); 268 269 // strip XEmbeddedScripts and XScriptInvocationContext if we have any form/report 270 // which already contains macros. In this case, the database document itself is not 271 // allowed to contain macros, too. 272 if ( !m_bAllowDocumentScripting ) 273 { 274 Sequence< Type > aStrippedTypes( aTypes.getLength() ); 275 Type* pStripTo( aStrippedTypes.getArray() ); 276 277 // strip XEmbeddedScripts, and immediately re-assign to aTypes 278 aTypes = Sequence< Type >( 279 pStripTo, 280 ::std::remove_copy_if( 281 aTypes.getConstArray(), 282 aTypes.getConstArray() + aTypes.getLength(), 283 pStripTo, 284 ::std::bind2nd( ::std::equal_to< Type >(), XEmbeddedScripts::static_type() ) 285 ) - pStripTo 286 ); 287 288 // strip XScriptInvocationContext, and immediately re-assign to aTypes 289 aTypes = Sequence< Type >( 290 pStripTo, 291 ::std::remove_copy_if( 292 aTypes.getConstArray(), 293 aTypes.getConstArray() + aTypes.getLength(), 294 pStripTo, 295 ::std::bind2nd( ::std::equal_to< Type >(), XScriptInvocationContext::static_type() ) 296 ) - pStripTo 297 ); 298 } 299 300 return aTypes; 301 } 302 //------------------------------------------------------------------------------ 303 Sequence< sal_Int8 > SAL_CALL ODatabaseDocument::getImplementationId( ) throw (RuntimeException) 304 { 305 static ::cppu::OImplementationId * pId = 0; 306 if (! pId) 307 { 308 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 309 if (! pId) 310 { 311 static ::cppu::OImplementationId aId; 312 pId = &aId; 313 } 314 } 315 return pId->getImplementationId(); 316 } 317 318 // ----------------------------------------------------------------------------- 319 // local functions 320 // ----------------------------------------------------------------------------- 321 namespace 322 { 323 // ----------------------------------------------------------------------------- 324 Reference< XStatusIndicator > lcl_extractStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments ) 325 { 326 Reference< XStatusIndicator > xStatusIndicator; 327 return _rArguments.getOrDefault( "StatusIndicator", xStatusIndicator ); 328 } 329 330 // ----------------------------------------------------------------------------- 331 static void lcl_triggerStatusIndicator_throw( const ::comphelper::NamedValueCollection& _rArguments, DocumentGuard& _rGuard, const bool _bStart ) 332 { 333 Reference< XStatusIndicator > xStatusIndicator( lcl_extractStatusIndicator( _rArguments ) ); 334 if ( !xStatusIndicator.is() ) 335 return; 336 337 _rGuard.clear(); 338 try 339 { 340 if ( _bStart ) 341 xStatusIndicator->start( ::rtl::OUString(), (sal_Int32)1000000 ); 342 else 343 xStatusIndicator->end(); 344 } 345 catch( const Exception& ) 346 { 347 DBG_UNHANDLED_EXCEPTION(); 348 } 349 _rGuard.reset(); 350 // note that |reset| can throw a DisposedException 351 } 352 353 // ----------------------------------------------------------------------------- 354 static void lcl_extractStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments, Sequence< Any >& _rCallArgs ) 355 { 356 Reference< XStatusIndicator > xStatusIndicator( lcl_extractStatusIndicator( _rArguments ) ); 357 if ( !xStatusIndicator.is() ) 358 return; 359 360 sal_Int32 nLength = _rCallArgs.getLength(); 361 _rCallArgs.realloc( nLength + 1 ); 362 _rCallArgs[ nLength ] <<= xStatusIndicator; 363 } 364 365 // ----------------------------------------------------------------------------- 366 static void lcl_extractAndStartStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments, Reference< XStatusIndicator >& _rxStatusIndicator, 367 Sequence< Any >& _rCallArgs ) 368 { 369 _rxStatusIndicator = lcl_extractStatusIndicator( _rArguments ); 370 if ( !_rxStatusIndicator.is() ) 371 return; 372 373 try 374 { 375 _rxStatusIndicator->start( ::rtl::OUString(), (sal_Int32)1000000 ); 376 377 sal_Int32 nLength = _rCallArgs.getLength(); 378 _rCallArgs.realloc( nLength + 1 ); 379 _rCallArgs[ nLength ] <<= _rxStatusIndicator; 380 } 381 catch( const Exception& ) 382 { 383 DBG_UNHANDLED_EXCEPTION(); 384 } 385 } 386 387 // ----------------------------------------------------------------------------- 388 static Sequence< PropertyValue > lcl_appendFileNameToDescriptor( const ::comphelper::NamedValueCollection& _rDescriptor, const ::rtl::OUString _rURL ) 389 { 390 ::comphelper::NamedValueCollection aMutableDescriptor( _rDescriptor ); 391 if ( _rURL.getLength() ) 392 { 393 aMutableDescriptor.put( "FileName", _rURL ); 394 aMutableDescriptor.put( "URL", _rURL ); 395 } 396 return aMutableDescriptor.getPropertyValues(); 397 } 398 } 399 400 // ----------------------------------------------------------------------------- 401 void ODatabaseDocument::impl_setInitialized() 402 { 403 m_eInitState = Initialized; 404 405 // start event notifications 406 m_aEventNotifier.onDocumentInitialized(); 407 } 408 409 // ----------------------------------------------------------------------------- 410 void ODatabaseDocument::impl_reset_nothrow() 411 { 412 try 413 { 414 m_pImpl->clearConnections(); 415 m_pImpl->disposeStorages(); 416 m_pImpl->resetRootStroage(); 417 418 clearObjectContainer( m_xForms ); 419 clearObjectContainer( m_xReports ); 420 clearObjectContainer( m_pImpl->m_xTableDefinitions ); 421 clearObjectContainer( m_pImpl->m_xCommandDefinitions ); 422 423 m_eInitState = NotInitialized; 424 425 m_pImpl->reset(); 426 } 427 catch(const Exception&) 428 { 429 DBG_UNHANDLED_EXCEPTION(); 430 } 431 m_pImpl->m_bDocumentReadOnly = sal_False; 432 } 433 434 // ----------------------------------------------------------------------------- 435 void ODatabaseDocument::impl_import_nolck_throw( const ::comphelper::ComponentContext _rContext, const Reference< XInterface >& _rxTargetComponent, 436 const ::comphelper::NamedValueCollection& _rResource ) 437 { 438 Sequence< Any > aFilterCreationArgs; 439 Reference< XStatusIndicator > xStatusIndicator; 440 lcl_extractAndStartStatusIndicator( _rResource, xStatusIndicator, aFilterCreationArgs ); 441 442 /** property map for import info set */ 443 comphelper::PropertyMapEntry aExportInfoMap[] = 444 { 445 { MAP_LEN( "BaseURI"), 0,&::getCppuType( (::rtl::OUString *)0 ),beans::PropertyAttribute::MAYBEVOID, 0 }, 446 { MAP_LEN( "StreamName"), 0,&::getCppuType( (::rtl::OUString *)0 ),beans::PropertyAttribute::MAYBEVOID, 0 }, 447 { NULL, 0, 0, NULL, 0, 0 } 448 }; 449 uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) ); 450 xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI")), uno::makeAny(_rResource.getOrDefault("URL",::rtl::OUString()))); 451 xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamName")), uno::makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("content.xml")))); 452 453 const sal_Int32 nCount = aFilterCreationArgs.getLength(); 454 aFilterCreationArgs.realloc(nCount + 1); 455 aFilterCreationArgs[nCount] <<= xInfoSet; 456 457 Reference< XImporter > xImporter( 458 _rContext.createComponentWithArguments( "com.sun.star.comp.sdb.DBFilter", aFilterCreationArgs ), 459 UNO_QUERY_THROW ); 460 461 Reference< XComponent > xComponent( _rxTargetComponent, UNO_QUERY_THROW ); 462 xImporter->setTargetDocument( xComponent ); 463 464 Reference< XFilter > xFilter( xImporter, UNO_QUERY_THROW ); 465 Sequence< PropertyValue > aFilterArgs( ODatabaseModelImpl::stripLoadArguments( _rResource ).getPropertyValues() ); 466 xFilter->filter( aFilterArgs ); 467 468 if ( xStatusIndicator.is() ) 469 xStatusIndicator->end(); 470 } 471 472 // ----------------------------------------------------------------------------- 473 void SAL_CALL ODatabaseDocument::initNew( ) throw (DoubleInitializationException, IOException, Exception, RuntimeException) 474 { 475 // SYNCHRONIZED -> 476 DocumentGuard aGuard( *this, DocumentGuard::InitMethod ); 477 478 impl_reset_nothrow(); 479 480 impl_setInitializing(); 481 482 // create a temporary storage 483 Reference< XStorage > xTempStor( ::comphelper::OStorageHelper::GetTemporaryStorage( 484 m_pImpl->m_aContext.getLegacyServiceFactory() ) ); 485 486 // store therein 487 impl_storeToStorage_throw( xTempStor, Sequence< PropertyValue >(), aGuard ); 488 489 // let the impl know we're now based on this storage 490 m_pImpl->switchToStorage( xTempStor ); 491 492 // for the newly created document, allow document-wide scripting 493 m_bAllowDocumentScripting = true; 494 495 impl_setInitialized(); 496 497 m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" ); 498 499 impl_setModified_nothrow( sal_False, aGuard ); 500 // <- SYNCHRONIZED 501 502 m_aEventNotifier.notifyDocumentEvent( "OnCreate" ); 503 504 impl_notifyStorageChange_nolck_nothrow( xTempStor ); 505 } 506 507 // ----------------------------------------------------------------------------- 508 void SAL_CALL ODatabaseDocument::load( const Sequence< PropertyValue >& _Arguments ) throw (DoubleInitializationException, IOException, Exception, RuntimeException) 509 { 510 // SYNCHRONIZED -> 511 DocumentGuard aGuard( *this, DocumentGuard::InitMethod ); 512 513 impl_reset_nothrow(); 514 515 ::comphelper::NamedValueCollection aResource( _Arguments ); 516 if ( aResource.has( "FileName" ) && !aResource.has( "URL" ) ) 517 // FileName is the compatibility name for URL, so we might have clients passing 518 // a FileName only. However, some of our code works with the URL only, so ensure 519 // we have one. 520 aResource.put( "URL", aResource.get( "FileName" ) ); 521 if ( aResource.has( "URL" ) && !aResource.has( "FileName" ) ) 522 // similar ... just in case there is legacy code which expects a FileName only 523 aResource.put( "FileName", aResource.get( "URL" ) ); 524 525 // now that somebody (perhaps) told us an macro execution mode, remember it as 526 // ImposedMacroExecMode 527 m_pImpl->setImposedMacroExecMode( 528 aResource.getOrDefault( "MacroExecutionMode", m_pImpl->getImposedMacroExecMode() ) ); 529 530 impl_setInitializing(); 531 try 532 { 533 aGuard.clear(); 534 impl_import_nolck_throw( m_pImpl->m_aContext, *this, aResource ); 535 aGuard.reset(); 536 } 537 catch( const Exception& ) 538 { 539 impl_reset_nothrow(); 540 throw; 541 } 542 // tell our view monitor that the document has been loaded - this way it will fire the proper 543 // event (OnLoad instead of OnCreate) later on 544 m_aViewMonitor.onLoadedDocument(); 545 546 // note that we do *not* call impl_setInitialized() here: The initialization is only complete 547 // when the XModel::attachResource has been called, not sooner. 548 549 impl_setModified_nothrow( sal_False, aGuard ); 550 // <- SYNCHRONIZED 551 } 552 553 // ----------------------------------------------------------------------------- 554 namespace 555 { 556 // ......................................................................... 557 bool lcl_hasAnyModifiedSubComponent_throw( const Reference< XController >& i_rController ) 558 { 559 Reference< XDatabaseDocumentUI > xDatabaseUI( i_rController, UNO_QUERY_THROW ); 560 561 Sequence< Reference< XComponent > > aComponents( xDatabaseUI->getSubComponents() ); 562 const Reference< XComponent >* component = aComponents.getConstArray(); 563 const Reference< XComponent >* componentsEnd = aComponents.getConstArray() + aComponents.getLength(); 564 565 bool isAnyModified = false; 566 for ( ; component != componentsEnd; ++component ) 567 { 568 Reference< XModifiable > xModify( *component, UNO_QUERY ); 569 if ( xModify.is() ) 570 { 571 isAnyModified = xModify->isModified(); 572 continue; 573 } 574 575 // TODO: clarify: anything else to care for? Both the sub componbents with and without model 576 // should support the XModifiable interface, so I think nothing more is needed here. 577 OSL_ENSURE( false, "lcl_hasAnyModifiedSubComponent_throw: anything left to do here?" ); 578 } 579 580 return isAnyModified; 581 } 582 } 583 584 // ----------------------------------------------------------------------------- 585 ::sal_Bool SAL_CALL ODatabaseDocument::wasModifiedSinceLastSave() throw ( RuntimeException ) 586 { 587 DocumentGuard aGuard( *this ); 588 589 // The implementation here is somewhat sloppy, in that it returns whether *any* part of the whole 590 // database document, including opened sub components, is modified. This is more than what is requested: 591 // We need to return <TRUE/> if the doc itself, or any of the opened sub components, has been modified 592 // since the last call to any of the save* methods, or since the document has been loaded/created. 593 // However, the API definition explicitly allows to be that sloppy ... 594 595 if ( isModified() ) 596 return sal_True; 597 598 // auto recovery is an "UI feature", it is to restore the UI the user knows. Thus, 599 // we ask our connected controllers, not simply our existing form/report definitions. 600 // (There is some information which even cannot be obtained without asking the controller. 601 // For instance, newly created, but not yet saved, forms/reports are acessible via the 602 // controller only, but not via the model.) 603 604 try 605 { 606 for ( Controllers::const_iterator ctrl = m_aControllers.begin(); 607 ctrl != m_aControllers.end(); 608 ++ctrl 609 ) 610 { 611 if ( lcl_hasAnyModifiedSubComponent_throw( *ctrl ) ) 612 return sal_True; 613 } 614 } 615 catch( const Exception& ) 616 { 617 DBG_UNHANDLED_EXCEPTION(); 618 } 619 620 return sal_False; 621 } 622 623 // ----------------------------------------------------------------------------- 624 void SAL_CALL ODatabaseDocument::storeToRecoveryFile( const ::rtl::OUString& i_TargetLocation, const Sequence< PropertyValue >& i_MediaDescriptor ) throw ( RuntimeException, IOException, WrappedTargetException ) 625 { 626 DocumentGuard aGuard( *this ); 627 ModifyLock aLock( *this ); 628 629 try 630 { 631 // create a storage for the target location 632 Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( i_TargetLocation ) ); 633 634 // first store the document as a whole into this storage 635 impl_storeToStorage_throw( xTargetStorage, i_MediaDescriptor, aGuard ); 636 637 // save the sub components which need saving 638 DatabaseDocumentRecovery aDocRecovery( m_pImpl->m_aContext); 639 aDocRecovery.saveModifiedSubComponents( xTargetStorage, m_aControllers ); 640 641 // commit the root storage 642 tools::stor::commitStorageIfWriteable( xTargetStorage ); 643 } 644 catch( const Exception& ) 645 { 646 Any aError = ::cppu::getCaughtException(); 647 if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) 648 || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) 649 || aError.isExtractableTo( ::cppu::UnoType< WrappedTargetException >::get() ) 650 ) 651 { 652 // allowed to leave 653 throw; 654 } 655 656 throw WrappedTargetException( ::rtl::OUString(), *this, aError ); 657 } 658 } 659 660 // ----------------------------------------------------------------------------- 661 void SAL_CALL ODatabaseDocument::recoverFromFile( const ::rtl::OUString& i_SourceLocation, const ::rtl::OUString& i_SalvagedFile, const Sequence< PropertyValue >& i_MediaDescriptor ) throw ( RuntimeException, IOException, WrappedTargetException ) 662 { 663 DocumentGuard aGuard( *this, DocumentGuard::InitMethod ); 664 665 if ( i_SourceLocation.getLength() == 0 ) 666 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 667 668 try 669 { 670 // load the document itself, by simply delegating to our "load" method 671 672 // our load implementation expects the SalvagedFile and URL to be in the media descriptor 673 ::comphelper::NamedValueCollection aMediaDescriptor( i_MediaDescriptor ); 674 aMediaDescriptor.put( "SalvagedFile", i_SalvagedFile ); 675 aMediaDescriptor.put( "URL", i_SourceLocation ); 676 677 aGuard.clear(); // (load has an own guarding scheme) 678 load( aMediaDescriptor.getPropertyValues() ); 679 680 // Without a controller, we are unable to recover the sub components, as they're always tied to a controller. 681 // So, everything else is done when the first controller is connected. 682 m_bHasBeenRecovered = true; 683 684 // tell the impl that we've been loaded from the given location 685 m_pImpl->setDocFileLocation( i_SourceLocation ); 686 687 // by definition (of XDocumentRecovery), we're responsible for delivering a fully-initialized document, 688 // which includes an attachResource call. 689 const ::rtl::OUString sLogicalDocumentURL( i_SalvagedFile.getLength() ? i_SalvagedFile : i_SourceLocation ); 690 impl_attachResource( sLogicalDocumentURL, aMediaDescriptor.getPropertyValues(), aGuard ); 691 // <- SYNCHRONIZED 692 } 693 catch( const Exception& ) 694 { 695 Any aError = ::cppu::getCaughtException(); 696 if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) 697 || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) 698 || aError.isExtractableTo( ::cppu::UnoType< WrappedTargetException >::get() ) 699 ) 700 { 701 // allowed to leave 702 throw; 703 } 704 705 throw WrappedTargetException( ::rtl::OUString(), *this, aError ); 706 } 707 } 708 709 // ----------------------------------------------------------------------------- 710 // XModel 711 sal_Bool SAL_CALL ODatabaseDocument::attachResource( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException) 712 { 713 DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); 714 return impl_attachResource( _rURL, _rArguments, aGuard ); 715 } 716 717 // ----------------------------------------------------------------------------- 718 sal_Bool ODatabaseDocument::impl_attachResource( const ::rtl::OUString& i_rLogicalDocumentURL, 719 const Sequence< PropertyValue >& i_rMediaDescriptor, DocumentGuard& _rDocGuard ) 720 { 721 if ( ( i_rLogicalDocumentURL == getURL() ) 722 && ( i_rMediaDescriptor.getLength() == 1 ) 723 && ( i_rMediaDescriptor[0].Name.compareToAscii( "BreakMacroSignature" ) == 0 ) 724 ) 725 { 726 // this is a BAD hack of the Basic importer code ... there should be a dedicated API for this, 727 // not this bad mis-using of existing interfaces 728 return sal_False; 729 // (we do not support macro signatures, so we can ignore this call) 730 } 731 732 // if no URL has been provided, the caller was lazy enough to not call our getURL - which is not allowed anymore, 733 // now since getURL and getLocation both return the same, so calling one of those should be simple. 734 ::rtl::OUString sDocumentURL( i_rLogicalDocumentURL ); 735 OSL_ENSURE( sDocumentURL.getLength(), "ODatabaseDocument::impl_attachResource: invalid URL!" ); 736 if ( !sDocumentURL.getLength() ) 737 sDocumentURL = getURL(); 738 739 m_pImpl->setResource( sDocumentURL, i_rMediaDescriptor ); 740 741 if ( impl_isInitializing() ) 742 { // this means we've just been loaded, and this is the attachResource call which follows 743 // the load call. 744 impl_setInitialized(); 745 746 // determine whether the document as a whole, or sub documents, have macros. Especially the latter 747 // controls the availability of our XEmbeddedScripts and XScriptInvocationContext interfaces, and we 748 // should know this before anybody actually uses the object. 749 m_bAllowDocumentScripting = ( m_pImpl->determineEmbeddedMacros() != ODatabaseModelImpl::eSubDocumentMacros ); 750 751 _rDocGuard.clear(); 752 // <- SYNCHRONIZED 753 m_aEventNotifier.notifyDocumentEvent( "OnLoadFinished" ); 754 } 755 756 return sal_True; 757 } 758 759 // ----------------------------------------------------------------------------- 760 ::rtl::OUString SAL_CALL ODatabaseDocument::getURL( ) throw (RuntimeException) 761 { 762 DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); 763 return m_pImpl->getURL(); 764 } 765 766 // ----------------------------------------------------------------------------- 767 Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getArgs( ) throw (RuntimeException) 768 { 769 DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); 770 return m_pImpl->getMediaDescriptor().getPropertyValues(); 771 } 772 773 // ----------------------------------------------------------------------------- 774 void SAL_CALL ODatabaseDocument::connectController( const Reference< XController >& _xController ) throw (RuntimeException) 775 { 776 DocumentGuard aGuard( *this ); 777 778 #if OSL_DEBUG_LEVEL > 0 779 for ( Controllers::const_iterator controller = m_aControllers.begin(); 780 controller != m_aControllers.end(); 781 ++controller 782 ) 783 { 784 OSL_ENSURE( *controller != _xController, "ODatabaseDocument::connectController: this controller is already connected!" ); 785 } 786 #endif 787 788 m_aControllers.push_back( _xController ); 789 790 m_aEventNotifier.notifyDocumentEventAsync( "OnViewCreated", Reference< XController2 >( _xController, UNO_QUERY ) ); 791 792 bool bFirstControllerEver = m_aViewMonitor.onControllerConnected( _xController ); 793 if ( !bFirstControllerEver ) 794 return; 795 796 // check/adjust our macro mode. 797 m_pImpl->checkMacrosOnLoading(); 798 } 799 800 // ----------------------------------------------------------------------------- 801 void SAL_CALL ODatabaseDocument::disconnectController( const Reference< XController >& _xController ) throw (RuntimeException) 802 { 803 bool bNotifyViewClosed = false; 804 bool bLastControllerGone = false; 805 bool bIsClosing = false; 806 807 // SYNCHRONIZED -> 808 { 809 DocumentGuard aGuard( *this ); 810 811 Controllers::iterator pos = ::std::find( m_aControllers.begin(), m_aControllers.end(), _xController ); 812 OSL_ENSURE( pos != m_aControllers.end(), "ODatabaseDocument::disconnectController: don't know this controller!" ); 813 if ( pos != m_aControllers.end() ) 814 { 815 m_aControllers.erase( pos ); 816 bNotifyViewClosed = true; 817 } 818 819 if ( m_xCurrentController == _xController ) 820 m_xCurrentController = NULL; 821 822 bLastControllerGone = m_aControllers.empty(); 823 bIsClosing = m_bClosing; 824 } 825 // <- SYNCHRONIZED 826 827 if ( bNotifyViewClosed ) 828 m_aEventNotifier.notifyDocumentEvent( "OnViewClosed", Reference< XController2 >( _xController, UNO_QUERY ) ); 829 830 if ( bLastControllerGone && !bIsClosing ) 831 { 832 // if this was the last view, close the document as a whole 833 // #i51157# / 2006-03-16 / frank.schoenheit@sun.com 834 try 835 { 836 close( sal_True ); 837 } 838 catch( const CloseVetoException& ) 839 { 840 // okay, somebody vetoed and took ownership 841 } 842 } 843 } 844 845 // ----------------------------------------------------------------------------- 846 void SAL_CALL ODatabaseDocument::lockControllers( ) throw (RuntimeException) 847 { 848 DocumentGuard aGuard( *this ); 849 850 ++m_pImpl->m_nControllerLockCount; 851 } 852 853 // ----------------------------------------------------------------------------- 854 void SAL_CALL ODatabaseDocument::unlockControllers( ) throw (RuntimeException) 855 { 856 DocumentGuard aGuard( *this ); 857 858 --m_pImpl->m_nControllerLockCount; 859 } 860 861 // ----------------------------------------------------------------------------- 862 sal_Bool SAL_CALL ODatabaseDocument::hasControllersLocked( ) throw (RuntimeException) 863 { 864 DocumentGuard aGuard( *this ); 865 866 return m_pImpl->m_nControllerLockCount != 0; 867 } 868 869 // ----------------------------------------------------------------------------- 870 Reference< XController > SAL_CALL ODatabaseDocument::getCurrentController() throw (RuntimeException) 871 { 872 DocumentGuard aGuard( *this ); 873 874 return m_xCurrentController.is() ? m_xCurrentController : ( m_aControllers.empty() ? Reference< XController >() : *m_aControllers.begin() ); 875 } 876 877 // ----------------------------------------------------------------------------- 878 void SAL_CALL ODatabaseDocument::setCurrentController( const Reference< XController >& _xController ) throw (NoSuchElementException, RuntimeException) 879 { 880 DocumentGuard aGuard( *this ); 881 882 m_xCurrentController = _xController; 883 884 if ( !m_aViewMonitor.onSetCurrentController( _xController ) ) 885 return; 886 887 // check if there are sub components to recover from our document storage 888 bool bAttemptRecovery = m_bHasBeenRecovered; 889 if ( !bAttemptRecovery && m_pImpl->getMediaDescriptor().has( "ForceRecovery" ) ) 890 // do not use getOrDefault, it will throw for invalid types, which is not desired here 891 m_pImpl->getMediaDescriptor().get( "ForceRecovery" ) >>= bAttemptRecovery; 892 893 if ( !bAttemptRecovery ) 894 return; 895 896 try 897 { 898 DatabaseDocumentRecovery aDocRecovery( m_pImpl->m_aContext ); 899 aDocRecovery.recoverSubDocuments( m_pImpl->getRootStorage(), _xController ); 900 } 901 catch( const Exception& ) 902 { 903 DBG_UNHANDLED_EXCEPTION(); 904 } 905 } 906 907 // ----------------------------------------------------------------------------- 908 Reference< XInterface > SAL_CALL ODatabaseDocument::getCurrentSelection( ) throw (RuntimeException) 909 { 910 DocumentGuard aGuard( *this ); 911 912 Reference< XInterface > xRet; 913 Reference< XSelectionSupplier > xDocView( getCurrentController(), UNO_QUERY ); 914 if ( xDocView.is() ) 915 xRet.set(xDocView->getSelection(),UNO_QUERY); 916 917 return xRet; 918 } 919 // ----------------------------------------------------------------------------- 920 921 // XStorable 922 sal_Bool SAL_CALL ODatabaseDocument::hasLocation( ) throw (RuntimeException) 923 { 924 return getLocation().getLength() > 0; 925 } 926 // ----------------------------------------------------------------------------- 927 ::rtl::OUString SAL_CALL ODatabaseDocument::getLocation( ) throw (RuntimeException) 928 { 929 DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); 930 return m_pImpl->getURL(); 931 // both XStorable::getLocation and XModel::getURL have to return the URL of the document, *not* 932 // the location of the file which the docunment was possibly recovered from (which would be getDocFileLocation) 933 } 934 // ----------------------------------------------------------------------------- 935 sal_Bool SAL_CALL ODatabaseDocument::isReadonly( ) throw (RuntimeException) 936 { 937 DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); 938 return m_pImpl->m_bDocumentReadOnly; 939 } 940 // ----------------------------------------------------------------------------- 941 void SAL_CALL ODatabaseDocument::store( ) throw (IOException, RuntimeException) 942 { 943 DocumentGuard aGuard( *this ); 944 945 ::rtl::OUString sDocumentURL( m_pImpl->getURL() ); 946 if ( sDocumentURL.getLength() ) 947 { 948 if ( m_pImpl->getDocFileLocation() == m_pImpl->getURL() ) 949 if ( m_pImpl->m_bDocumentReadOnly ) 950 throw IOException(); 951 952 impl_storeAs_throw( m_pImpl->getURL(), m_pImpl->getMediaDescriptor(), SAVE, aGuard ); 953 return; 954 } 955 956 // if we have no URL, but did survive the DocumentGuard above, then we've been inited via XLoadable::initNew, 957 // i.e. we're based on a temporary storage 958 OSL_ENSURE( m_pImpl->getDocFileLocation().getLength() == 0, "ODatabaseDocument::store: unexpected URL inconsistency!" ); 959 960 try 961 { 962 impl_storeToStorage_throw( m_pImpl->getRootStorage(), m_pImpl->getMediaDescriptor().getPropertyValues(), aGuard ); 963 } 964 catch( const Exception& ) 965 { 966 Any aError = ::cppu::getCaughtException(); 967 if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) 968 || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) 969 ) 970 { 971 // allowed to leave 972 throw; 973 } 974 impl_throwIOExceptionCausedBySave_throw( aError, ::rtl::OUString() ); 975 } 976 } 977 978 // ----------------------------------------------------------------------------- 979 void ODatabaseDocument::impl_throwIOExceptionCausedBySave_throw( const Any& i_rError, const ::rtl::OUString& i_rTargetURL ) const 980 { 981 ::rtl::OUString sErrorMessage = extractExceptionMessage( m_pImpl->m_aContext, i_rError ); 982 sErrorMessage = ResourceManager::loadString( 983 RID_STR_ERROR_WHILE_SAVING, 984 "$location$", i_rTargetURL, 985 "$message$", sErrorMessage 986 ); 987 throw IOException( sErrorMessage, *const_cast< ODatabaseDocument* >( this ) ); 988 } 989 990 // ----------------------------------------------------------------------------- 991 void ODatabaseDocument::impl_storeAs_throw( const ::rtl::OUString& _rURL, const ::comphelper::NamedValueCollection& _rArguments, 992 const StoreType _eType, DocumentGuard& _rGuard ) throw ( IOException, RuntimeException ) 993 { 994 OSL_PRECOND( ( _eType == SAVE ) || ( _eType == SAVE_AS ), 995 "ODatabaseDocument::impl_storeAs_throw: you introduced a new type which cannot be handled here!" ); 996 997 // if we're in the process of initializing the document (which effectively means it is an implicit 998 // initialization triggered in storeAsURL), the we do not notify events, since to an observer, the SaveAs 999 // should not be noticable 1000 bool bIsInitializationProcess = impl_isInitializing(); 1001 1002 if ( !bIsInitializationProcess ) 1003 { 1004 _rGuard.clear(); 1005 m_aEventNotifier.notifyDocumentEvent( _eType == SAVE ? "OnSave" : "OnSaveAs", NULL, makeAny( _rURL ) ); 1006 _rGuard.reset(); 1007 } 1008 1009 Reference< XStorage > xNewRootStorage; 1010 // will be non-NULL if our storage changed 1011 1012 try 1013 { 1014 ModifyLock aLock( *this ); 1015 // ignore all changes of our "modified" state during storing 1016 1017 sal_Bool bLocationChanged = ( _rURL != m_pImpl->getDocFileLocation() ); 1018 if ( bLocationChanged ) 1019 { 1020 // create storage for target URL 1021 Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( _rURL ) ); 1022 1023 if ( m_pImpl->isEmbeddedDatabase() ) 1024 m_pImpl->clearConnections(); 1025 1026 // commit everything 1027 m_pImpl->commitEmbeddedStorage(); 1028 m_pImpl->commitStorages(); 1029 1030 // copy own storage to target storage 1031 Reference< XStorage > xCurrentStorage( m_pImpl->getRootStorage() ); 1032 if ( xCurrentStorage.is() ) 1033 xCurrentStorage->copyToStorage( xTargetStorage ); 1034 1035 m_pImpl->disposeStorages(); 1036 1037 // each and every document definition obtained via m_xForms and m_xReports depends 1038 // on the sub storages which we just disposed. So, dispose the forms/reports collections, too. 1039 // This ensures that they're re-created when needed. 1040 clearObjectContainer( m_xForms ); 1041 clearObjectContainer( m_xReports ); 1042 1043 xNewRootStorage = m_pImpl->switchToStorage( xTargetStorage ); 1044 1045 m_pImpl->m_bDocumentReadOnly = sal_False; 1046 } 1047 1048 // store to current storage 1049 Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_QUERY_THROW ); 1050 Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) ); 1051 impl_storeToStorage_throw( xCurrentStorage, aMediaDescriptor, _rGuard ); 1052 1053 // success - tell our impl 1054 m_pImpl->setDocFileLocation( _rURL ); 1055 m_pImpl->setResource( _rURL, aMediaDescriptor ); 1056 1057 // if we are in an initialization process, then this is finished, now that we stored the document 1058 if ( bIsInitializationProcess ) 1059 impl_setInitialized(); 1060 } 1061 catch( const Exception& ) 1062 { 1063 Any aError = ::cppu::getCaughtException(); 1064 1065 // notify the failure 1066 if ( !bIsInitializationProcess ) 1067 m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveFailed" : "OnSaveAsFailed", NULL, makeAny( _rURL ) ); 1068 1069 if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) 1070 || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) 1071 ) 1072 { 1073 // allowed to leave 1074 throw; 1075 } 1076 1077 impl_throwIOExceptionCausedBySave_throw( aError, _rURL ); 1078 } 1079 1080 // notify the document event 1081 if ( !bIsInitializationProcess ) 1082 m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveDone" : "OnSaveAsDone", NULL, makeAny( _rURL ) ); 1083 1084 // reset our "modified" flag, and clear the guard 1085 impl_setModified_nothrow( sal_False, _rGuard ); 1086 // <- SYNCHRONIZED 1087 1088 // notify storage listeners 1089 if ( xNewRootStorage.is() ) 1090 impl_notifyStorageChange_nolck_nothrow( xNewRootStorage ); 1091 } 1092 1093 // ----------------------------------------------------------------------------- 1094 Reference< XStorage > ODatabaseDocument::impl_createStorageFor_throw( const ::rtl::OUString& _rURL ) const 1095 { 1096 Reference < ::com::sun::star::ucb::XSimpleFileAccess > xTempAccess; 1097 m_pImpl->m_aContext.createComponent( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ,xTempAccess); 1098 Reference< io::XStream > xStream = xTempAccess->openFileReadWrite( _rURL ); 1099 Reference< io::XTruncate > xTruncate(xStream,UNO_QUERY); 1100 if ( xTruncate.is() ) 1101 { 1102 xTruncate->truncate(); 1103 } 1104 Sequence<Any> aParam(2); 1105 aParam[0] <<= xStream; 1106 aParam[1] <<= ElementModes::READWRITE | ElementModes::TRUNCATE; 1107 1108 Reference< XSingleServiceFactory > xStorageFactory( m_pImpl->createStorageFactory(), UNO_SET_THROW ); 1109 return Reference< XStorage >( xStorageFactory->createInstanceWithArguments( aParam ), UNO_QUERY_THROW ); 1110 } 1111 1112 // ----------------------------------------------------------------------------- 1113 void SAL_CALL ODatabaseDocument::storeAsURL( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException) 1114 { 1115 // SYNCHRONIZED -> 1116 DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); 1117 1118 // Normally, a document initialization is done via XLoadable::load or XLoadable::initNew. For convenience 1119 // reasons, and to not break existing API clients, it's allowed to call storeAsURL without having initialized 1120 // the document, in which case the initialization will be done implicitly. 1121 bool bImplicitInitialization = !impl_isInitialized(); 1122 // implicit initialization while another initialization is just running is not possible 1123 if ( bImplicitInitialization && impl_isInitializing() ) 1124 throw DoubleInitializationException(); 1125 1126 if ( bImplicitInitialization ) 1127 impl_setInitializing(); 1128 1129 try 1130 { 1131 impl_storeAs_throw( _rURL, _rArguments, SAVE_AS, aGuard ); 1132 // <- SYNCHRONIZED 1133 1134 // impl_storeAs_throw cleared the lock on our mutex, but the below lines need this lock 1135 // SYNCHRONIZED -> 1136 aGuard.reset(); 1137 1138 // our title might have changed, potentially at least 1139 // Sadly, we cannot check this: Calling getTitle here and now would not deliver 1140 // an up-to-date result, as the call is delegated to our TitleHelper instance, which itself 1141 // updates its title only if it gets the OnSaveAsDone event (which was sent asynchronously 1142 // by impl_storeAs_throw). So, we simply notify always, and also asynchronously 1143 m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" ); 1144 } 1145 catch( const Exception& ) 1146 { 1147 impl_reset_nothrow(); 1148 throw; 1149 } 1150 1151 if ( bImplicitInitialization ) 1152 m_bAllowDocumentScripting = true; 1153 1154 aGuard.clear(); 1155 // <- SYNCHRONIZED 1156 1157 if ( bImplicitInitialization ) 1158 m_aEventNotifier.notifyDocumentEvent( "OnCreate" ); 1159 } 1160 1161 // ----------------------------------------------------------------------------- 1162 void ODatabaseDocument::impl_storeToStorage_throw( const Reference< XStorage >& _rxTargetStorage, const Sequence< PropertyValue >& _rMediaDescriptor, 1163 DocumentGuard& _rDocGuard ) const 1164 { 1165 if ( !_rxTargetStorage.is() ) 1166 throw IllegalArgumentException( ::rtl::OUString(), *const_cast< ODatabaseDocument* >( this ), 1 ); 1167 1168 if ( !m_pImpl.is() ) 1169 throw DisposedException( ::rtl::OUString(), *const_cast< ODatabaseDocument* >( this ) ); 1170 1171 try 1172 { 1173 // commit everything 1174 m_pImpl->commitEmbeddedStorage(); 1175 m_pImpl->commitStorages(); 1176 1177 // copy own storage to target storage 1178 if ( impl_isInitialized() ) 1179 { 1180 Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_QUERY_THROW ); 1181 if ( xCurrentStorage != _rxTargetStorage ) 1182 xCurrentStorage->copyToStorage( _rxTargetStorage ); 1183 } 1184 1185 // write into target storage 1186 ::comphelper::NamedValueCollection aWriteArgs( _rMediaDescriptor ); 1187 lcl_triggerStatusIndicator_throw( aWriteArgs, _rDocGuard, true ); 1188 impl_writeStorage_throw( _rxTargetStorage, aWriteArgs ); 1189 lcl_triggerStatusIndicator_throw( aWriteArgs, _rDocGuard, false ); 1190 1191 // commit target storage 1192 OSL_VERIFY( tools::stor::commitStorageIfWriteable( _rxTargetStorage ) ); 1193 } 1194 catch( const IOException& ) { throw; } 1195 catch( const RuntimeException& ) { throw; } 1196 catch ( const Exception& e ) 1197 { 1198 throw IOException( e.Message, *const_cast< ODatabaseDocument* >( this ) ); 1199 } 1200 } 1201 1202 // ----------------------------------------------------------------------------- 1203 void SAL_CALL ODatabaseDocument::storeToURL( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException) 1204 { 1205 DocumentGuard aGuard( *this ); 1206 ModifyLock aLock( *this ); 1207 1208 { 1209 aGuard.clear(); 1210 m_aEventNotifier.notifyDocumentEvent( "OnSaveTo", NULL, makeAny( _rURL ) ); 1211 aGuard.reset(); 1212 } 1213 1214 try 1215 { 1216 // create storage for target URL 1217 Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( _rURL ) ); 1218 1219 // extend media descriptor with URL 1220 Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) ); 1221 1222 // store to this storage 1223 impl_storeToStorage_throw( xTargetStorage, aMediaDescriptor, aGuard ); 1224 } 1225 catch( const Exception& ) 1226 { 1227 Any aError = ::cppu::getCaughtException(); 1228 m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToFailed", NULL, aError ); 1229 1230 if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) 1231 || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) 1232 ) 1233 { 1234 // allowed to leave 1235 throw; 1236 } 1237 1238 impl_throwIOExceptionCausedBySave_throw( aError, _rURL ); 1239 } 1240 1241 m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToDone", NULL, makeAny( _rURL ) ); 1242 } 1243 1244 // ----------------------------------------------------------------------------- 1245 // XModifyBroadcaster 1246 void SAL_CALL ODatabaseDocument::addModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException) 1247 { 1248 DocumentGuard aGuard( *this ); 1249 m_aModifyListeners.addInterface(_xListener); 1250 } 1251 1252 // ----------------------------------------------------------------------------- 1253 void SAL_CALL ODatabaseDocument::removeModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException) 1254 { 1255 DocumentGuard aGuard( *this ); 1256 m_aModifyListeners.removeInterface(_xListener); 1257 } 1258 1259 // ----------------------------------------------------------------------------- 1260 // XModifiable 1261 sal_Bool SAL_CALL ODatabaseDocument::isModified( ) throw (RuntimeException) 1262 { 1263 DocumentGuard aGuard( *this ); 1264 1265 return m_pImpl->m_bModified; 1266 } 1267 1268 // ----------------------------------------------------------------------------- 1269 void SAL_CALL ODatabaseDocument::setModified( sal_Bool _bModified ) throw (PropertyVetoException, RuntimeException) 1270 { 1271 DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); 1272 if ( impl_isInitialized() ) 1273 impl_setModified_nothrow( _bModified, aGuard ); 1274 // it's allowed to call setModified without the document being initialized already. In this case, 1275 // we simply ignore the call - when the initialization is finished, the respective code will set 1276 // a proper "modified" flag 1277 } 1278 1279 // ----------------------------------------------------------------------------- 1280 void ODatabaseDocument::impl_setModified_nothrow( sal_Bool _bModified, DocumentGuard& _rGuard ) 1281 { 1282 // SYNCHRONIZED -> 1283 bool bModifiedChanged = ( m_pImpl->m_bModified != _bModified ) && ( !m_pImpl->isModifyLocked() ); 1284 1285 if ( bModifiedChanged ) 1286 { 1287 m_pImpl->m_bModified = _bModified; 1288 m_aEventNotifier.notifyDocumentEventAsync( "OnModifyChanged" ); 1289 } 1290 _rGuard.clear(); 1291 // <- SYNCHRONIZED 1292 1293 if ( bModifiedChanged ) 1294 { 1295 lang::EventObject aEvent( *this ); 1296 m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent ); 1297 } 1298 } 1299 1300 // ----------------------------------------------------------------------------- 1301 // ::com::sun::star::document::XEventBroadcaster 1302 void SAL_CALL ODatabaseDocument::addEventListener(const uno::Reference< document::XEventListener >& _Listener ) throw (uno::RuntimeException) 1303 { 1304 m_aEventNotifier.addLegacyEventListener( _Listener ); 1305 } 1306 1307 // ----------------------------------------------------------------------------- 1308 void SAL_CALL ODatabaseDocument::removeEventListener( const uno::Reference< document::XEventListener >& _Listener ) throw (uno::RuntimeException) 1309 { 1310 m_aEventNotifier.removeLegacyEventListener( _Listener ); 1311 } 1312 1313 // ----------------------------------------------------------------------------- 1314 void SAL_CALL ODatabaseDocument::addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) throw (RuntimeException) 1315 { 1316 m_aEventNotifier.addDocumentEventListener( _Listener ); 1317 } 1318 1319 // ----------------------------------------------------------------------------- 1320 void SAL_CALL ODatabaseDocument::removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) throw (RuntimeException) 1321 { 1322 m_aEventNotifier.removeDocumentEventListener( _Listener ); 1323 } 1324 1325 // ----------------------------------------------------------------------------- 1326 void SAL_CALL ODatabaseDocument::notifyDocumentEvent( const ::rtl::OUString& _EventName, const Reference< XController2 >& _ViewController, const Any& _Supplement ) throw (IllegalArgumentException, NoSupportException, RuntimeException) 1327 { 1328 if ( !_EventName.getLength() ) 1329 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 1330 1331 // SYNCHRONIZED -> 1332 DocumentGuard aGuard( *this ); 1333 1334 if ( !DocumentEvents::needsSynchronousNotification( _EventName ) ) 1335 { 1336 m_aEventNotifier.notifyDocumentEventAsync( _EventName, _ViewController, _Supplement ); 1337 return; 1338 } 1339 aGuard.clear(); 1340 // <- SYNCHRONIZED 1341 1342 m_aEventNotifier.notifyDocumentEvent( _EventName, _ViewController, _Supplement ); 1343 } 1344 1345 // ----------------------------------------------------------------------------- 1346 Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getPrinter( ) throw (RuntimeException) 1347 { 1348 DBG_ERROR( "ODatabaseDocument::getPrinter: not supported!" ); 1349 return Sequence< PropertyValue >(); 1350 } 1351 1352 // ----------------------------------------------------------------------------- 1353 void SAL_CALL ODatabaseDocument::setPrinter( const Sequence< PropertyValue >& /*aPrinter*/ ) throw (IllegalArgumentException, RuntimeException) 1354 { 1355 DBG_ERROR( "ODatabaseDocument::setPrinter: not supported!" ); 1356 } 1357 1358 // ----------------------------------------------------------------------------- 1359 void SAL_CALL ODatabaseDocument::print( const Sequence< PropertyValue >& /*xOptions*/ ) throw (IllegalArgumentException, RuntimeException) 1360 { 1361 DBG_ERROR( "ODatabaseDocument::print: not supported!" ); 1362 } 1363 1364 // ----------------------------------------------------------------------------- 1365 void ODatabaseDocument::impl_reparent_nothrow( const WeakReference< XNameAccess >& _rxContainer ) 1366 { 1367 Reference< XChild > xChild( _rxContainer.get(), UNO_QUERY ); 1368 if ( xChild.is() ) 1369 xChild->setParent( *this ); 1370 } 1371 // ----------------------------------------------------------------------------- 1372 void ODatabaseDocument::clearObjectContainer( WeakReference< XNameAccess >& _rxContainer) 1373 { 1374 Reference< XNameAccess > xContainer = _rxContainer; 1375 ::comphelper::disposeComponent( xContainer ); 1376 1377 Reference< XChild > xChild( _rxContainer.get(),UNO_QUERY ); 1378 if ( xChild.is() ) 1379 xChild->setParent( NULL ); 1380 _rxContainer = Reference< XNameAccess >(); 1381 } 1382 // ----------------------------------------------------------------------------- 1383 Reference< XNameAccess > ODatabaseDocument::impl_getDocumentContainer_throw( ODatabaseModelImpl::ObjectType _eType ) 1384 { 1385 if ( ( _eType != ODatabaseModelImpl::E_FORM ) && ( _eType != ODatabaseModelImpl::E_REPORT ) ) 1386 throw IllegalArgumentException(); 1387 1388 bool bFormsContainer = _eType == ODatabaseModelImpl::E_FORM; 1389 1390 WeakReference< XNameAccess >& rContainerRef( bFormsContainer ? m_xForms : m_xReports ); 1391 Reference< XNameAccess > xContainer = rContainerRef; 1392 if ( !xContainer.is() ) 1393 { 1394 Any aValue; 1395 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xMy(*this); 1396 if ( dbtools::getDataSourceSetting(xMy,bFormsContainer ? "Forms" : "Reports",aValue) ) 1397 { 1398 ::rtl::OUString sSupportService; 1399 aValue >>= sSupportService; 1400 if ( sSupportService.getLength() ) 1401 { 1402 Sequence<Any> aArgs(1); 1403 aArgs[0] <<= NamedValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DatabaseDocument")),makeAny(xMy)); 1404 xContainer.set(m_pImpl->m_aContext.createComponentWithArguments(sSupportService,aArgs),UNO_QUERY); 1405 rContainerRef = xContainer; 1406 } 1407 } 1408 if ( !xContainer.is() ) 1409 { 1410 TContentPtr& rContainerData( m_pImpl->getObjectContainer( _eType ) ); 1411 rContainerRef = xContainer = new ODocumentContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, bFormsContainer ); 1412 } 1413 impl_reparent_nothrow( xContainer ); 1414 } 1415 return xContainer; 1416 } 1417 1418 // ----------------------------------------------------------------------------- 1419 void ODatabaseDocument::impl_closeControllerFrames_nolck_throw( sal_Bool _bDeliverOwnership ) 1420 { 1421 Controllers aCopy = m_aControllers; 1422 1423 Controllers::iterator aEnd = aCopy.end(); 1424 for ( Controllers::iterator aIter = aCopy.begin(); aIter != aEnd ; ++aIter ) 1425 { 1426 if ( !aIter->is() ) 1427 continue; 1428 1429 try 1430 { 1431 Reference< XCloseable> xFrame( (*aIter)->getFrame(), UNO_QUERY ); 1432 if ( xFrame.is() ) 1433 xFrame->close( _bDeliverOwnership ); 1434 } 1435 catch( const CloseVetoException& ) { throw; } 1436 catch( const Exception& ) 1437 { 1438 DBG_UNHANDLED_EXCEPTION(); 1439 } 1440 } 1441 } 1442 1443 // ----------------------------------------------------------------------------- 1444 struct DisposeControllerFrame : public ::std::unary_function< Reference< XController >, void > 1445 { 1446 void operator()( const Reference< XController >& _rxController ) const 1447 { 1448 try 1449 { 1450 if ( !_rxController.is() ) 1451 return; 1452 1453 Reference< XFrame > xFrame( _rxController->getFrame() ); 1454 ::comphelper::disposeComponent( xFrame ); 1455 } 1456 catch( const Exception& ) 1457 { 1458 DBG_UNHANDLED_EXCEPTION(); 1459 } 1460 }; 1461 }; 1462 1463 // ----------------------------------------------------------------------------- 1464 void ODatabaseDocument::impl_disposeControllerFrames_nothrow() 1465 { 1466 Controllers aCopy; 1467 aCopy.swap( m_aControllers ); // ensure m_aControllers is empty afterwards 1468 ::std::for_each( aCopy.begin(), aCopy.end(), DisposeControllerFrame() ); 1469 } 1470 1471 // ----------------------------------------------------------------------------- 1472 void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw (CloseVetoException, RuntimeException) 1473 { 1474 // nearly everything below can/must be done without our mutex locked, the below is just for 1475 // the checks for being disposed and the like 1476 // SYNCHRONIZED -> 1477 { 1478 DocumentGuard aGuard( *this ); 1479 m_bClosing = true; 1480 } 1481 // <- SYNCHRONIZED 1482 1483 try 1484 { 1485 // allow listeners to veto 1486 lang::EventObject aEvent( *this ); 1487 m_aCloseListener.forEach< XCloseListener >( 1488 boost::bind( &XCloseListener::queryClosing, _1, boost::cref( aEvent ), boost::cref( _bDeliverOwnership ) ) ); 1489 1490 // notify that we're going to unload 1491 m_aEventNotifier.notifyDocumentEvent( "OnPrepareUnload" ); 1492 1493 impl_closeControllerFrames_nolck_throw( _bDeliverOwnership ); 1494 1495 m_aCloseListener.notifyEach( &XCloseListener::notifyClosing, (const lang::EventObject&)aEvent ); 1496 1497 dispose(); 1498 } 1499 catch ( const Exception& ) 1500 { 1501 ::osl::MutexGuard aGuard( m_aMutex ); 1502 m_bClosing = false; 1503 throw; 1504 } 1505 1506 // SYNCHRONIZED -> 1507 ::osl::MutexGuard aGuard( m_aMutex ); 1508 m_bClosing = false; 1509 // <- SYNCHRONIZED 1510 } 1511 // ----------------------------------------------------------------------------- 1512 void SAL_CALL ODatabaseDocument::addCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) 1513 { 1514 DocumentGuard aGuard( *this ); 1515 m_aCloseListener.addInterface(Listener); 1516 } 1517 // ----------------------------------------------------------------------------- 1518 void SAL_CALL ODatabaseDocument::removeCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) 1519 { 1520 DocumentGuard aGuard( *this ); 1521 m_aCloseListener.removeInterface(Listener); 1522 } 1523 // ----------------------------------------------------------------------------- 1524 Reference< XNameAccess > SAL_CALL ODatabaseDocument::getFormDocuments( ) throw (RuntimeException) 1525 { 1526 DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); 1527 return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_FORM ); 1528 } 1529 // ----------------------------------------------------------------------------- 1530 Reference< XNameAccess > SAL_CALL ODatabaseDocument::getReportDocuments( ) throw (RuntimeException) 1531 { 1532 DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); 1533 return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_REPORT ); 1534 } 1535 1536 // ----------------------------------------------------------------------------- 1537 void ODatabaseDocument::WriteThroughComponent( const Reference< XComponent >& xComponent, const sal_Char* pStreamName, 1538 const sal_Char* pServiceName, const Sequence< Any >& _rArguments, const Sequence< PropertyValue >& rMediaDesc, 1539 const Reference<XStorage>& _xStorageToSaveTo ) const 1540 { 1541 OSL_ENSURE( pStreamName, "Need stream name!" ); 1542 OSL_ENSURE( pServiceName, "Need service name!" ); 1543 1544 // open stream 1545 ::rtl::OUString sStreamName = ::rtl::OUString::createFromAscii( pStreamName ); 1546 Reference< XStream > xStream = _xStorageToSaveTo->openStreamElement( sStreamName, ElementModes::READWRITE | ElementModes::TRUNCATE ); 1547 if ( !xStream.is() ) 1548 return; 1549 1550 Reference< XOutputStream > xOutputStream( xStream->getOutputStream() ); 1551 OSL_ENSURE( xOutputStream.is(), "Can't create output stream in package!" ); 1552 if ( !xOutputStream.is() ) 1553 return; 1554 1555 Reference< XSeekable > xSeek( xOutputStream, UNO_QUERY ); 1556 if ( xSeek.is() ) 1557 xSeek->seek(0); 1558 1559 Reference< XPropertySet > xStreamProp( xOutputStream, UNO_QUERY_THROW ); 1560 xStreamProp->setPropertyValue( INFO_MEDIATYPE, makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "text/xml" ) ) ) ); 1561 xStreamProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), makeAny( (sal_Bool)sal_True ) ); 1562 1563 // write the stuff 1564 WriteThroughComponent( xOutputStream, xComponent, pServiceName, _rArguments, rMediaDesc ); 1565 } 1566 1567 void ODatabaseDocument::WriteThroughComponent( const Reference< XOutputStream >& xOutputStream, 1568 const Reference< XComponent >& xComponent, const sal_Char* pServiceName, const Sequence< Any >& _rArguments, 1569 const Sequence< PropertyValue >& rMediaDesc ) const 1570 { 1571 OSL_ENSURE( xOutputStream.is(), "I really need an output stream!" ); 1572 OSL_ENSURE( xComponent.is(), "Need component!" ); 1573 OSL_ENSURE( NULL != pServiceName, "Need component name!" ); 1574 1575 // get component 1576 Reference< XActiveDataSource > xSaxWriter; 1577 OSL_VERIFY( m_pImpl->m_aContext.createComponent( "com.sun.star.xml.sax.Writer", xSaxWriter ) ); 1578 if ( !xSaxWriter.is() ) 1579 return; 1580 1581 // connect XML writer to output stream 1582 xSaxWriter->setOutputStream( xOutputStream ); 1583 1584 // prepare arguments (prepend doc handler to given arguments) 1585 Reference< XDocumentHandler > xDocHandler( xSaxWriter,UNO_QUERY); 1586 Sequence<Any> aArgs( 1 + _rArguments.getLength() ); 1587 aArgs[0] <<= xDocHandler; 1588 for ( sal_Int32 i = 0; i < _rArguments.getLength(); ++i ) 1589 aArgs[ i+1 ] = _rArguments[i]; 1590 1591 // get filter component 1592 Reference< XExporter > xExporter; 1593 OSL_VERIFY( m_pImpl->m_aContext.createComponentWithArguments( pServiceName, aArgs, xExporter ) ); 1594 if ( !xExporter.is() ) 1595 return; 1596 1597 // connect model and filter 1598 xExporter->setSourceDocument( xComponent ); 1599 1600 // filter 1601 Reference< XFilter > xFilter( xExporter, UNO_QUERY_THROW ); 1602 xFilter->filter( rMediaDesc ); 1603 } 1604 1605 // ----------------------------------------------------------------------------- 1606 void ODatabaseDocument::impl_writeStorage_throw( const Reference< XStorage >& _rxTargetStorage, const ::comphelper::NamedValueCollection& _rMediaDescriptor ) const 1607 { 1608 // extract status indicator 1609 Sequence< Any > aDelegatorArguments; 1610 lcl_extractStatusIndicator( _rMediaDescriptor, aDelegatorArguments ); 1611 1612 /** property map for export info set */ 1613 comphelper::PropertyMapEntry aExportInfoMap[] = 1614 { 1615 { MAP_LEN( "BaseURI"), 0,&::getCppuType( (::rtl::OUString *)0 ),beans::PropertyAttribute::MAYBEVOID, 0 }, 1616 { MAP_LEN( "StreamName"), 0,&::getCppuType( (::rtl::OUString *)0 ),beans::PropertyAttribute::MAYBEVOID, 0 }, 1617 { MAP_LEN( "UsePrettyPrinting" ), 0, &::getCppuType((sal_Bool*)0), beans::PropertyAttribute::MAYBEVOID, 0}, 1618 { NULL, 0, 0, NULL, 0, 0 } 1619 }; 1620 uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) ); 1621 1622 SvtSaveOptions aSaveOpt; 1623 xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UsePrettyPrinting")), uno::makeAny(aSaveOpt.IsPrettyPrinting())); 1624 if ( aSaveOpt.IsSaveRelFSys() ) 1625 xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI")), uno::makeAny(_rMediaDescriptor.getOrDefault("URL",::rtl::OUString()))); 1626 1627 ::rtl::OUString aVersion; 1628 SvtSaveOptions::ODFDefaultVersion nDefVersion = aSaveOpt.GetODFDefaultVersion(); 1629 1630 // older versions can not have this property set, it exists only starting from ODF1.2 1631 if ( nDefVersion >= SvtSaveOptions::ODFVER_012 ) 1632 aVersion = ODFVER_012_TEXT; 1633 1634 if ( aVersion.getLength() ) 1635 { 1636 try 1637 { 1638 xInfoSet->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Version" )), uno::makeAny( aVersion ) ); 1639 } 1640 catch( uno::Exception& ) 1641 { 1642 } 1643 } 1644 1645 sal_Int32 nArgsLen = aDelegatorArguments.getLength(); 1646 aDelegatorArguments.realloc(nArgsLen+1); 1647 aDelegatorArguments[nArgsLen++] <<= xInfoSet; 1648 1649 Reference< XPropertySet > xProp( _rxTargetStorage, UNO_QUERY_THROW ); 1650 xProp->setPropertyValue( INFO_MEDIATYPE, makeAny( (rtl::OUString)MIMETYPE_OASIS_OPENDOCUMENT_DATABASE ) ); 1651 1652 Reference< XComponent > xComponent( *const_cast< ODatabaseDocument* >( this ), UNO_QUERY_THROW ); 1653 1654 Sequence< PropertyValue > aMediaDescriptor; 1655 _rMediaDescriptor >>= aMediaDescriptor; 1656 1657 xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamName")), uno::makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("settings.xml")))); 1658 WriteThroughComponent( xComponent, "settings.xml", "com.sun.star.comp.sdb.XMLSettingsExporter", 1659 aDelegatorArguments, aMediaDescriptor, _rxTargetStorage ); 1660 1661 xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamName")), uno::makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("content.xml")))); 1662 WriteThroughComponent( xComponent, "content.xml", "com.sun.star.comp.sdb.DBExportFilter", 1663 aDelegatorArguments, aMediaDescriptor, _rxTargetStorage ); 1664 1665 m_pImpl->storeLibraryContainersTo( _rxTargetStorage ); 1666 } 1667 1668 // ----------------------------------------------------------------------------- 1669 Reference< XUIConfigurationManager > SAL_CALL ODatabaseDocument::getUIConfigurationManager( ) throw (RuntimeException) 1670 { 1671 DocumentGuard aGuard( *this ); 1672 1673 if ( !m_xUIConfigurationManager.is() ) 1674 { 1675 m_pImpl->m_aContext.createComponent( "com.sun.star.ui.UIConfigurationManager", m_xUIConfigurationManager ); 1676 Reference< XUIConfigurationStorage > xUIConfigStorage( m_xUIConfigurationManager, UNO_QUERY ); 1677 if ( xUIConfigStorage.is() ) 1678 { 1679 rtl::OUString aUIConfigFolderName( RTL_CONSTASCII_USTRINGPARAM( "Configurations2" )); 1680 Reference< XStorage > xConfigStorage; 1681 1682 // First try to open with READWRITE and then READ 1683 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READWRITE ); 1684 if ( xConfigStorage.is() ) 1685 { 1686 rtl::OUString aUIConfigMediaType( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.xml.ui.configuration" )); 1687 rtl::OUString aMediaType; 1688 Reference< XPropertySet > xPropSet( xConfigStorage, UNO_QUERY ); 1689 Any a = xPropSet->getPropertyValue( INFO_MEDIATYPE ); 1690 if ( !( a >>= aMediaType ) || ( aMediaType.getLength() == 0 )) 1691 { 1692 a <<= aUIConfigMediaType; 1693 xPropSet->setPropertyValue( INFO_MEDIATYPE, a ); 1694 } 1695 } 1696 else 1697 xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READ ); 1698 1699 // initialize ui configuration manager with document substorage 1700 xUIConfigStorage->setStorage( xConfigStorage ); 1701 } 1702 } 1703 1704 return m_xUIConfigurationManager; 1705 } 1706 // ----------------------------------------------------------------------------- 1707 Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentSubStorage( const ::rtl::OUString& aStorageName, sal_Int32 nMode ) throw (RuntimeException) 1708 { 1709 DocumentGuard aGuard( *this ); 1710 1711 Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() ); 1712 return xStorageAccess->getDocumentSubStorage( aStorageName, nMode ); 1713 } 1714 // ----------------------------------------------------------------------------- 1715 Sequence< ::rtl::OUString > SAL_CALL ODatabaseDocument::getDocumentSubStoragesNames( ) throw (::com::sun::star::io::IOException, RuntimeException) 1716 { 1717 Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() ); 1718 return xStorageAccess->getDocumentSubStoragesNames(); 1719 } 1720 1721 //------------------------------------------------------------------------------ 1722 void ODatabaseDocument::impl_notifyStorageChange_nolck_nothrow( const Reference< XStorage >& _rxNewRootStorage ) 1723 { 1724 Reference< XInterface > xMe( *const_cast< ODatabaseDocument* >( this ) ); 1725 1726 m_aStorageListeners.forEach< XStorageChangeListener >( 1727 boost::bind( &XStorageChangeListener::notifyStorageChange, _1, boost::cref( xMe ), boost::cref( _rxNewRootStorage ) ) ); 1728 } 1729 1730 //------------------------------------------------------------------------------ 1731 void ODatabaseDocument::disposing() 1732 { 1733 OSL_TRACE( "DD: disp: %p: %p", this, m_pImpl.get() ); 1734 if ( !m_pImpl.is() ) 1735 { 1736 // this means that we're already disposed 1737 DBG_ASSERT( ODatabaseDocument_OfficeDocument::rBHelper.bDisposed, "ODatabaseDocument::disposing: no impl anymore, but not yet disposed!" ); 1738 return; 1739 } 1740 1741 if ( impl_isInitialized() ) 1742 m_aEventNotifier.notifyDocumentEvent( "OnUnload" ); 1743 1744 Reference< XModel > xHoldAlive( this ); 1745 1746 m_aEventNotifier.disposing(); 1747 1748 lang::EventObject aDisposeEvent(static_cast<XWeak*>(this)); 1749 m_aModifyListeners.disposeAndClear( aDisposeEvent ); 1750 m_aCloseListener.disposeAndClear( aDisposeEvent ); 1751 m_aStorageListeners.disposeAndClear( aDisposeEvent ); 1752 1753 // this is the list of objects which we currently hold as member. Upon resetting 1754 // those members, we can (potentially) release the last reference to them, in which 1755 // case they will be deleted - if they're C++ implementations, that is :). 1756 // Some of those implementations are offending enough to require the SolarMutex, which 1757 // means we should not release the last reference while our own mutex is locked ... 1758 ::std::list< Reference< XInterface > > aKeepAlive; 1759 1760 // SYNCHRONIZED -> 1761 ::osl::ClearableMutexGuard aGuard( m_aMutex ); 1762 1763 DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); 1764 // normally, nobody should explicitly dispose, but only XCloseable::close the document. And upon 1765 // closing, our controllers are closed, too 1766 1767 aKeepAlive.push_back( m_xUIConfigurationManager ); 1768 m_xUIConfigurationManager = NULL; 1769 1770 clearObjectContainer( m_xForms ); 1771 clearObjectContainer( m_xReports ); 1772 1773 // reset the macro mode: in case the our impl struct stays alive (e.g. because our DataSource 1774 // object still exists), and somebody subsequently re-opens the document, we want to have 1775 // the security warning, again. 1776 m_pImpl->resetMacroExecutionMode(); 1777 1778 // similar argueing for our ViewMonitor 1779 m_aViewMonitor.reset(); 1780 1781 // tell our Impl to forget us 1782 m_pImpl->modelIsDisposing( impl_isInitialized(), ODatabaseModelImpl::ResetModelAccess() ); 1783 1784 // now, at the latest, the controller array should be empty. Controllers are 1785 // expected to listen for our disposal, and disconnect then 1786 DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); 1787 impl_disposeControllerFrames_nothrow(); 1788 1789 aKeepAlive.push_back( m_xModuleManager ); 1790 m_xModuleManager.clear(); 1791 1792 aKeepAlive.push_back( m_xTitleHelper ); 1793 m_xTitleHelper.clear(); 1794 1795 m_pImpl.clear(); 1796 1797 aGuard.clear(); 1798 // <- SYNCHRONIZED 1799 1800 aKeepAlive.clear(); 1801 } 1802 // ----------------------------------------------------------------------------- 1803 // XComponent 1804 void SAL_CALL ODatabaseDocument::dispose( ) throw (RuntimeException) 1805 { 1806 ::cppu::WeakComponentImplHelperBase::dispose(); 1807 } 1808 // ----------------------------------------------------------------------------- 1809 void SAL_CALL ODatabaseDocument::addEventListener( const Reference< lang::XEventListener >& _xListener ) throw (RuntimeException) 1810 { 1811 ::cppu::WeakComponentImplHelperBase::addEventListener( _xListener ); 1812 } 1813 // ----------------------------------------------------------------------------- 1814 void SAL_CALL ODatabaseDocument::removeEventListener( const Reference< lang::XEventListener >& _xListener ) throw (RuntimeException) 1815 { 1816 ::cppu::WeakComponentImplHelperBase::removeEventListener( _xListener ); 1817 } 1818 // XServiceInfo 1819 //------------------------------------------------------------------------------ 1820 rtl::OUString ODatabaseDocument::getImplementationName( ) throw(RuntimeException) 1821 { 1822 return getImplementationName_static(); 1823 } 1824 1825 //------------------------------------------------------------------------------ 1826 rtl::OUString ODatabaseDocument::getImplementationName_static( ) throw(RuntimeException) 1827 { 1828 return rtl::OUString::createFromAscii("com.sun.star.comp.dba.ODatabaseDocument"); 1829 } 1830 1831 //------------------------------------------------------------------------------ 1832 Sequence< ::rtl::OUString > ODatabaseDocument::getSupportedServiceNames( ) throw (RuntimeException) 1833 { 1834 return getSupportedServiceNames_static(); 1835 } 1836 1837 //------------------------------------------------------------------------------ 1838 Reference< XInterface > ODatabaseDocument::Create( const Reference< XComponentContext >& _rxContext ) 1839 { 1840 ::comphelper::ComponentContext aContext( _rxContext ); 1841 Reference< XUnoTunnel > xDBContextTunnel( aContext.createComponent( (::rtl::OUString)SERVICE_SDB_DATABASECONTEXT ), UNO_QUERY_THROW ); 1842 ODatabaseContext* pContext = reinterpret_cast< ODatabaseContext* >( xDBContextTunnel->getSomething( ODatabaseContext::getUnoTunnelImplementationId() ) ); 1843 1844 ::rtl::Reference<ODatabaseModelImpl> pImpl( new ODatabaseModelImpl( aContext.getLegacyServiceFactory(), *pContext ) ); 1845 Reference< XModel > xModel( pImpl->createNewModel_deliverOwnership( false ) ); 1846 return xModel.get(); 1847 } 1848 1849 //------------------------------------------------------------------------------ 1850 Sequence< ::rtl::OUString > ODatabaseDocument::getSupportedServiceNames_static( ) throw (RuntimeException) 1851 { 1852 Sequence< ::rtl::OUString > aSNS( 2 ); 1853 aSNS[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.OfficeDatabaseDocument")); 1854 aSNS[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.OfficeDocument")); 1855 return aSNS; 1856 } 1857 1858 //------------------------------------------------------------------------------ 1859 sal_Bool ODatabaseDocument::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) 1860 { 1861 return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; 1862 } 1863 // ----------------------------------------------------------------------------- 1864 Reference< XDataSource > SAL_CALL ODatabaseDocument::getDataSource() throw (RuntimeException) 1865 { 1866 DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); 1867 return m_pImpl->getOrCreateDataSource(); 1868 } 1869 1870 // ----------------------------------------------------------------------------- 1871 void SAL_CALL ODatabaseDocument::loadFromStorage( const Reference< XStorage >& /*xStorage*/, const Sequence< PropertyValue >& /*aMediaDescriptor*/ ) throw (IllegalArgumentException, DoubleInitializationException, IOException, Exception, RuntimeException) 1872 { 1873 DocumentGuard aGuard( *this ); 1874 1875 throw Exception( 1876 DBACORE_RESSTRING( RID_STR_NO_EMBEDDING ), 1877 *this 1878 ); 1879 } 1880 1881 // ----------------------------------------------------------------------------- 1882 void SAL_CALL ODatabaseDocument::storeToStorage( const Reference< XStorage >& _rxStorage, const Sequence< PropertyValue >& _rMediaDescriptor ) throw (IllegalArgumentException, IOException, Exception, RuntimeException) 1883 { 1884 DocumentGuard aGuard( *this ); 1885 impl_storeToStorage_throw( _rxStorage, _rMediaDescriptor, aGuard ); 1886 } 1887 1888 // ----------------------------------------------------------------------------- 1889 void SAL_CALL ODatabaseDocument::switchToStorage( const Reference< XStorage >& _rxNewRootStorage ) throw (IllegalArgumentException, IOException, Exception, RuntimeException) 1890 { 1891 DocumentGuard aGuard( *this ); 1892 1893 Reference< XStorage > xNewRootStorage( m_pImpl->switchToStorage( _rxNewRootStorage ) ); 1894 1895 aGuard.clear(); 1896 impl_notifyStorageChange_nolck_nothrow( xNewRootStorage ); 1897 } 1898 1899 // ----------------------------------------------------------------------------- 1900 Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentStorage( ) throw (IOException, Exception, RuntimeException) 1901 { 1902 DocumentGuard aGuard( *this ); 1903 return m_pImpl->getOrCreateRootStorage(); 1904 } 1905 1906 // ----------------------------------------------------------------------------- 1907 void SAL_CALL ODatabaseDocument::addStorageChangeListener( const Reference< XStorageChangeListener >& _Listener ) throw (RuntimeException) 1908 { 1909 DocumentGuard aGuard( *this ); 1910 m_aStorageListeners.addInterface( _Listener ); 1911 } 1912 1913 // ----------------------------------------------------------------------------- 1914 void SAL_CALL ODatabaseDocument::removeStorageChangeListener( const Reference< XStorageChangeListener >& _Listener ) throw (RuntimeException) 1915 { 1916 DocumentGuard aGuard( *this ); 1917 m_aStorageListeners.addInterface( _Listener ); 1918 } 1919 1920 // ----------------------------------------------------------------------------- 1921 Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getBasicLibraries() throw (RuntimeException) 1922 { 1923 DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); 1924 return m_pImpl->getLibraryContainer( true ); 1925 } 1926 1927 // ----------------------------------------------------------------------------- 1928 Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getDialogLibraries() throw (RuntimeException) 1929 { 1930 DocumentGuard aGuard( *this ); 1931 return m_pImpl->getLibraryContainer( false ); 1932 } 1933 1934 // ----------------------------------------------------------------------------- 1935 ::sal_Bool SAL_CALL ODatabaseDocument::getAllowMacroExecution() throw (RuntimeException) 1936 { 1937 DocumentGuard aGuard( *this ); 1938 return m_pImpl->adjustMacroMode_AutoReject(); 1939 } 1940 1941 // ----------------------------------------------------------------------------- 1942 Reference< XEmbeddedScripts > SAL_CALL ODatabaseDocument::getScriptContainer() throw (RuntimeException) 1943 { 1944 DocumentGuard aGuard( *this ); 1945 return this; 1946 } 1947 1948 // ----------------------------------------------------------------------------- 1949 Reference< provider::XScriptProvider > SAL_CALL ODatabaseDocument::getScriptProvider( ) throw (RuntimeException) 1950 { 1951 DocumentGuard aGuard( *this ); 1952 1953 Reference< XScriptProvider > xScriptProvider( m_xScriptProvider ); 1954 if ( !xScriptProvider.is() ) 1955 { 1956 Reference < XScriptProviderFactory > xFactory( 1957 m_pImpl->m_aContext.getSingleton( "com.sun.star.script.provider.theMasterScriptProviderFactory" ), UNO_QUERY_THROW ); 1958 1959 Any aScriptProviderContext; 1960 if ( m_bAllowDocumentScripting ) 1961 aScriptProviderContext <<= Reference< XModel >( this ); 1962 1963 xScriptProvider.set( xFactory->createScriptProvider( aScriptProviderContext ), UNO_SET_THROW ); 1964 m_xScriptProvider = xScriptProvider; 1965 } 1966 1967 return xScriptProvider; 1968 } 1969 1970 // ----------------------------------------------------------------------------- 1971 Reference< XNameReplace > SAL_CALL ODatabaseDocument::getEvents( ) throw (RuntimeException) 1972 { 1973 DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); 1974 return m_pEventContainer; 1975 } 1976 1977 // ----------------------------------------------------------------------------- 1978 void SAL_CALL ODatabaseDocument::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException) 1979 { 1980 if ( m_pImpl.is() ) 1981 m_pImpl->disposing(Source); 1982 } 1983 1984 //------------------------------------------------------------------ 1985 Reference< XInterface > ODatabaseDocument::getThis() const 1986 { 1987 return *const_cast< ODatabaseDocument* >( this ); 1988 } 1989 // ----------------------------------------------------------------------------- 1990 struct CreateAny : public ::std::unary_function< Reference<XController>, Any> 1991 { 1992 Any operator() (const Reference<XController>& lhs) const 1993 { 1994 return makeAny(lhs); 1995 } 1996 }; 1997 1998 // XModel2 1999 Reference< XEnumeration > SAL_CALL ODatabaseDocument::getControllers( ) throw (RuntimeException) 2000 { 2001 DocumentGuard aGuard( *this ); 2002 uno::Sequence< Any> aController( m_aControllers.size() ); 2003 ::std::transform( m_aControllers.begin(), m_aControllers.end(), aController.getArray(), CreateAny() ); 2004 return new ::comphelper::OAnyEnumeration(aController); 2005 } 2006 // ----------------------------------------------------------------------------- 2007 Sequence< ::rtl::OUString > SAL_CALL ODatabaseDocument::getAvailableViewControllerNames( ) throw (RuntimeException) 2008 { 2009 Sequence< ::rtl::OUString > aNames(1); 2010 aNames[0] = SERVICE_SDB_APPLICATIONCONTROLLER; 2011 return aNames; 2012 } 2013 // ----------------------------------------------------------------------------- 2014 Reference< XController2 > SAL_CALL ODatabaseDocument::createDefaultViewController( const Reference< XFrame >& _Frame ) throw (IllegalArgumentException, Exception, RuntimeException) 2015 { 2016 return createViewController( 2017 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Default" ) ), 2018 Sequence< PropertyValue >(), 2019 _Frame 2020 ); 2021 } 2022 2023 // ----------------------------------------------------------------------------- 2024 Reference< XController2 > SAL_CALL ODatabaseDocument::createViewController( const ::rtl::OUString& _ViewName, const Sequence< PropertyValue >& _Arguments, const Reference< XFrame >& _Frame ) throw (IllegalArgumentException, Exception, RuntimeException) 2025 { 2026 if ( !_ViewName.equalsAscii( "Default" ) && !_ViewName.equalsAscii( "Preview" ) ) 2027 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 2028 if ( !_Frame.is() ) 2029 throw IllegalArgumentException( ::rtl::OUString(), *this, 3 ); 2030 2031 DocumentGuard aGuard( *this ); 2032 ::comphelper::ComponentContext aContext( m_pImpl->m_aContext ); 2033 aGuard.clear(); 2034 2035 Reference< XController2 > xController; 2036 aContext.createComponent( "org.openoffice.comp.dbu.OApplicationController", xController ); 2037 2038 ::comphelper::NamedValueCollection aInitArgs( _Arguments ); 2039 aInitArgs.put( "Frame", _Frame ); 2040 if ( _ViewName.equalsAscii( "Preview" ) ) 2041 aInitArgs.put( "Preview", sal_Bool( sal_True ) ); 2042 Reference< XInitialization > xInitController( xController, UNO_QUERY_THROW ); 2043 xInitController->initialize( aInitArgs.getWrappedPropertyValues() ); 2044 2045 return xController; 2046 } 2047 2048 // ----------------------------------------------------------------------------- 2049 //============================================================================= 2050 Reference< XTitle > ODatabaseDocument::impl_getTitleHelper_throw() 2051 { 2052 if ( ! m_xTitleHelper.is ()) 2053 { 2054 Reference< XUntitledNumbers > xDesktop( 2055 m_pImpl->m_aContext.createComponent( "com.sun.star.frame.Desktop" ), 2056 UNO_QUERY_THROW ); 2057 uno::Reference< frame::XModel > xThis (getThis(), uno::UNO_QUERY_THROW); 2058 2059 ::framework::TitleHelper* pHelper = new ::framework::TitleHelper(m_pImpl->m_aContext.getLegacyServiceFactory()); 2060 m_xTitleHelper.set(static_cast< ::cppu::OWeakObject* >(pHelper), uno::UNO_QUERY_THROW); 2061 pHelper->setOwner (xThis ); 2062 pHelper->connectWithUntitledNumbers (xDesktop); 2063 } 2064 2065 return m_xTitleHelper; 2066 } 2067 2068 //============================================================================= 2069 uno::Reference< frame::XUntitledNumbers > ODatabaseDocument::impl_getUntitledHelper_throw(const uno::Reference< uno::XInterface >& _xComponent) 2070 { 2071 if ( !m_xModuleManager.is() ) 2072 m_xModuleManager.set( m_pImpl->m_aContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW ); 2073 2074 ::rtl::OUString sModuleId; 2075 try 2076 { 2077 sModuleId = m_xModuleManager->identify( _xComponent ); 2078 } 2079 catch(uno::Exception) 2080 { 2081 // ni 2082 } 2083 uno::Reference< frame::XUntitledNumbers > xNumberedControllers; 2084 2085 TNumberedController::iterator aFind = m_aNumberedControllers.find(sModuleId); 2086 if ( aFind == m_aNumberedControllers.end() ) 2087 { 2088 uno::Reference< frame::XModel > xThis(static_cast< frame::XModel* >(this), uno::UNO_QUERY_THROW); 2089 ::comphelper::NumberedCollection* pHelper = new ::comphelper::NumberedCollection(); 2090 xNumberedControllers.set(static_cast< ::cppu::OWeakObject* >(pHelper), uno::UNO_QUERY_THROW); 2091 2092 pHelper->setOwner (xThis); 2093 //pHelper->setUntitledPrefix (::rtl::OUString::createFromAscii(" : ")); 2094 2095 m_aNumberedControllers.insert(TNumberedController::value_type(sModuleId,xNumberedControllers)); 2096 } 2097 else 2098 xNumberedControllers = aFind->second; 2099 2100 return xNumberedControllers; 2101 } 2102 2103 //============================================================================= 2104 // css.frame.XTitle 2105 ::rtl::OUString SAL_CALL ODatabaseDocument::getTitle() 2106 throw (uno::RuntimeException) 2107 { 2108 // SYNCHRONIZED -> 2109 DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); 2110 return impl_getTitleHelper_throw()->getTitle(); 2111 } 2112 2113 //============================================================================= 2114 // css.frame.XTitle 2115 void SAL_CALL ODatabaseDocument::setTitle( const ::rtl::OUString& sTitle ) 2116 throw (uno::RuntimeException) 2117 { 2118 // SYNCHRONIZED -> 2119 DocumentGuard aGuard( *this ); 2120 impl_getTitleHelper_throw()->setTitle( sTitle ); 2121 m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" ); 2122 // <- SYNCHRONIZED 2123 } 2124 2125 //============================================================================= 2126 // css.frame.XTitleChangeBroadcaster 2127 void SAL_CALL ODatabaseDocument::addTitleChangeListener( const uno::Reference< frame::XTitleChangeListener >& xListener ) 2128 throw (uno::RuntimeException) 2129 { 2130 // SYNCHRONIZED -> 2131 DocumentGuard aGuard( *this ); 2132 2133 uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW ); 2134 xBroadcaster->addTitleChangeListener( xListener ); 2135 } 2136 2137 //============================================================================= 2138 // css.frame.XTitleChangeBroadcaster 2139 void SAL_CALL ODatabaseDocument::removeTitleChangeListener( const uno::Reference< frame::XTitleChangeListener >& xListener ) 2140 throw (uno::RuntimeException) 2141 { 2142 // SYNCHRONIZED -> 2143 DocumentGuard aGuard( *this ); 2144 2145 uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW ); 2146 xBroadcaster->removeTitleChangeListener( xListener ); 2147 } 2148 2149 //============================================================================= 2150 // css.frame.XUntitledNumbers 2151 ::sal_Int32 SAL_CALL ODatabaseDocument::leaseNumber( const uno::Reference< uno::XInterface >& xComponent ) 2152 throw (lang::IllegalArgumentException, 2153 uno::RuntimeException ) 2154 { 2155 DocumentGuard aGuard( *this ); 2156 return impl_getUntitledHelper_throw(xComponent)->leaseNumber (xComponent); 2157 } 2158 2159 //============================================================================= 2160 // css.frame.XUntitledNumbers 2161 void SAL_CALL ODatabaseDocument::releaseNumber( ::sal_Int32 nNumber ) 2162 throw (lang::IllegalArgumentException, 2163 uno::RuntimeException ) 2164 { 2165 DocumentGuard aGuard( *this ); 2166 impl_getUntitledHelper_throw()->releaseNumber (nNumber); 2167 } 2168 2169 //============================================================================= 2170 // css.frame.XUntitledNumbers 2171 void SAL_CALL ODatabaseDocument::releaseNumberForComponent( const uno::Reference< uno::XInterface >& xComponent ) 2172 throw (lang::IllegalArgumentException, 2173 uno::RuntimeException ) 2174 { 2175 DocumentGuard aGuard( *this ); 2176 impl_getUntitledHelper_throw(xComponent)->releaseNumberForComponent (xComponent); 2177 } 2178 2179 //============================================================================= 2180 // css.frame.XUntitledNumbers 2181 ::rtl::OUString SAL_CALL ODatabaseDocument::getUntitledPrefix() throw (uno::RuntimeException) 2182 { 2183 return ::rtl::OUString();/*RTL_CONSTASCII_USTRINGPARAM(" : "));*/ 2184 } 2185 2186 //------------------------------------------------------------------ 2187 //........................................................................ 2188 } // namespace dbaccess 2189 //........................................................................ 2190 2191 2192