1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_embeddedobj.hxx" 26 27 #include <commonembobj.hxx> 28 #include <com/sun/star/embed/Aspects.hpp> 29 #include <com/sun/star/document/XStorageBasedDocument.hpp> 30 #include <com/sun/star/embed/EmbedStates.hpp> 31 #include <com/sun/star/embed/EmbedVerbs.hpp> 32 #include <com/sun/star/embed/EntryInitModes.hpp> 33 #include <com/sun/star/embed/XStorage.hpp> 34 #include <com/sun/star/embed/XOptimizedStorage.hpp> 35 #include <com/sun/star/embed/ElementModes.hpp> 36 #include <com/sun/star/embed/EmbedUpdateModes.hpp> 37 #include <com/sun/star/frame/XModel.hpp> 38 #include <com/sun/star/frame/XStorable.hpp> 39 #include <com/sun/star/frame/XLoadable.hpp> 40 #include <com/sun/star/frame/XComponentLoader.hpp> 41 #include <com/sun/star/frame/XModule.hpp> 42 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 43 #include <com/sun/star/lang/XSingleServiceFactory.hpp> 44 #include <com/sun/star/lang/DisposedException.hpp> 45 #include <com/sun/star/util/XModifiable.hpp> 46 47 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCEESS_HPP_ 48 #include <com/sun/star/container/XNameAccess.hpp> 49 #endif 50 #include <com/sun/star/container/XChild.hpp> 51 #include <com/sun/star/util/XCloseable.hpp> 52 #include <com/sun/star/beans/XPropertySet.hpp> 53 #include <com/sun/star/beans/IllegalTypeException.hpp> 54 #include <com/sun/star/chart2/XChartDocument.hpp> 55 56 #include <comphelper/fileformat.h> 57 #include <comphelper/storagehelper.hxx> 58 #include <comphelper/mimeconfighelper.hxx> 59 #include <comphelper/namedvaluecollection.hxx> 60 61 #include <rtl/logfile.hxx> 62 63 #include <tools/diagnose_ex.h> 64 65 #define USE_STORAGEBASED_DOCUMENT 66 67 using namespace ::com::sun::star; 68 69 70 //------------------------------------------------------ 71 uno::Sequence< beans::PropertyValue > GetValuableArgs_Impl( const uno::Sequence< beans::PropertyValue >& aMedDescr, 72 sal_Bool bCanUseDocumentBaseURL ) 73 { 74 uno::Sequence< beans::PropertyValue > aResult; 75 sal_Int32 nResLen = 0; 76 77 for ( sal_Int32 nInd = 0; nInd < aMedDescr.getLength(); nInd++ ) 78 { 79 if ( aMedDescr[nInd].Name.equalsAscii( "ComponentData" ) 80 || aMedDescr[nInd].Name.equalsAscii( "DocumentTitle" ) 81 || aMedDescr[nInd].Name.equalsAscii( "InteractionHandler" ) 82 || aMedDescr[nInd].Name.equalsAscii( "JumpMark" ) 83 // || aMedDescr[nInd].Name.equalsAscii( "Password" ) makes no sense for embedded objects 84 || aMedDescr[nInd].Name.equalsAscii( "Preview" ) 85 || aMedDescr[nInd].Name.equalsAscii( "ReadOnly" ) 86 || aMedDescr[nInd].Name.equalsAscii( "StartPresentation" ) 87 || aMedDescr[nInd].Name.equalsAscii( "RepairPackage" ) 88 || aMedDescr[nInd].Name.equalsAscii( "StatusIndicator" ) 89 || aMedDescr[nInd].Name.equalsAscii( "ViewData" ) 90 || aMedDescr[nInd].Name.equalsAscii( "ViewId" ) 91 || aMedDescr[nInd].Name.equalsAscii( "MacroExecutionMode" ) 92 || aMedDescr[nInd].Name.equalsAscii( "UpdateDocMode" ) 93 || (aMedDescr[nInd].Name.equalsAscii( "DocumentBaseURL" ) && bCanUseDocumentBaseURL) ) 94 { 95 aResult.realloc( ++nResLen ); 96 aResult[nResLen-1] = aMedDescr[nInd]; 97 } 98 } 99 100 return aResult; 101 } 102 103 //------------------------------------------------------ 104 uno::Sequence< beans::PropertyValue > addAsTemplate( const uno::Sequence< beans::PropertyValue >& aOrig ) 105 { 106 sal_Bool bAsTemplateSet = sal_False; 107 sal_Int32 nLength = aOrig.getLength(); 108 uno::Sequence< beans::PropertyValue > aResult( nLength ); 109 110 for ( sal_Int32 nInd = 0; nInd < nLength; nInd++ ) 111 { 112 aResult[nInd].Name = aOrig[nInd].Name; 113 if ( aResult[nInd].Name.equalsAscii( "AsTemplate" ) ) 114 { 115 aResult[nInd].Value <<= sal_True; 116 bAsTemplateSet = sal_True; 117 } 118 else 119 aResult[nInd].Value = aOrig[nInd].Value; 120 } 121 122 if ( !bAsTemplateSet ) 123 { 124 aResult.realloc( nLength + 1 ); 125 aResult[nLength].Name = ::rtl::OUString::createFromAscii( "AsTemplate" ); 126 aResult[nLength].Value <<= sal_True; 127 } 128 129 return aResult; 130 } 131 132 //------------------------------------------------------ 133 uno::Reference< io::XInputStream > createTempInpStreamFromStor( 134 const uno::Reference< embed::XStorage >& xStorage, 135 const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 136 { 137 OSL_ENSURE( xStorage.is(), "The storage can not be empty!" ); 138 139 uno::Reference< io::XInputStream > xResult; 140 141 const ::rtl::OUString aServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) ); 142 uno::Reference < io::XStream > xTempStream = uno::Reference < io::XStream > ( 143 xFactory->createInstance ( aServiceName ), 144 uno::UNO_QUERY ); 145 if ( xTempStream.is() ) 146 { 147 uno::Reference < lang::XSingleServiceFactory > xStorageFactory( 148 xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.embed.StorageFactory" ) ), 149 uno::UNO_QUERY ); 150 151 uno::Sequence< uno::Any > aArgs( 2 ); 152 aArgs[0] <<= xTempStream; 153 aArgs[1] <<= embed::ElementModes::READWRITE; 154 uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArgs ), 155 uno::UNO_QUERY ); 156 if ( !xTempStorage.is() ) 157 throw uno::RuntimeException(); // TODO: 158 159 try 160 { 161 xStorage->copyToStorage( xTempStorage ); 162 } catch( uno::Exception& e ) 163 { 164 throw embed::StorageWrappedTargetException( 165 ::rtl::OUString::createFromAscii( "Can't copy storage!" ), 166 uno::Reference< uno::XInterface >(), 167 uno::makeAny( e ) ); 168 } 169 170 try { 171 uno::Reference< lang::XComponent > xComponent( xTempStorage, uno::UNO_QUERY ); 172 OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" ); 173 if ( xComponent.is() ) 174 xComponent->dispose(); 175 } 176 catch ( uno::Exception& ) 177 { 178 } 179 180 try { 181 uno::Reference< io::XOutputStream > xTempOut = xTempStream->getOutputStream(); 182 if ( xTempOut.is() ) 183 xTempOut->closeOutput(); 184 } 185 catch ( uno::Exception& ) 186 { 187 } 188 189 xResult = xTempStream->getInputStream(); 190 } 191 192 return xResult; 193 194 } 195 196 //------------------------------------------------------ 197 static void TransferMediaType( const uno::Reference< embed::XStorage >& i_rSource, const uno::Reference< embed::XStorage >& i_rTarget ) 198 { 199 try 200 { 201 const uno::Reference< beans::XPropertySet > xSourceProps( i_rSource, uno::UNO_QUERY_THROW ); 202 const uno::Reference< beans::XPropertySet > xTargetProps( i_rTarget, uno::UNO_QUERY_THROW ); 203 const ::rtl::OUString sMediaTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ); 204 xTargetProps->setPropertyValue( sMediaTypePropName, xSourceProps->getPropertyValue( sMediaTypePropName ) ); 205 } 206 catch( const uno::Exception& ) 207 { 208 DBG_UNHANDLED_EXCEPTION(); 209 } 210 } 211 212 //------------------------------------------------------ 213 static uno::Reference< util::XCloseable > CreateDocument( const uno::Reference< lang::XMultiServiceFactory >& _rxFactory, 214 const ::rtl::OUString& _rDocumentServiceName, bool _bEmbeddedScriptSupport, const bool i_bDocumentRecoverySupport ) 215 { 216 ::comphelper::NamedValueCollection aArguments; 217 aArguments.put( "EmbeddedObject", (sal_Bool)sal_True ); 218 aArguments.put( "EmbeddedScriptSupport", (sal_Bool)_bEmbeddedScriptSupport ); 219 aArguments.put( "DocumentRecoverySupport", (sal_Bool)i_bDocumentRecoverySupport ); 220 221 uno::Reference< uno::XInterface > xDocument; 222 try 223 { 224 xDocument = _rxFactory->createInstanceWithArguments( _rDocumentServiceName, aArguments.getWrappedPropertyValues() ); 225 } 226 catch( const uno::Exception& ) 227 { 228 // if an embedded object implementation does not support XInitialization, 229 // the default factory from cppuhelper will throw an 230 // IllegalArgumentException when we try to create the instance with arguments. 231 // Okay, so we fall back to creating the instance without any arguments. 232 OSL_ASSERT("Consider implementing interface XInitialization to avoid duplicate construction"); 233 xDocument = _rxFactory->createInstance( _rDocumentServiceName ); 234 } 235 236 return uno::Reference< util::XCloseable >( xDocument, uno::UNO_QUERY ); 237 } 238 239 //------------------------------------------------------ 240 static void SetDocToEmbedded( const uno::Reference< frame::XModel > xDocument, const ::rtl::OUString& aModuleName ) 241 { 242 if ( xDocument.is() ) 243 { 244 uno::Sequence< beans::PropertyValue > aSeq( 1 ); 245 aSeq[0].Name = ::rtl::OUString::createFromAscii( "SetEmbedded" ); 246 aSeq[0].Value <<= sal_True; 247 xDocument->attachResource( ::rtl::OUString(), aSeq ); 248 249 if ( aModuleName.getLength() ) 250 { 251 try 252 { 253 uno::Reference< frame::XModule > xModule( xDocument, uno::UNO_QUERY_THROW ); 254 xModule->setIdentifier( aModuleName ); 255 } 256 catch( uno::Exception& ) 257 {} 258 } 259 } 260 } 261 262 //------------------------------------------------------ 263 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage, 264 const uno::Reference< embed::XStorage >& xNewObjectStorage, 265 const ::rtl::OUString& aNewName ) 266 { 267 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) ) 268 { 269 OSL_ENSURE( xNewObjectStorage == m_xObjectStorage, "The storage must be the same!\n" ); 270 return; 271 } 272 273 uno::Reference< lang::XComponent > xComponent( m_xObjectStorage, uno::UNO_QUERY ); 274 OSL_ENSURE( !m_xObjectStorage.is() || xComponent.is(), "Wrong storage implementation!" ); 275 276 m_xObjectStorage = xNewObjectStorage; 277 m_xParentStorage = xNewParentStorage; 278 m_aEntryName = aNewName; 279 280 #ifdef USE_STORAGEBASED_DOCUMENT 281 // the linked document should not be switched 282 if ( !m_bIsLink ) 283 { 284 uno::Reference< document::XStorageBasedDocument > xDoc( m_pDocHolder->GetComponent(), uno::UNO_QUERY ); 285 if ( xDoc.is() ) 286 SwitchDocToStorage_Impl( xDoc, m_xObjectStorage ); 287 } 288 #endif 289 290 try { 291 if ( xComponent.is() ) 292 xComponent->dispose(); 293 } 294 catch ( uno::Exception& ) 295 { 296 } 297 } 298 299 //------------------------------------------------------ 300 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage, 301 const ::rtl::OUString& aNewName ) 302 { 303 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) ) 304 return; 305 306 sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE; 307 308 uno::Reference< embed::XStorage > xNewOwnStorage = xNewParentStorage->openStorageElement( aNewName, nStorageMode ); 309 OSL_ENSURE( xNewOwnStorage.is(), "The method can not return empty reference!" ); 310 311 SwitchOwnPersistence( xNewParentStorage, xNewOwnStorage, aNewName ); 312 } 313 314 //------------------------------------------------------ 315 void OCommonEmbeddedObject::EmbedAndReparentDoc_Impl( const uno::Reference< util::XCloseable >& i_rxDocument ) const 316 { 317 SetDocToEmbedded( uno::Reference< frame::XModel >( i_rxDocument, uno::UNO_QUERY ), m_aModuleName ); 318 319 try 320 { 321 uno::Reference < container::XChild > xChild( i_rxDocument, uno::UNO_QUERY ); 322 if ( xChild.is() ) 323 xChild->setParent( m_xParent ); 324 } 325 catch( const lang::NoSupportException & ) 326 { 327 OSL_ENSURE( false, "OCommonEmbeddedObject::EmbedAndReparentDoc: cannot set parent at document!" ); 328 } 329 } 330 331 //------------------------------------------------------ 332 uno::Reference< util::XCloseable > OCommonEmbeddedObject::InitNewDocument_Impl() 333 { 334 uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(), 335 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) ); 336 337 uno::Reference< frame::XModel > xModel( xDocument, uno::UNO_QUERY ); 338 uno::Reference< frame::XLoadable > xLoadable( xModel, uno::UNO_QUERY ); 339 if ( !xLoadable.is() ) 340 throw uno::RuntimeException(); 341 342 try 343 { 344 // set the document mode to embedded as the first action on document!!! 345 EmbedAndReparentDoc_Impl( xDocument ); 346 347 // if we have a storage to recover the document from, do not use initNew, but instead load from that storage 348 bool bInitNew = true; 349 if ( m_xRecoveryStorage.is() ) 350 { 351 uno::Reference< document::XStorageBasedDocument > xDoc( xLoadable, uno::UNO_QUERY ); 352 OSL_ENSURE( xDoc.is(), "OCommonEmbeddedObject::InitNewDocument_Impl: cannot recover from a storage when the document is not storage based!" ); 353 if ( xDoc.is() ) 354 { 355 ::comphelper::NamedValueCollection aLoadArgs; 356 FillDefaultLoadArgs_Impl( m_xRecoveryStorage, aLoadArgs ); 357 358 xDoc->loadFromStorage( m_xRecoveryStorage, aLoadArgs.getPropertyValues() ); 359 SwitchDocToStorage_Impl( xDoc, m_xObjectStorage ); 360 bInitNew = false; 361 } 362 } 363 364 if ( bInitNew ) 365 { 366 // init document as a new 367 xLoadable->initNew(); 368 } 369 xModel->attachResource( xModel->getURL(), m_aDocMediaDescriptor ); 370 } 371 catch( uno::Exception& ) 372 { 373 uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY ); 374 if ( xCloseable.is() ) 375 { 376 try 377 { 378 xCloseable->close( sal_True ); 379 } 380 catch( uno::Exception& ) 381 { 382 } 383 } 384 385 throw; // TODO 386 } 387 388 return xDocument; 389 } 390 391 //------------------------------------------------------ 392 uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl() 393 { 394 uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(), 395 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) ); 396 397 uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY ); 398 if ( !xLoadable.is() ) 399 throw uno::RuntimeException(); 400 401 sal_Int32 nLen = 2; 402 uno::Sequence< beans::PropertyValue > aArgs( nLen ); 403 aArgs[0].Name = ::rtl::OUString::createFromAscii( "URL" ); 404 aArgs[0].Value <<= m_aLinkURL; 405 aArgs[1].Name = ::rtl::OUString::createFromAscii( "FilterName" ); 406 aArgs[1].Value <<= m_aLinkFilterName; 407 if ( m_bLinkHasPassword ) 408 { 409 aArgs.realloc( ++nLen ); 410 aArgs[nLen-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Password" ) ); 411 aArgs[nLen-1].Value <<= m_aLinkPassword; 412 } 413 414 aArgs.realloc( m_aDocMediaDescriptor.getLength() + nLen ); 415 for ( sal_Int32 nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ ) 416 { 417 aArgs[nInd+nLen].Name = m_aDocMediaDescriptor[nInd].Name; 418 aArgs[nInd+nLen].Value = m_aDocMediaDescriptor[nInd].Value; 419 } 420 421 try 422 { 423 // the document is not really an embedded one, it is a link 424 EmbedAndReparentDoc_Impl( xDocument ); 425 426 // load the document 427 xLoadable->load( aArgs ); 428 429 if ( !m_bLinkHasPassword ) 430 { 431 // check if there is a password to cache 432 uno::Reference< frame::XModel > xModel( xLoadable, uno::UNO_QUERY_THROW ); 433 uno::Sequence< beans::PropertyValue > aProps = xModel->getArgs(); 434 for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ ) 435 if ( aProps[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Password" ) ) ) 436 && ( aProps[nInd].Value >>= m_aLinkPassword ) ) 437 { 438 m_bLinkHasPassword = sal_True; 439 break; 440 } 441 } 442 } 443 catch( uno::Exception& ) 444 { 445 uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY ); 446 if ( xCloseable.is() ) 447 { 448 try 449 { 450 xCloseable->close( sal_True ); 451 } 452 catch( uno::Exception& ) 453 { 454 } 455 } 456 457 throw; // TODO 458 } 459 460 return xDocument; 461 462 } 463 464 //------------------------------------------------------ 465 ::rtl::OUString OCommonEmbeddedObject::GetFilterName( sal_Int32 nVersion ) const 466 { 467 ::rtl::OUString aFilterName = GetPresetFilterName(); 468 if ( !aFilterName.getLength() ) 469 { 470 try { 471 ::comphelper::MimeConfigurationHelper aHelper( m_xFactory ); 472 aFilterName = aHelper.GetDefaultFilterFromServiceName( GetDocumentServiceName(), nVersion ); 473 } catch( uno::Exception& ) 474 {} 475 } 476 477 return aFilterName; 478 } 479 480 //------------------------------------------------------ 481 void OCommonEmbeddedObject::FillDefaultLoadArgs_Impl( const uno::Reference< embed::XStorage >& i_rxStorage, 482 ::comphelper::NamedValueCollection& o_rLoadArgs ) const 483 { 484 o_rLoadArgs.put( "DocumentBaseURL", GetBaseURL_Impl() ); 485 o_rLoadArgs.put( "HierarchicalDocumentName", m_aEntryName ); 486 o_rLoadArgs.put( "ReadOnly", m_bReadOnly ); 487 488 ::rtl::OUString aFilterName = GetFilterName( ::comphelper::OStorageHelper::GetXStorageFormat( i_rxStorage ) ); 489 OSL_ENSURE( aFilterName.getLength(), "OCommonEmbeddedObject::FillDefaultLoadArgs_Impl: Wrong document service name!" ); 490 if ( !aFilterName.getLength() ) 491 throw io::IOException(); // TODO: error message/code 492 493 o_rLoadArgs.put( "FilterName", aFilterName ); 494 } 495 496 //------------------------------------------------------ 497 uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadDocumentFromStorage_Impl() 498 { 499 ENSURE_OR_THROW( m_xObjectStorage.is(), "no object storage" ); 500 501 const uno::Reference< embed::XStorage > xSourceStorage( m_xRecoveryStorage.is() ? m_xRecoveryStorage : m_xObjectStorage ); 502 503 uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(), 504 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) ); 505 506 //#i103460# ODF: take the size given from the parent frame as default 507 uno::Reference< chart2::XChartDocument > xChart( xDocument, uno::UNO_QUERY ); 508 if( xChart.is() ) 509 { 510 uno::Reference< embed::XVisualObject > xChartVisualObject( xChart, uno::UNO_QUERY ); 511 if( xChartVisualObject.is() ) 512 xChartVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, m_aDefaultSizeForChart_In_100TH_MM ); 513 } 514 515 uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY ); 516 uno::Reference< document::XStorageBasedDocument > xDoc 517 #ifdef USE_STORAGEBASED_DOCUMENT 518 ( xDocument, uno::UNO_QUERY ) 519 #endif 520 ; 521 if ( !xDoc.is() && !xLoadable.is() ) ///BUG: This should be || instead of && ? 522 throw uno::RuntimeException(); 523 524 ::comphelper::NamedValueCollection aLoadArgs; 525 FillDefaultLoadArgs_Impl( xSourceStorage, aLoadArgs ); 526 527 uno::Reference< io::XInputStream > xTempInpStream; 528 if ( !xDoc.is() ) 529 { 530 xTempInpStream = createTempInpStreamFromStor( xSourceStorage, m_xFactory ); 531 if ( !xTempInpStream.is() ) 532 throw uno::RuntimeException(); 533 534 ::rtl::OUString aTempFileURL; 535 try 536 { 537 // no need to let the file stay after the stream is removed since the embedded document 538 // can not be stored directly 539 uno::Reference< beans::XPropertySet > xTempStreamProps( xTempInpStream, uno::UNO_QUERY_THROW ); 540 xTempStreamProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ) >>= aTempFileURL; 541 } 542 catch( uno::Exception& ) 543 { 544 } 545 546 OSL_ENSURE( aTempFileURL.getLength(), "Couldn't retrieve temporary file URL!\n" ); 547 548 aLoadArgs.put( "URL", aTempFileURL ); 549 aLoadArgs.put( "InputStream", xTempInpStream ); 550 } 551 552 // aLoadArgs.put( "AsTemplate", sal_True ); 553 554 aLoadArgs.merge( m_aDocMediaDescriptor, true ); 555 556 try 557 { 558 // set the document mode to embedded as the first step!!! 559 EmbedAndReparentDoc_Impl( xDocument ); 560 561 if ( xDoc.is() ) 562 { 563 xDoc->loadFromStorage( xSourceStorage, aLoadArgs.getPropertyValues() ); 564 if ( xSourceStorage != m_xObjectStorage ) 565 SwitchDocToStorage_Impl( xDoc, m_xObjectStorage ); 566 } 567 else 568 xLoadable->load( aLoadArgs.getPropertyValues() ); 569 } 570 catch( uno::Exception& ) 571 { 572 uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY ); 573 if ( xCloseable.is() ) 574 { 575 try 576 { 577 xCloseable->close( sal_True ); 578 } 579 catch( uno::Exception& ) 580 { 581 DBG_UNHANDLED_EXCEPTION(); 582 } 583 } 584 585 throw; // TODO 586 } 587 588 return xDocument; 589 } 590 591 //------------------------------------------------------ 592 uno::Reference< io::XInputStream > OCommonEmbeddedObject::StoreDocumentToTempStream_Impl( 593 sal_Int32 nStorageFormat, 594 const ::rtl::OUString& aBaseURL, 595 const ::rtl::OUString& aHierarchName ) 596 { 597 uno::Reference < io::XOutputStream > xTempOut( 598 m_xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 599 uno::UNO_QUERY ); 600 uno::Reference< io::XInputStream > aResult( xTempOut, uno::UNO_QUERY ); 601 602 if ( !xTempOut.is() || !aResult.is() ) 603 throw uno::RuntimeException(); // TODO: 604 605 uno::Reference< frame::XStorable > xStorable; 606 { 607 osl::MutexGuard aGuard( m_aMutex ); 608 if ( m_pDocHolder ) 609 xStorable = uno::Reference< frame::XStorable > ( m_pDocHolder->GetComponent(), uno::UNO_QUERY ); 610 } 611 612 if( !xStorable.is() ) 613 throw uno::RuntimeException(); // TODO: 614 615 ::rtl::OUString aFilterName = GetFilterName( nStorageFormat ); 616 617 OSL_ENSURE( aFilterName.getLength(), "Wrong document service name!" ); 618 if ( !aFilterName.getLength() ) 619 throw io::IOException(); // TODO: 620 621 uno::Sequence< beans::PropertyValue > aArgs( 4 ); 622 aArgs[0].Name = ::rtl::OUString::createFromAscii( "FilterName" ); 623 aArgs[0].Value <<= aFilterName; 624 aArgs[1].Name = ::rtl::OUString::createFromAscii( "OutputStream" ); 625 aArgs[1].Value <<= xTempOut; 626 aArgs[2].Name = ::rtl::OUString::createFromAscii( "DocumentBaseURL" ); 627 aArgs[2].Value <<= aBaseURL; 628 aArgs[3].Name = ::rtl::OUString::createFromAscii( "HierarchicalDocumentName" ); 629 aArgs[3].Value <<= aHierarchName; 630 631 xStorable->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aArgs ); 632 try 633 { 634 xTempOut->closeOutput(); 635 } 636 catch( uno::Exception& ) 637 { 638 OSL_ENSURE( sal_False, "Looks like stream was closed already" ); 639 } 640 641 return aResult; 642 } 643 644 //------------------------------------------------------ 645 void OCommonEmbeddedObject::SaveObject_Impl() 646 { 647 if ( m_xClientSite.is() ) 648 { 649 try 650 { 651 // check whether the component is modified, 652 // if not there is no need for storing 653 uno::Reference< util::XModifiable > xModifiable( m_pDocHolder->GetComponent(), uno::UNO_QUERY ); 654 if ( xModifiable.is() && !xModifiable->isModified() ) 655 return; 656 } 657 catch( uno::Exception& ) 658 {} 659 660 try { 661 m_xClientSite->saveObject(); 662 } 663 catch( uno::Exception& ) 664 { 665 OSL_ENSURE( sal_False, "The object was not stored!\n" ); 666 } 667 } 668 } 669 670 //------------------------------------------------------ 671 ::rtl::OUString OCommonEmbeddedObject::GetBaseURL_Impl() const 672 { 673 ::rtl::OUString aBaseURL; 674 sal_Int32 nInd = 0; 675 676 if ( m_xClientSite.is() ) 677 { 678 try 679 { 680 uno::Reference< frame::XModel > xParentModel( m_xClientSite->getComponent(), uno::UNO_QUERY_THROW ); 681 uno::Sequence< beans::PropertyValue > aModelProps = xParentModel->getArgs(); 682 for ( nInd = 0; nInd < aModelProps.getLength(); nInd++ ) 683 if ( aModelProps[nInd].Name.equals( 684 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentBaseURL" ) ) ) ) 685 { 686 aModelProps[nInd].Value >>= aBaseURL; 687 break; 688 } 689 690 691 } 692 catch( uno::Exception& ) 693 {} 694 } 695 696 if ( !aBaseURL.getLength() ) 697 { 698 for ( nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ ) 699 if ( m_aDocMediaDescriptor[nInd].Name.equals( 700 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentBaseURL" ) ) ) ) 701 { 702 m_aDocMediaDescriptor[nInd].Value >>= aBaseURL; 703 break; 704 } 705 } 706 707 if ( !aBaseURL.getLength() ) 708 aBaseURL = m_aDefaultParentBaseURL; 709 710 return aBaseURL; 711 } 712 713 //------------------------------------------------------ 714 ::rtl::OUString OCommonEmbeddedObject::GetBaseURLFrom_Impl( 715 const uno::Sequence< beans::PropertyValue >& lArguments, 716 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 717 { 718 ::rtl::OUString aBaseURL; 719 sal_Int32 nInd = 0; 720 721 for ( nInd = 0; nInd < lArguments.getLength(); nInd++ ) 722 if ( lArguments[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentBaseURL" ) ) ) ) 723 { 724 lArguments[nInd].Value >>= aBaseURL; 725 break; 726 } 727 728 if ( !aBaseURL.getLength() ) 729 { 730 for ( nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) 731 if ( lObjArgs[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultParentBaseURL" ) ) ) ) 732 { 733 lObjArgs[nInd].Value >>= aBaseURL; 734 break; 735 } 736 } 737 738 return aBaseURL; 739 } 740 741 742 //------------------------------------------------------ 743 void OCommonEmbeddedObject::SwitchDocToStorage_Impl( const uno::Reference< document::XStorageBasedDocument >& xDoc, const uno::Reference< embed::XStorage >& xStorage ) 744 { 745 xDoc->switchToStorage( xStorage ); 746 747 uno::Reference< util::XModifiable > xModif( xDoc, uno::UNO_QUERY ); 748 if ( xModif.is() ) 749 xModif->setModified( sal_False ); 750 751 if ( m_xRecoveryStorage.is() ) 752 m_xRecoveryStorage.clear(); 753 } 754 755 //------------------------------------------------------ 756 void OCommonEmbeddedObject::StoreDocToStorage_Impl( const uno::Reference< embed::XStorage >& xStorage, 757 sal_Int32 nStorageFormat, 758 const ::rtl::OUString& aBaseURL, 759 const ::rtl::OUString& aHierarchName, 760 sal_Bool bAttachToTheStorage ) 761 { 762 OSL_ENSURE( xStorage.is(), "No storage is provided for storing!" ); 763 764 if ( !xStorage.is() ) 765 throw uno::RuntimeException(); // TODO: 766 767 #ifdef USE_STORAGEBASED_DOCUMENT 768 uno::Reference< document::XStorageBasedDocument > xDoc; 769 { 770 osl::MutexGuard aGuard( m_aMutex ); 771 if ( m_pDocHolder ) 772 xDoc = uno::Reference< document::XStorageBasedDocument >( m_pDocHolder->GetComponent(), uno::UNO_QUERY ); 773 } 774 775 if ( xDoc.is() ) 776 { 777 ::rtl::OUString aFilterName = GetFilterName( nStorageFormat ); 778 779 OSL_ENSURE( aFilterName.getLength(), "Wrong document service name!" ); 780 if ( !aFilterName.getLength() ) 781 throw io::IOException(); // TODO: 782 783 uno::Sequence< beans::PropertyValue > aArgs( 3 ); 784 aArgs[0].Name = ::rtl::OUString::createFromAscii( "FilterName" ); 785 aArgs[0].Value <<= aFilterName; 786 aArgs[2].Name = ::rtl::OUString::createFromAscii( "DocumentBaseURL" ); 787 aArgs[2].Value <<= aBaseURL; 788 aArgs[1].Name = ::rtl::OUString::createFromAscii( "HierarchicalDocumentName" ); 789 aArgs[1].Value <<= aHierarchName; 790 791 xDoc->storeToStorage( xStorage, aArgs ); 792 if ( bAttachToTheStorage ) 793 SwitchDocToStorage_Impl( xDoc, xStorage ); 794 } 795 else 796 #endif 797 { 798 // store document to temporary stream based on temporary file 799 uno::Reference < io::XInputStream > xTempIn = StoreDocumentToTempStream_Impl( nStorageFormat, aBaseURL, aHierarchName ); 800 801 OSL_ENSURE( xTempIn.is(), "The stream reference can not be empty!\n" ); 802 803 // open storage based on document temporary file for reading 804 uno::Reference < lang::XSingleServiceFactory > xStorageFactory( 805 m_xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.embed.StorageFactory" ) ), 806 uno::UNO_QUERY ); 807 808 uno::Sequence< uno::Any > aArgs(1); 809 aArgs[0] <<= xTempIn; 810 uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArgs ), 811 uno::UNO_QUERY ); 812 if ( !xTempStorage.is() ) 813 throw uno::RuntimeException(); // TODO: 814 815 // object storage must be committed automatically 816 xTempStorage->copyToStorage( xStorage ); 817 } 818 } 819 820 //------------------------------------------------------ 821 uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateDocFromMediaDescr_Impl( 822 const uno::Sequence< beans::PropertyValue >& aMedDescr ) 823 { 824 uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(), 825 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) ); 826 827 uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY ); 828 if ( !xLoadable.is() ) 829 throw uno::RuntimeException(); 830 831 try 832 { 833 // set the document mode to embedded as the first action on the document!!! 834 EmbedAndReparentDoc_Impl( xDocument ); 835 836 xLoadable->load( addAsTemplate( aMedDescr ) ); 837 } 838 catch( uno::Exception& ) 839 { 840 uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY ); 841 if ( xCloseable.is() ) 842 { 843 try 844 { 845 xCloseable->close( sal_True ); 846 } 847 catch( uno::Exception& ) 848 { 849 } 850 } 851 852 throw; // TODO 853 } 854 855 return xDocument; 856 } 857 858 //------------------------------------------------------ 859 uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateTempDocFromLink_Impl() 860 { 861 uno::Reference< util::XCloseable > xResult; 862 863 OSL_ENSURE( m_bIsLink, "The object is not a linked one!\n" ); 864 865 uno::Sequence< beans::PropertyValue > aTempMediaDescr; 866 867 sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT; 868 try { 869 nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage ); 870 } 871 catch ( beans::IllegalTypeException& ) 872 { 873 // the container just has an unknown type, use current file format 874 } 875 catch ( uno::Exception& ) 876 { 877 OSL_ENSURE( sal_False, "Can not retrieve storage media type!\n" ); 878 } 879 880 if ( m_pDocHolder->GetComponent().is() ) 881 { 882 aTempMediaDescr.realloc( 4 ); 883 884 // TODO/LATER: may be private:stream should be used as target URL 885 ::rtl::OUString aTempFileURL; 886 uno::Reference< io::XInputStream > xTempStream = StoreDocumentToTempStream_Impl( SOFFICE_FILEFORMAT_CURRENT, 887 ::rtl::OUString(), 888 ::rtl::OUString() ); 889 try 890 { 891 // no need to let the file stay after the stream is removed since the embedded document 892 // can not be stored directly 893 uno::Reference< beans::XPropertySet > xTempStreamProps( xTempStream, uno::UNO_QUERY_THROW ); 894 xTempStreamProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ) >>= aTempFileURL; 895 } 896 catch( uno::Exception& ) 897 { 898 } 899 900 OSL_ENSURE( aTempFileURL.getLength(), "Couldn't retrieve temporary file URL!\n" ); 901 902 aTempMediaDescr[0].Name = ::rtl::OUString::createFromAscii( "URL" ); 903 aTempMediaDescr[0].Value <<= aTempFileURL; 904 aTempMediaDescr[1].Name = ::rtl::OUString::createFromAscii( "InputStream" ); 905 aTempMediaDescr[1].Value <<= xTempStream; 906 aTempMediaDescr[2].Name = ::rtl::OUString::createFromAscii( "FilterName" ); 907 aTempMediaDescr[2].Value <<= GetFilterName( nStorageFormat ); 908 aTempMediaDescr[3].Name = ::rtl::OUString::createFromAscii( "AsTemplate" ); 909 aTempMediaDescr[3].Value <<= sal_True; 910 } 911 else 912 { 913 aTempMediaDescr.realloc( 2 ); 914 aTempMediaDescr[0].Name = ::rtl::OUString::createFromAscii( "URL" ); 915 aTempMediaDescr[0].Value <<= m_aLinkURL; 916 aTempMediaDescr[1].Name = ::rtl::OUString::createFromAscii( "FilterName" ); 917 aTempMediaDescr[1].Value <<= m_aLinkFilterName; 918 // aTempMediaDescr[2].Name = ::rtl::OUString::createFromAscii( "AsTemplate" ); 919 // aTempMediaDescr[2].Value <<= sal_True; 920 } 921 922 xResult = CreateDocFromMediaDescr_Impl( aTempMediaDescr ); 923 924 return xResult; 925 } 926 927 //------------------------------------------------------ 928 void SAL_CALL OCommonEmbeddedObject::setPersistentEntry( 929 const uno::Reference< embed::XStorage >& xStorage, 930 const ::rtl::OUString& sEntName, 931 sal_Int32 nEntryConnectionMode, 932 const uno::Sequence< beans::PropertyValue >& lArguments, 933 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 934 { 935 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::setPersistentEntry" ); 936 937 // the type of the object must be already set 938 // a kind of typedetection should be done in the factory 939 940 ::osl::MutexGuard aGuard( m_aMutex ); 941 if ( m_bDisposed ) 942 throw lang::DisposedException(); // TODO 943 944 if ( !xStorage.is() ) 945 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 946 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 947 1 ); 948 949 if ( !sEntName.getLength() ) 950 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 951 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 952 2 ); 953 954 // May be LOADED should be forbidden here ??? 955 if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) 956 && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) ) 957 { 958 // if the object is not loaded 959 // it can not get persistent representation without initialization 960 961 // if the object is loaded 962 // it can switch persistent representation only without initialization 963 964 throw embed::WrongStateException( 965 ::rtl::OUString::createFromAscii( "Can't change persistent representation of activated object!\n" ), 966 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 967 } 968 969 if ( m_bWaitSaveCompleted ) 970 { 971 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) 972 { 973 // saveCompleted is expected, handle it accordingly 974 if ( m_xNewParentStorage == xStorage && m_aNewEntryName.equals( sEntName ) ) 975 { 976 saveCompleted( sal_True ); 977 return; 978 } 979 980 // if a completely different entry is provided, switch first back to the old persistence in saveCompleted 981 // and then switch to the target persistence 982 sal_Bool bSwitchFurther = ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ); 983 saveCompleted( sal_False ); 984 if ( !bSwitchFurther ) 985 return; 986 } 987 else 988 throw embed::WrongStateException( 989 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 990 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 991 } 992 993 // for now support of this interface is required to allow breaking of links and converting them to normal embedded 994 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) 995 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" ); 996 if ( m_bIsLink ) 997 { 998 m_aEntryName = sEntName; 999 return; 1000 } 1001 1002 uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY ); 1003 if ( !xNameAccess.is() ) 1004 throw uno::RuntimeException(); //TODO 1005 1006 // detect entry existence 1007 sal_Bool bElExists = xNameAccess->hasByName( sEntName ); 1008 1009 m_aDocMediaDescriptor = GetValuableArgs_Impl( lArguments, 1010 nEntryConnectionMode != embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT ); 1011 1012 m_bReadOnly = sal_False; 1013 for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ ) 1014 if ( lArguments[nInd].Name.equalsAscii( "ReadOnly" ) ) 1015 lArguments[nInd].Value >>= m_bReadOnly; 1016 1017 // TODO: use lObjArgs for StoreVisualReplacement 1018 for ( sal_Int32 nObjInd = 0; nObjInd < lObjArgs.getLength(); nObjInd++ ) 1019 if ( lObjArgs[nObjInd].Name.equalsAscii( "OutplaceDispatchInterceptor" ) ) 1020 { 1021 uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor; 1022 if ( lObjArgs[nObjInd].Value >>= xDispatchInterceptor ) 1023 m_pDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor ); 1024 } 1025 else if ( lObjArgs[nObjInd].Name.equalsAscii( "DefaultParentBaseURL" ) ) 1026 { 1027 lObjArgs[nObjInd].Value >>= m_aDefaultParentBaseURL; 1028 } 1029 else if ( lObjArgs[nObjInd].Name.equalsAscii( "Parent" ) ) 1030 { 1031 lObjArgs[nObjInd].Value >>= m_xParent; 1032 } 1033 else if ( lObjArgs[nObjInd].Name.equalsAscii( "IndividualMiscStatus" ) ) 1034 { 1035 sal_Int64 nMiscStatus=0; 1036 lObjArgs[nObjInd].Value >>= nMiscStatus; 1037 m_nMiscStatus |= nMiscStatus; 1038 } 1039 else if ( lObjArgs[nObjInd].Name.equalsAscii( "CloneFrom" ) ) 1040 { 1041 uno::Reference < embed::XEmbeddedObject > xObj; 1042 lObjArgs[nObjInd].Value >>= xObj; 1043 if ( xObj.is() ) 1044 { 1045 m_bHasClonedSize = sal_True; 1046 m_aClonedSize = xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); 1047 m_nClonedMapUnit = xObj->getMapUnit( embed::Aspects::MSOLE_CONTENT ); 1048 } 1049 } 1050 else if ( lObjArgs[nObjInd].Name.equalsAscii( "OutplaceFrameProperties" ) ) 1051 { 1052 uno::Sequence< uno::Any > aOutFrameProps; 1053 uno::Sequence< beans::NamedValue > aOutFramePropsTyped; 1054 if ( lObjArgs[nObjInd].Value >>= aOutFrameProps ) 1055 { 1056 m_pDocHolder->SetOutplaceFrameProperties( aOutFrameProps ); 1057 } 1058 else if ( lObjArgs[nObjInd].Value >>= aOutFramePropsTyped ) 1059 { 1060 aOutFrameProps.realloc( aOutFramePropsTyped.getLength() ); 1061 uno::Any* pProp = aOutFrameProps.getArray(); 1062 for ( const beans::NamedValue* pTypedProp = aOutFramePropsTyped.getConstArray(); 1063 pTypedProp != aOutFramePropsTyped.getConstArray() + aOutFramePropsTyped.getLength(); 1064 ++pTypedProp, ++pProp 1065 ) 1066 { 1067 *pProp <<= *pTypedProp; 1068 } 1069 m_pDocHolder->SetOutplaceFrameProperties( aOutFrameProps ); 1070 } 1071 else 1072 OSL_ENSURE( false, "OCommonEmbeddedObject::setPersistentEntry: illegal type for argument 'OutplaceFrameProperties'!" ); 1073 } 1074 else if ( lObjArgs[nObjInd].Name.equalsAscii( "ModuleName" ) ) 1075 { 1076 lObjArgs[nObjInd].Value >>= m_aModuleName; 1077 } 1078 else if ( lObjArgs[nObjInd].Name.equalsAscii( "EmbeddedScriptSupport" ) ) 1079 { 1080 OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_bEmbeddedScriptSupport ); 1081 } 1082 else if ( lObjArgs[nObjInd].Name.equalsAscii( "DocumentRecoverySupport" ) ) 1083 { 1084 OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_bDocumentRecoverySupport ); 1085 } 1086 else if ( lObjArgs[nObjInd].Name.equalsAscii( "RecoveryStorage" ) ) 1087 { 1088 OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_xRecoveryStorage ); 1089 } 1090 1091 1092 sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE; 1093 1094 SwitchOwnPersistence( xStorage, sEntName ); 1095 1096 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT ) 1097 { 1098 if ( bElExists ) 1099 { 1100 // the initialization from existing storage allows to leave object in loaded state 1101 m_nObjectState = embed::EmbedStates::LOADED; 1102 } 1103 else 1104 { 1105 m_pDocHolder->SetComponent( InitNewDocument_Impl(), m_bReadOnly ); 1106 if ( !m_pDocHolder->GetComponent().is() ) 1107 throw io::IOException(); // TODO: can not create document 1108 1109 m_nObjectState = embed::EmbedStates::RUNNING; 1110 } 1111 } 1112 else 1113 { 1114 if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE ) 1115 throw io::IOException(); 1116 1117 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) 1118 { 1119 // the document just already changed its storage to store to 1120 // the links to OOo documents for now ignore this call 1121 // TODO: OOo links will have persistence so it will be switched here 1122 } 1123 else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT ) 1124 { 1125 if ( m_xRecoveryStorage.is() ) 1126 TransferMediaType( m_xRecoveryStorage, m_xObjectStorage ); 1127 1128 // TODO: 1129 m_pDocHolder->SetComponent( InitNewDocument_Impl(), m_bReadOnly ); 1130 1131 if ( !m_pDocHolder->GetComponent().is() ) 1132 throw io::IOException(); // TODO: can not create document 1133 1134 m_nObjectState = embed::EmbedStates::RUNNING; 1135 } 1136 else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT ) 1137 { 1138 m_pDocHolder->SetComponent( CreateDocFromMediaDescr_Impl( lArguments ), m_bReadOnly ); 1139 m_nObjectState = embed::EmbedStates::RUNNING; 1140 } 1141 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT ) 1142 //{ 1143 //TODO: 1144 //} 1145 else 1146 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong connection mode is provided!\n" ), 1147 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 1148 3 ); 1149 } 1150 } 1151 1152 //------------------------------------------------------ 1153 void SAL_CALL OCommonEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage, 1154 const ::rtl::OUString& sEntName, 1155 const uno::Sequence< beans::PropertyValue >& lArguments, 1156 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 1157 { 1158 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::storeToEntry" ); 1159 1160 ::osl::ResettableMutexGuard aGuard( m_aMutex ); 1161 if ( m_bDisposed ) 1162 throw lang::DisposedException(); // TODO 1163 1164 if ( m_nObjectState == -1 ) 1165 { 1166 // the object is still not loaded 1167 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), 1168 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1169 } 1170 1171 if ( m_bWaitSaveCompleted ) 1172 throw embed::WrongStateException( 1173 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1174 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1175 1176 // for now support of this interface is required to allow breaking of links and converting them to normal embedded 1177 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) 1178 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" ); 1179 if ( m_bIsLink ) 1180 return; 1181 1182 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" ); 1183 1184 sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT; 1185 sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT; 1186 try { 1187 nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage ); 1188 } 1189 catch ( beans::IllegalTypeException& ) 1190 { 1191 // the container just has an unknown type, use current file format 1192 } 1193 catch ( uno::Exception& ) 1194 { 1195 OSL_ENSURE( sal_False, "Can not retrieve target storage media type!\n" ); 1196 } 1197 1198 try 1199 { 1200 nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage ); 1201 } 1202 catch ( beans::IllegalTypeException& ) 1203 { 1204 // the container just has an unknown type, use current file format 1205 } 1206 catch ( uno::Exception& ) 1207 { 1208 OSL_ENSURE( sal_False, "Can not retrieve own storage media type!\n" ); 1209 } 1210 1211 sal_Bool bTryOptimization = sal_False; 1212 for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) 1213 { 1214 // StoreVisualReplacement and VisualReplacement args have no sense here 1215 if ( lObjArgs[nInd].Name.equalsAscii( "CanTryOptimization" ) ) 1216 lObjArgs[nInd].Value >>= bTryOptimization; 1217 } 1218 1219 sal_Bool bSwitchBackToLoaded = sal_False; 1220 1221 // Storing to different format can be done only in running state. 1222 if ( m_nObjectState == embed::EmbedStates::LOADED ) 1223 { 1224 // TODO/LATER: copying is not legal for documents with relative links. 1225 if ( nTargetStorageFormat == nOriginalStorageFormat ) 1226 { 1227 sal_Bool bOptimizationWorks = sal_False; 1228 if ( bTryOptimization ) 1229 { 1230 try 1231 { 1232 // try to use optimized copying 1233 uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW ); 1234 uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW ); 1235 xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName ); 1236 bOptimizationWorks = sal_True; 1237 } 1238 catch( uno::Exception& ) 1239 { 1240 } 1241 } 1242 1243 if ( !bOptimizationWorks ) 1244 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName ); 1245 } 1246 else 1247 { 1248 changeState( embed::EmbedStates::RUNNING ); 1249 bSwitchBackToLoaded = sal_True; 1250 } 1251 } 1252 1253 if ( m_nObjectState != embed::EmbedStates::LOADED ) 1254 { 1255 uno::Reference< embed::XStorage > xSubStorage = 1256 xStorage->openStorageElement( sEntName, embed::ElementModes::READWRITE ); 1257 1258 if ( !xSubStorage.is() ) 1259 throw uno::RuntimeException(); //TODO 1260 1261 aGuard.clear(); 1262 // TODO/LATER: support hierarchical name for embedded objects in embedded objects 1263 StoreDocToStorage_Impl( xSubStorage, nTargetStorageFormat, GetBaseURLFrom_Impl( lArguments, lObjArgs ), sEntName, sal_False ); 1264 aGuard.reset(); 1265 1266 if ( bSwitchBackToLoaded ) 1267 changeState( embed::EmbedStates::LOADED ); 1268 } 1269 1270 // TODO: should the listener notification be done? 1271 } 1272 1273 //------------------------------------------------------ 1274 void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage, 1275 const ::rtl::OUString& sEntName, 1276 const uno::Sequence< beans::PropertyValue >& lArguments, 1277 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 1278 { 1279 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::storeAsEntry" ); 1280 1281 // TODO: use lObjArgs 1282 1283 ::osl::ResettableMutexGuard aGuard( m_aMutex ); 1284 if ( m_bDisposed ) 1285 throw lang::DisposedException(); // TODO 1286 1287 if ( m_nObjectState == -1 ) 1288 { 1289 // the object is still not loaded 1290 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), 1291 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1292 } 1293 1294 if ( m_bWaitSaveCompleted ) 1295 throw embed::WrongStateException( 1296 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1297 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1298 1299 // for now support of this interface is required to allow breaking of links and converting them to normal embedded 1300 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) 1301 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" ); 1302 if ( m_bIsLink ) 1303 { 1304 m_aNewEntryName = sEntName; 1305 return; 1306 } 1307 1308 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" ); 1309 1310 sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT; 1311 sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT; 1312 try { 1313 nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage ); 1314 } 1315 catch ( beans::IllegalTypeException& ) 1316 { 1317 // the container just has an unknown type, use current file format 1318 } 1319 catch ( uno::Exception& ) 1320 { 1321 OSL_ENSURE( sal_False, "Can not retrieve target storage media type!\n" ); 1322 } 1323 1324 try 1325 { 1326 nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage ); 1327 } 1328 catch ( beans::IllegalTypeException& ) 1329 { 1330 // the container just has an unknown type, use current file format 1331 } 1332 catch ( uno::Exception& ) 1333 { 1334 OSL_ENSURE( sal_False, "Can not retrieve own storage media type!\n" ); 1335 } 1336 1337 PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSaveAs" ) ); 1338 1339 sal_Bool bTryOptimization = sal_False; 1340 for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) 1341 { 1342 // StoreVisualReplacement and VisualReplacement args have no sense here 1343 if ( lObjArgs[nInd].Name.equalsAscii( "CanTryOptimization" ) ) 1344 lObjArgs[nInd].Value >>= bTryOptimization; 1345 } 1346 1347 sal_Bool bSwitchBackToLoaded = sal_False; 1348 1349 // Storing to different format can be done only in running state. 1350 if ( m_nObjectState == embed::EmbedStates::LOADED ) 1351 { 1352 // TODO/LATER: copying is not legal for documents with relative links. 1353 if ( nTargetStorageFormat == nOriginalStorageFormat ) 1354 { 1355 sal_Bool bOptimizationWorks = sal_False; 1356 if ( bTryOptimization ) 1357 { 1358 try 1359 { 1360 // try to use optimized copying 1361 uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW ); 1362 uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW ); 1363 xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName ); 1364 bOptimizationWorks = sal_True; 1365 } 1366 catch( uno::Exception& ) 1367 { 1368 } 1369 } 1370 1371 if ( !bOptimizationWorks ) 1372 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName ); 1373 } 1374 else 1375 { 1376 changeState( embed::EmbedStates::RUNNING ); 1377 bSwitchBackToLoaded = sal_True; 1378 } 1379 } 1380 1381 uno::Reference< embed::XStorage > xSubStorage = 1382 xStorage->openStorageElement( sEntName, embed::ElementModes::READWRITE ); 1383 1384 if ( !xSubStorage.is() ) 1385 throw uno::RuntimeException(); //TODO 1386 1387 if ( m_nObjectState != embed::EmbedStates::LOADED ) 1388 { 1389 aGuard.clear(); 1390 // TODO/LATER: support hierarchical name for embedded objects in embedded objects 1391 StoreDocToStorage_Impl( xSubStorage, nTargetStorageFormat, GetBaseURLFrom_Impl( lArguments, lObjArgs ), sEntName, sal_False ); 1392 aGuard.reset(); 1393 1394 if ( bSwitchBackToLoaded ) 1395 changeState( embed::EmbedStates::LOADED ); 1396 } 1397 1398 m_bWaitSaveCompleted = sal_True; 1399 m_xNewObjectStorage = xSubStorage; 1400 m_xNewParentStorage = xStorage; 1401 m_aNewEntryName = sEntName; 1402 m_aNewDocMediaDescriptor = GetValuableArgs_Impl( lArguments, sal_True ); 1403 1404 // TODO: register listeners for storages above, in case thay are disposed 1405 // an exception will be thrown on saveCompleted( true ) 1406 1407 // TODO: should the listener notification be done here or in saveCompleted? 1408 } 1409 1410 //------------------------------------------------------ 1411 void SAL_CALL OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew ) 1412 { 1413 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::saveCompleted" ); 1414 1415 ::osl::MutexGuard aGuard( m_aMutex ); 1416 if ( m_bDisposed ) 1417 throw lang::DisposedException(); // TODO 1418 1419 if ( m_nObjectState == -1 ) 1420 { 1421 // the object is still not loaded 1422 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), 1423 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1424 } 1425 1426 // for now support of this interface is required to allow breaking of links and converting them to normal embedded 1427 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) 1428 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" ); 1429 if ( m_bIsLink ) 1430 { 1431 if ( bUseNew ) 1432 m_aEntryName = m_aNewEntryName; 1433 m_aNewEntryName = ::rtl::OUString(); 1434 return; 1435 } 1436 1437 // it is allowed to call saveCompleted( false ) for nonstored objects 1438 if ( !m_bWaitSaveCompleted && !bUseNew ) 1439 return; 1440 1441 OSL_ENSURE( m_bWaitSaveCompleted, "Unexpected saveCompleted() call!\n" ); 1442 if ( !m_bWaitSaveCompleted ) 1443 throw io::IOException(); // TODO: illegal call 1444 1445 OSL_ENSURE( m_xNewObjectStorage.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" ); 1446 if ( !m_xNewObjectStorage.is() || !m_xNewParentStorage.is() ) 1447 throw uno::RuntimeException(); // TODO: broken internal information 1448 1449 if ( bUseNew ) 1450 { 1451 SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStorage, m_aNewEntryName ); 1452 m_aDocMediaDescriptor = m_aNewDocMediaDescriptor; 1453 1454 uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY ); 1455 if ( xModif.is() ) 1456 xModif->setModified( sal_False ); 1457 1458 PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSaveAsDone" ) ); 1459 } 1460 else 1461 { 1462 try { 1463 uno::Reference< lang::XComponent > xComponent( m_xNewObjectStorage, uno::UNO_QUERY ); 1464 OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" ); 1465 if ( xComponent.is() ) 1466 xComponent->dispose(); 1467 } 1468 catch ( uno::Exception& ) 1469 { 1470 } 1471 } 1472 1473 m_xNewObjectStorage = uno::Reference< embed::XStorage >(); 1474 m_xNewParentStorage = uno::Reference< embed::XStorage >(); 1475 m_aNewEntryName = ::rtl::OUString(); 1476 m_aNewDocMediaDescriptor.realloc( 0 ); 1477 m_bWaitSaveCompleted = sal_False; 1478 1479 if ( bUseNew ) 1480 { 1481 // TODO: notify listeners 1482 1483 if ( m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE ) 1484 { 1485 // TODO: update visual representation 1486 } 1487 } 1488 } 1489 1490 //------------------------------------------------------ 1491 sal_Bool SAL_CALL OCommonEmbeddedObject::hasEntry() 1492 { 1493 ::osl::MutexGuard aGuard( m_aMutex ); 1494 if ( m_bDisposed ) 1495 throw lang::DisposedException(); // TODO 1496 1497 if ( m_bWaitSaveCompleted ) 1498 throw embed::WrongStateException( 1499 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1500 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1501 1502 if ( m_xObjectStorage.is() ) 1503 return sal_True; 1504 1505 return sal_False; 1506 } 1507 1508 //------------------------------------------------------ 1509 ::rtl::OUString SAL_CALL OCommonEmbeddedObject::getEntryName() 1510 { 1511 ::osl::MutexGuard aGuard( m_aMutex ); 1512 if ( m_bDisposed ) 1513 throw lang::DisposedException(); // TODO 1514 1515 if ( m_nObjectState == -1 ) 1516 { 1517 // the object is still not loaded 1518 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ), 1519 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1520 } 1521 1522 if ( m_bWaitSaveCompleted ) 1523 throw embed::WrongStateException( 1524 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1525 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1526 1527 return m_aEntryName; 1528 } 1529 1530 //------------------------------------------------------ 1531 void SAL_CALL OCommonEmbeddedObject::storeOwn() 1532 { 1533 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::storeOwn" ); 1534 1535 // during switching from Activated to Running and from Running to Loaded states the object will 1536 // ask container to store the object, the container has to make decision 1537 // to do so or not 1538 1539 ::osl::ResettableMutexGuard aGuard( m_aMutex ); 1540 if ( m_bDisposed ) 1541 throw lang::DisposedException(); // TODO 1542 1543 if ( m_nObjectState == -1 ) 1544 { 1545 // the object is still not loaded 1546 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), 1547 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1548 } 1549 1550 if ( m_bWaitSaveCompleted ) 1551 throw embed::WrongStateException( 1552 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1553 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1554 1555 if ( m_bReadOnly ) 1556 throw io::IOException(); // TODO: access denied 1557 1558 // nothing to do, if the object is in loaded state 1559 if ( m_nObjectState == embed::EmbedStates::LOADED ) 1560 return; 1561 1562 PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSave" ) ); 1563 1564 OSL_ENSURE( m_pDocHolder->GetComponent().is(), "If an object is activated or in running state it must have a document!\n" ); 1565 if ( !m_pDocHolder->GetComponent().is() ) 1566 throw uno::RuntimeException(); 1567 1568 if ( m_bIsLink ) 1569 { 1570 // TODO: just store the document to it's location 1571 uno::Reference< frame::XStorable > xStorable( m_pDocHolder->GetComponent(), uno::UNO_QUERY ); 1572 if ( !xStorable.is() ) 1573 throw uno::RuntimeException(); // TODO 1574 1575 // free the main mutex for the storing time 1576 aGuard.clear(); 1577 1578 xStorable->store(); 1579 1580 aGuard.reset(); 1581 } 1582 else 1583 { 1584 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" ); 1585 1586 if ( !m_xObjectStorage.is() ) 1587 throw io::IOException(); //TODO: access denied 1588 1589 sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT; 1590 try { 1591 nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage ); 1592 } 1593 catch ( beans::IllegalTypeException& ) 1594 { 1595 // the container just has an unknown type, use current file format 1596 } 1597 catch ( uno::Exception& ) 1598 { 1599 OSL_ENSURE( sal_False, "Can not retrieve storage media type!\n" ); 1600 } 1601 1602 aGuard.clear(); 1603 StoreDocToStorage_Impl( m_xObjectStorage, nStorageFormat, GetBaseURL_Impl(), m_aEntryName, sal_True ); 1604 aGuard.reset(); 1605 } 1606 1607 uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY ); 1608 if ( xModif.is() ) 1609 xModif->setModified( sal_False ); 1610 1611 PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSaveDone" ) ); 1612 } 1613 1614 //------------------------------------------------------ 1615 sal_Bool SAL_CALL OCommonEmbeddedObject::isReadonly() 1616 { 1617 ::osl::MutexGuard aGuard( m_aMutex ); 1618 if ( m_bDisposed ) 1619 throw lang::DisposedException(); // TODO 1620 1621 if ( m_nObjectState == -1 ) 1622 { 1623 // the object is still not loaded 1624 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ), 1625 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1626 } 1627 1628 if ( m_bWaitSaveCompleted ) 1629 throw embed::WrongStateException( 1630 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1631 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1632 1633 return m_bReadOnly; 1634 } 1635 1636 //------------------------------------------------------ 1637 void SAL_CALL OCommonEmbeddedObject::reload( 1638 const uno::Sequence< beans::PropertyValue >& lArguments, 1639 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 1640 { 1641 // TODO: use lObjArgs 1642 // for now this method is used only to switch readonly state 1643 1644 ::osl::MutexGuard aGuard( m_aMutex ); 1645 if ( m_bDisposed ) 1646 throw lang::DisposedException(); // TODO 1647 1648 if ( m_nObjectState == -1 ) 1649 { 1650 // the object is still not loaded 1651 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ), 1652 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1653 } 1654 1655 if ( m_nObjectState != embed::EmbedStates::LOADED ) 1656 { 1657 // the object is still not loaded 1658 throw embed::WrongStateException( 1659 ::rtl::OUString::createFromAscii( "The object must be in loaded state to be reloaded!\n" ), 1660 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1661 } 1662 1663 if ( m_bWaitSaveCompleted ) 1664 throw embed::WrongStateException( 1665 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1666 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1667 1668 if ( m_bIsLink ) 1669 { 1670 // reload of the link 1671 ::rtl::OUString aOldLinkFilter = m_aLinkFilterName; 1672 1673 ::rtl::OUString aNewLinkFilter; 1674 for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ ) 1675 { 1676 if ( lArguments[nInd].Name.equalsAscii( "URL" ) ) 1677 { 1678 // the new URL 1679 lArguments[nInd].Value >>= m_aLinkURL; 1680 m_aLinkFilterName = ::rtl::OUString(); 1681 } 1682 else if ( lArguments[nInd].Name.equalsAscii( "FilterName" ) ) 1683 { 1684 lArguments[nInd].Value >>= aNewLinkFilter; 1685 m_aLinkFilterName = ::rtl::OUString(); 1686 } 1687 } 1688 1689 ::comphelper::MimeConfigurationHelper aHelper( m_xFactory ); 1690 if ( !m_aLinkFilterName.getLength() ) 1691 { 1692 if ( aNewLinkFilter.getLength() ) 1693 m_aLinkFilterName = aNewLinkFilter; 1694 else 1695 { 1696 uno::Sequence< beans::PropertyValue > aArgs( 1 ); 1697 aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); 1698 aArgs[0].Value <<= m_aLinkURL; 1699 m_aLinkFilterName = aHelper.UpdateMediaDescriptorWithFilterName( aArgs, sal_False ); 1700 } 1701 } 1702 1703 if ( !aOldLinkFilter.equals( m_aLinkFilterName ) ) 1704 { 1705 uno::Sequence< beans::NamedValue > aObject = aHelper.GetObjectPropsByFilter( m_aLinkFilterName ); 1706 1707 // TODO/LATER: probably the document holder could be cleaned explicitly as in the destructor 1708 m_pDocHolder->release(); 1709 m_pDocHolder = NULL; 1710 1711 LinkInit_Impl( aObject, lArguments, lObjArgs ); 1712 } 1713 } 1714 1715 m_aDocMediaDescriptor = GetValuableArgs_Impl( lArguments, sal_True ); 1716 1717 // TODO: use lObjArgs for StoreVisualReplacement 1718 for ( sal_Int32 nObjInd = 0; nObjInd < lObjArgs.getLength(); nObjInd++ ) 1719 if ( lObjArgs[nObjInd].Name.equalsAscii( "OutplaceDispatchInterceptor" ) ) 1720 { 1721 uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor; 1722 if ( lObjArgs[nObjInd].Value >>= xDispatchInterceptor ) 1723 m_pDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor ); 1724 1725 break; 1726 } 1727 1728 // TODO: 1729 // when document allows reloading through API the object can be reloaded not only in loaded state 1730 1731 sal_Bool bOldReadOnlyValue = m_bReadOnly; 1732 1733 m_bReadOnly = sal_False; 1734 for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ ) 1735 if ( lArguments[nInd].Name.equalsAscii( "ReadOnly" ) ) 1736 lArguments[nInd].Value >>= m_bReadOnly; 1737 1738 if ( bOldReadOnlyValue != m_bReadOnly && !m_bIsLink ) 1739 { 1740 // close own storage 1741 try { 1742 uno::Reference< lang::XComponent > xComponent( m_xObjectStorage, uno::UNO_QUERY ); 1743 OSL_ENSURE( !m_xObjectStorage.is() || xComponent.is(), "Wrong storage implementation!" ); 1744 if ( xComponent.is() ) 1745 xComponent->dispose(); 1746 } 1747 catch ( uno::Exception& ) 1748 { 1749 } 1750 1751 sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE; 1752 m_xObjectStorage = m_xParentStorage->openStorageElement( m_aEntryName, nStorageMode ); 1753 } 1754 } 1755 1756 //------------------------------------------------------ 1757 void SAL_CALL OCommonEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage, 1758 const ::rtl::OUString& sEntName ) 1759 { 1760 ::osl::ResettableMutexGuard aGuard( m_aMutex ); 1761 if ( m_bDisposed ) 1762 throw lang::DisposedException(); // TODO 1763 1764 if ( !m_bIsLink ) 1765 { 1766 // it must be a linked initialized object 1767 throw embed::WrongStateException( 1768 ::rtl::OUString::createFromAscii( "The object is not a valid linked object!\n" ), 1769 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1770 } 1771 #if 0 1772 else 1773 { 1774 // the current implementation of OOo links does not implement this method since it does not implement 1775 // all the set of interfaces required for OOo embedded object ( XEmbedPersist is not supported ). 1776 throw io::IOException(); // TODO: 1777 } 1778 #endif 1779 1780 if ( !xStorage.is() ) 1781 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 1782 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 1783 1 ); 1784 1785 if ( !sEntName.getLength() ) 1786 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 1787 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 1788 2 ); 1789 1790 if ( !m_bIsLink || m_nObjectState == -1 ) 1791 { 1792 // it must be a linked initialized object 1793 throw embed::WrongStateException( 1794 ::rtl::OUString::createFromAscii( "The object is not a valid linked object!\n" ), 1795 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1796 } 1797 1798 if ( m_bWaitSaveCompleted ) 1799 throw embed::WrongStateException( 1800 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1801 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1802 1803 uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY ); 1804 if ( !xNameAccess.is() ) 1805 throw uno::RuntimeException(); //TODO 1806 1807 // detect entry existence 1808 /*sal_Bool bElExists =*/ xNameAccess->hasByName( sEntName ); 1809 1810 m_bReadOnly = sal_False; 1811 // sal_Int32 nStorageMode = embed::ElementModes::READWRITE; 1812 1813 if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) 1814 SwitchOwnPersistence( xStorage, sEntName ); 1815 1816 // for linked object it means that it becomes embedded object 1817 // the document must switch it's persistence also 1818 1819 // TODO/LATER: handle the case when temp doc can not be created 1820 // the document is a new embedded object so it must be marked as modified 1821 uno::Reference< util::XCloseable > xDocument = CreateTempDocFromLink_Impl(); 1822 uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY ); 1823 if ( !xModif.is() ) 1824 throw uno::RuntimeException(); 1825 try 1826 { 1827 xModif->setModified( sal_True ); 1828 } 1829 catch( uno::Exception& ) 1830 {} 1831 1832 m_pDocHolder->SetComponent( xDocument, m_bReadOnly ); 1833 OSL_ENSURE( m_pDocHolder->GetComponent().is(), "If document can't be created, an exception must be thrown!\n" ); 1834 1835 if ( m_nObjectState == embed::EmbedStates::LOADED ) 1836 { 1837 // the state is changed and can not be switched to loaded state back without saving 1838 m_nObjectState = embed::EmbedStates::RUNNING; 1839 StateChangeNotification_Impl( sal_False, embed::EmbedStates::LOADED, m_nObjectState, aGuard ); 1840 } 1841 else if ( m_nObjectState == embed::EmbedStates::ACTIVE ) 1842 m_pDocHolder->Show(); 1843 1844 m_bIsLink = sal_False; 1845 m_aLinkFilterName = ::rtl::OUString(); 1846 m_aLinkURL = ::rtl::OUString(); 1847 } 1848 1849 //------------------------------------------------------ 1850 sal_Bool SAL_CALL OCommonEmbeddedObject::isLink() 1851 { 1852 ::osl::MutexGuard aGuard( m_aMutex ); 1853 if ( m_bDisposed ) 1854 throw lang::DisposedException(); // TODO 1855 1856 // Actually this information is clear even in case object is wayting for saveCompleted 1857 // if ( m_bWaitSaveCompleted ) 1858 // throw embed::WrongStateException( 1859 // ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1860 // uno::Reference< uno::XInterface >( reinterpret_cast< ::cppu::OWeakObject* >(this) ) ); 1861 1862 return m_bIsLink; 1863 } 1864 1865 //------------------------------------------------------ 1866 ::rtl::OUString SAL_CALL OCommonEmbeddedObject::getLinkURL() 1867 { 1868 ::osl::MutexGuard aGuard( m_aMutex ); 1869 if ( m_bDisposed ) 1870 throw lang::DisposedException(); // TODO 1871 1872 // Actually this information is clear even in case object is wayting for saveCompleted 1873 // if ( m_bWaitSaveCompleted ) 1874 // throw embed::WrongStateException( 1875 // ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1876 // uno::Reference< uno::XInterface >( reinterpret_cast< ::cppu::OWeakObject* >(this) ) ); 1877 1878 if ( !m_bIsLink ) 1879 throw embed::WrongStateException( 1880 ::rtl::OUString::createFromAscii( "The object is not a link object!\n" ), 1881 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1882 1883 return m_aLinkURL; 1884 } 1885