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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_comphelper.hxx" 24 #include <com/sun/star/container/XChild.hpp> 25 #include <com/sun/star/container/XNameAccess.hpp> 26 #include <com/sun/star/embed/XEmbedObjectCreator.hpp> 27 #include <com/sun/star/embed/XLinkCreator.hpp> 28 #include <com/sun/star/embed/XEmbedPersist.hpp> 29 #include <com/sun/star/embed/XLinkageSupport.hpp> 30 #include <com/sun/star/embed/XTransactedObject.hpp> 31 #include <com/sun/star/embed/XOptimizedStorage.hpp> 32 #include <com/sun/star/embed/EntryInitModes.hpp> 33 #include <com/sun/star/util/XCloseable.hpp> 34 #include <com/sun/star/util/XModifiable.hpp> 35 #include <com/sun/star/embed/EmbedStates.hpp> 36 #include <com/sun/star/datatransfer/XTransferable.hpp> 37 #include <com/sun/star/beans/XPropertySetInfo.hpp> 38 #include <com/sun/star/beans/XPropertySet.hpp> 39 #include <com/sun/star/embed/Aspects.hpp> 40 #include <com/sun/star/embed/EmbedMisc.hpp> 41 42 #include <comphelper/seqstream.hxx> 43 #include <comphelper/processfactory.hxx> 44 #include <comphelper/storagehelper.hxx> 45 #include <comphelper/embeddedobjectcontainer.hxx> 46 #include <comphelper/sequence.hxx> 47 #include <cppuhelper/weakref.hxx> 48 #include <hash_map> 49 #include <algorithm> 50 51 #include <rtl/logfile.hxx> 52 53 using namespace ::com::sun::star; 54 55 namespace comphelper 56 { 57 58 struct hashObjectName_Impl 59 { 60 size_t operator()(const ::rtl::OUString Str) const 61 { 62 return (size_t)Str.hashCode(); 63 } 64 }; 65 66 struct eqObjectName_Impl 67 { 68 sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const 69 { 70 return ( Str1 == Str2 ); 71 } 72 }; 73 74 typedef std::hash_map 75 < 76 ::rtl::OUString, 77 ::com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >, 78 hashObjectName_Impl, 79 eqObjectName_Impl 80 > 81 EmbeddedObjectContainerNameMap; 82 83 struct EmbedImpl 84 { 85 // TODO/LATER: remove objects from temp. Container storage when object is disposed 86 EmbeddedObjectContainerNameMap maObjectContainer; 87 uno::Reference < embed::XStorage > mxStorage; 88 EmbeddedObjectContainer* mpTempObjectContainer; 89 uno::Reference < embed::XStorage > mxImageStorage; 90 uno::WeakReference < uno::XInterface > m_xModel; 91 //EmbeddedObjectContainerNameMap maTempObjectContainer; 92 //uno::Reference < embed::XStorage > mxTempStorage; 93 94 /// bitfield 95 bool mbOwnsStorage : 1; 96 bool mbUserAllowsLinkUpdate : 1; 97 98 const uno::Reference < embed::XStorage >& GetReplacements(); 99 }; 100 101 const uno::Reference < embed::XStorage >& EmbedImpl::GetReplacements() 102 { 103 if ( !mxImageStorage.is() ) 104 { 105 try 106 { 107 mxImageStorage = mxStorage->openStorageElement( 108 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READWRITE ); 109 } 110 catch ( uno::Exception& ) 111 { 112 mxImageStorage = mxStorage->openStorageElement( 113 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READ ); 114 } 115 } 116 117 if ( !mxImageStorage.is() ) 118 throw io::IOException(); 119 120 return mxImageStorage; 121 } 122 123 EmbeddedObjectContainer::EmbeddedObjectContainer() 124 { 125 pImpl = new EmbedImpl; 126 pImpl->mxStorage = ::comphelper::OStorageHelper::GetTemporaryStorage(); 127 pImpl->mbOwnsStorage = true; 128 pImpl->mbUserAllowsLinkUpdate = true; 129 pImpl->mpTempObjectContainer = 0; 130 } 131 132 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor ) 133 { 134 pImpl = new EmbedImpl; 135 pImpl->mxStorage = rStor; 136 pImpl->mbOwnsStorage = false; 137 pImpl->mbUserAllowsLinkUpdate = true; 138 pImpl->mpTempObjectContainer = 0; 139 } 140 141 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor, const uno::Reference < uno::XInterface >& xModel ) 142 { 143 pImpl = new EmbedImpl; 144 pImpl->mxStorage = rStor; 145 pImpl->mbOwnsStorage = false; 146 pImpl->mbUserAllowsLinkUpdate = true; 147 pImpl->mpTempObjectContainer = 0; 148 pImpl->m_xModel = xModel; 149 } 150 151 void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference < embed::XStorage >& rStor ) 152 { 153 ReleaseImageSubStorage(); 154 155 if ( pImpl->mbOwnsStorage ) 156 pImpl->mxStorage->dispose(); 157 158 pImpl->mxStorage = rStor; 159 pImpl->mbOwnsStorage = false; 160 } 161 162 sal_Bool EmbeddedObjectContainer::CommitImageSubStorage() 163 { 164 if ( pImpl->mxImageStorage.is() ) 165 { 166 try 167 { 168 sal_Bool bReadOnlyMode = sal_True; 169 uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY); 170 if ( xSet.is() ) 171 { 172 // get the open mode from the parent storage 173 sal_Int32 nMode = 0; 174 uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") ); 175 if ( aAny >>= nMode ) 176 bReadOnlyMode = !(nMode & embed::ElementModes::WRITE ); 177 } // if ( xSet.is() ) 178 if ( !bReadOnlyMode ) 179 { 180 uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW ); 181 xTransact->commit(); 182 } 183 } 184 catch( uno::Exception& ) 185 { 186 return sal_False; 187 } 188 } 189 190 return sal_True; 191 } 192 193 void EmbeddedObjectContainer::ReleaseImageSubStorage() 194 { 195 CommitImageSubStorage(); 196 197 if ( pImpl->mxImageStorage.is() ) 198 { 199 try 200 { 201 pImpl->mxImageStorage->dispose(); 202 pImpl->mxImageStorage = uno::Reference< embed::XStorage >(); 203 } 204 catch( uno::Exception& ) 205 { 206 OSL_ASSERT( "Problems releasing image substorage!\n" ); 207 } 208 } 209 } 210 211 EmbeddedObjectContainer::~EmbeddedObjectContainer() 212 { 213 ReleaseImageSubStorage(); 214 215 if ( pImpl->mbOwnsStorage ) 216 pImpl->mxStorage->dispose(); 217 218 delete pImpl->mpTempObjectContainer; 219 delete pImpl; 220 } 221 222 void EmbeddedObjectContainer::CloseEmbeddedObjects() 223 { 224 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin(); 225 while ( aIt != pImpl->maObjectContainer.end() ) 226 { 227 uno::Reference < util::XCloseable > xClose( (*aIt).second, uno::UNO_QUERY ); 228 if ( xClose.is() ) 229 { 230 try 231 { 232 xClose->close( sal_True ); 233 } 234 catch ( uno::Exception& ) 235 { 236 } 237 } 238 239 aIt++; 240 } 241 } 242 243 ::rtl::OUString EmbeddedObjectContainer::CreateUniqueObjectName() 244 { 245 ::rtl::OUString aPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") ); 246 ::rtl::OUString aStr; 247 sal_Int32 i=1; 248 do 249 { 250 aStr = aPersistName; 251 aStr += ::rtl::OUString::valueOf( i++ ); 252 } 253 while( HasEmbeddedObject( aStr ) ); 254 // TODO/LATER: should we consider deleted objects? 255 256 return aStr; 257 } 258 259 uno::Sequence < ::rtl::OUString > EmbeddedObjectContainer::GetObjectNames() 260 { 261 uno::Sequence < ::rtl::OUString > aSeq( pImpl->maObjectContainer.size() ); 262 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin(); 263 sal_Int32 nIdx=0; 264 while ( aIt != pImpl->maObjectContainer.end() ) 265 aSeq[nIdx++] = (*aIt++).first; 266 return aSeq; 267 } 268 269 sal_Bool EmbeddedObjectContainer::HasEmbeddedObjects() 270 { 271 return pImpl->maObjectContainer.size() != 0; 272 } 273 274 sal_Bool EmbeddedObjectContainer::HasEmbeddedObject( const ::rtl::OUString& rName ) 275 { 276 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName ); 277 if ( aIt == pImpl->maObjectContainer.end() ) 278 { 279 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY ); 280 return xAccess->hasByName(rName); 281 } 282 else 283 return sal_True; 284 } 285 286 sal_Bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj ) 287 { 288 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin(); 289 while ( aIt != pImpl->maObjectContainer.end() ) 290 { 291 if ( (*aIt).second == xObj ) 292 return sal_True; 293 else 294 aIt++; 295 } 296 297 return sal_False; 298 } 299 300 sal_Bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const ::rtl::OUString& rName ) 301 { 302 // allows to detect whether the object was already instantiated 303 // currently the filter instantiate it on loading, so this method allows 304 // to avoid objects pointing to the same persistence 305 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName ); 306 return ( aIt != pImpl->maObjectContainer.end() ); 307 } 308 309 ::rtl::OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj ) 310 { 311 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin(); 312 while ( aIt != pImpl->maObjectContainer.end() ) 313 { 314 if ( (*aIt).second == xObj ) 315 return (*aIt).first; 316 else 317 aIt++; 318 } 319 320 OSL_ENSURE( 0, "Unknown object!" ); 321 return ::rtl::OUString(); 322 } 323 324 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::GetEmbeddedObject( const ::rtl::OUString& rName ) 325 { 326 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetEmbeddedObject" ); 327 328 OSL_ENSURE( !rName.isEmpty(), "Empty object name!"); 329 330 uno::Reference < embed::XEmbeddedObject > xObj; 331 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName ); 332 333 #if OSL_DEBUG_LEVEL > 1 334 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY ); 335 uno::Sequence< ::rtl::OUString> aSeq = xAccess->getElementNames(); 336 const ::rtl::OUString* pIter = aSeq.getConstArray(); 337 const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); 338 for(;pIter != pEnd;++pIter) 339 { 340 (void)*pIter; 341 } 342 OSL_ENSURE( aIt != pImpl->maObjectContainer.end() || xAccess->hasByName(rName), "Could not return object!" ); 343 #endif 344 345 // check if object was already created 346 if ( aIt != pImpl->maObjectContainer.end() ) 347 xObj = (*aIt).second; 348 else 349 xObj = Get_Impl( rName, uno::Reference < embed::XEmbeddedObject >() ); 350 351 return xObj; 352 } 353 354 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::Get_Impl( const ::rtl::OUString& rName, const uno::Reference < embed::XEmbeddedObject >& xCopy ) 355 { 356 uno::Reference < embed::XEmbeddedObject > xObj; 357 try 358 { 359 // create the object from the storage 360 uno::Reference < beans::XPropertySet > xSet( pImpl->mxStorage, uno::UNO_QUERY ); 361 sal_Bool bReadOnlyMode = sal_True; 362 if ( xSet.is() ) 363 { 364 // get the open mode from the parent storage 365 sal_Int32 nMode = 0; 366 uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") ); 367 if ( aAny >>= nMode ) 368 bReadOnlyMode = !(nMode & embed::ElementModes::WRITE ); 369 } 370 371 // object was not added until now - should happen only by calling this method from "inside" 372 //TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call) 373 uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance( 374 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY ); 375 uno::Sequence< beans::PropertyValue > aObjDescr( xCopy.is() ? 2 : 1 ); 376 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) ); 377 aObjDescr[0].Value <<= pImpl->m_xModel.get(); 378 if ( xCopy.is() ) 379 { 380 aObjDescr[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CloneFrom" ) ); 381 aObjDescr[1].Value <<= xCopy; 382 } 383 384 uno::Sequence< beans::PropertyValue > aMediaDescr( 1 ); 385 aMediaDescr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")); 386 aMediaDescr[0].Value <<= bReadOnlyMode; 387 xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromEntry( 388 pImpl->mxStorage, rName, 389 aMediaDescr, aObjDescr ), uno::UNO_QUERY ); 390 391 // insert object into my list 392 AddEmbeddedObject( xObj, rName ); 393 } 394 catch ( uno::Exception& ) 395 { 396 } 397 398 return xObj; 399 } 400 401 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId, 402 const uno::Sequence < beans::PropertyValue >& rArgs, ::rtl::OUString& rNewName ) 403 { 404 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CreateEmbeddedObject" ); 405 406 if ( rNewName.isEmpty() ) 407 rNewName = CreateUniqueObjectName(); 408 409 OSL_ENSURE( !HasEmbeddedObject(rNewName), "Object to create already exists!"); 410 411 // create object from classid by inserting it into storage 412 uno::Reference < embed::XEmbeddedObject > xObj; 413 try 414 { 415 uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance( 416 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY ); 417 418 uno::Sequence< beans::PropertyValue > aObjDescr( rArgs.getLength() + 1 ); 419 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) ); 420 aObjDescr[0].Value <<= pImpl->m_xModel.get(); 421 ::std::copy( rArgs.getConstArray(), rArgs.getConstArray() + rArgs.getLength(), aObjDescr.getArray() + 1 ); 422 xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitNew( 423 rClassId, ::rtl::OUString(), pImpl->mxStorage, rNewName, 424 aObjDescr ), uno::UNO_QUERY ); 425 426 AddEmbeddedObject( xObj, rNewName ); 427 428 OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED, 429 "A freshly create object should be running always!\n" ); 430 } 431 catch ( uno::Exception& ) 432 { 433 } 434 435 return xObj; 436 } 437 438 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId, ::rtl::OUString& rNewName ) 439 { 440 return CreateEmbeddedObject( rClassId, uno::Sequence < beans::PropertyValue >(), rNewName ); 441 } 442 443 void EmbeddedObjectContainer::AddEmbeddedObject( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, const ::rtl::OUString& rName ) 444 { 445 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::AddEmbeddedObject" ); 446 447 #if OSL_DEBUG_LEVEL > 1 448 OSL_ENSURE( !rName.isEmpty(), "Added object doesn't have a name!"); 449 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY ); 450 uno::Reference < embed::XEmbedPersist > xEmb( xObj, uno::UNO_QUERY ); 451 uno::Reference < embed::XLinkageSupport > xLink( xEmb, uno::UNO_QUERY ); 452 // if the object has a persistence and the object is not a link than it must have persistence entry in the storage 453 OSL_ENSURE( !( xEmb.is() && ( !xLink.is() || !xLink->isLink() ) ) || xAccess->hasByName(rName), 454 "Added element not in storage!" ); 455 #endif 456 457 // remember object - it needs to be in storage already 458 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName ); 459 OSL_ENSURE( aIt == pImpl->maObjectContainer.end(), "Element already inserted!" ); 460 pImpl->maObjectContainer[ rName ] = xObj; 461 uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY ); 462 if ( xChild.is() && xChild->getParent() != pImpl->m_xModel.get() ) 463 xChild->setParent( pImpl->m_xModel.get() ); 464 465 // look for object in temorary container 466 if ( pImpl->mpTempObjectContainer ) 467 { 468 aIt = pImpl->mpTempObjectContainer->pImpl->maObjectContainer.begin(); 469 while ( aIt != pImpl->mpTempObjectContainer->pImpl->maObjectContainer.end() ) 470 { 471 if ( (*aIt).second == xObj ) 472 { 473 // copy replacement image from temporary container (if there is any) 474 ::rtl::OUString aTempName = (*aIt).first; 475 ::rtl::OUString aMediaType; 476 uno::Reference < io::XInputStream > xStream = pImpl->mpTempObjectContainer->GetGraphicStream( xObj, &aMediaType ); 477 if ( xStream.is() ) 478 { 479 InsertGraphicStream( xStream, rName, aMediaType ); 480 xStream = 0; 481 pImpl->mpTempObjectContainer->RemoveGraphicStream( aTempName ); 482 } 483 484 // remove object from storage of temporary container 485 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 486 if ( xPersist.is() ) 487 { 488 try 489 { 490 pImpl->mpTempObjectContainer->pImpl->mxStorage->removeElement( aTempName ); 491 } 492 catch ( uno::Exception& ) 493 { 494 } 495 } 496 497 // temp. container needs to forget the object 498 pImpl->mpTempObjectContainer->pImpl->maObjectContainer.erase( aIt ); 499 break; 500 } 501 else 502 aIt++; 503 } 504 } 505 } 506 507 sal_Bool EmbeddedObjectContainer::StoreEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName, sal_Bool bCopy ) 508 { 509 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::StoreEmbeddedObject" ); 510 511 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 512 if ( rName.isEmpty() ) 513 rName = CreateUniqueObjectName(); 514 515 #if OSL_DEBUG_LEVEL > 1 516 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY ); 517 OSL_ENSURE( !xPersist.is() || !xAccess->hasByName(rName), "Inserting element already present in storage!" ); 518 OSL_ENSURE( xPersist.is() || xObj->getCurrentState() == embed::EmbedStates::RUNNING, "Non persistent object inserted!"); 519 #endif 520 521 // insert objects' storage into the container storage (if object has one) 522 try 523 { 524 if ( xPersist.is() ) 525 { 526 uno::Sequence < beans::PropertyValue > aSeq; 527 if ( bCopy ) 528 xPersist->storeToEntry( pImpl->mxStorage, rName, aSeq, aSeq ); 529 else 530 { 531 // TODO/LATER: possible optimization, don't store immediately 532 //xPersist->setPersistentEntry( pImpl->mxStorage, rName, embed::EntryInitModes::ENTRY_NO_INIT, aSeq, aSeq ); 533 xPersist->storeAsEntry( pImpl->mxStorage, rName, aSeq, aSeq ); 534 xPersist->saveCompleted( sal_True ); 535 } 536 } 537 } 538 catch ( uno::Exception& ) 539 { 540 // TODO/LATER: better error recovery should keep storage intact 541 return sal_False; 542 } 543 544 return sal_True; 545 } 546 547 sal_Bool EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName ) 548 { 549 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( Object )" ); 550 // store it into the container storage 551 if ( StoreEmbeddedObject( xObj, rName, sal_False ) ) 552 { 553 // remember object 554 AddEmbeddedObject( xObj, rName ); 555 return sal_True; 556 } 557 else 558 return sal_False; 559 } 560 561 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < io::XInputStream >& xStm, ::rtl::OUString& rNewName ) 562 { 563 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( InputStream )" ); 564 565 if ( rNewName.isEmpty() ) 566 rNewName = CreateUniqueObjectName(); 567 568 // store it into the container storage 569 sal_Bool bIsStorage = sal_False; 570 try 571 { 572 // first try storage persistence 573 uno::Reference < embed::XStorage > xStore = ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm ); 574 575 // storage was created from stream successfully 576 bIsStorage = sal_True; 577 578 uno::Reference < embed::XStorage > xNewStore = pImpl->mxStorage->openStorageElement( rNewName, embed::ElementModes::READWRITE ); 579 xStore->copyToStorage( xNewStore ); 580 } 581 catch ( uno::Exception& ) 582 { 583 if ( bIsStorage ) 584 // it is storage persistence, but opening of new substorage or copying to it failed 585 return uno::Reference < embed::XEmbeddedObject >(); 586 587 // stream didn't contain a storage, now try stream persistence 588 try 589 { 590 uno::Reference < io::XStream > xNewStream = pImpl->mxStorage->openStreamElement( rNewName, embed::ElementModes::READWRITE ); 591 ::comphelper::OStorageHelper::CopyInputToOutput( xStm, xNewStream->getOutputStream() ); 592 593 // No mediatype is provided so the default for OLE objects value is used 594 // it is correct so for now, but what if somebody introduces a new stream based embedded object? 595 // Probably introducing of such an object must be restricted ( a storage must be used! ). 596 uno::Reference< beans::XPropertySet > xProps( xNewStream, uno::UNO_QUERY_THROW ); 597 xProps->setPropertyValue( 598 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), 599 uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) ); 600 } 601 catch ( uno::Exception& ) 602 { 603 // complete disaster! 604 return uno::Reference < embed::XEmbeddedObject >(); 605 } 606 } 607 608 // stream was copied into the container storage in either way, now try to open something form it 609 uno::Reference < embed::XEmbeddedObject > xRet = GetEmbeddedObject( rNewName ); 610 try 611 { 612 if ( !xRet.is() ) 613 // no object could be created, so withdraw insertion 614 pImpl->mxStorage->removeElement( rNewName ); 615 } 616 catch ( uno::Exception& ) 617 { 618 } 619 620 return xRet; 621 } 622 623 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, ::rtl::OUString& rNewName ) 624 { 625 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( MediaDescriptor )" ); 626 627 if ( rNewName.isEmpty() ) 628 rNewName = CreateUniqueObjectName(); 629 630 uno::Reference < embed::XEmbeddedObject > xObj; 631 try 632 { 633 uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance( 634 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY ); 635 uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); 636 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) ); 637 aObjDescr[0].Value <<= pImpl->m_xModel.get(); 638 xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromMediaDescriptor( 639 pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY ); 640 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 641 642 OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED, 643 "A freshly create object should be running always!\n" ); 644 645 // possible optimization: store later! 646 if ( xPersist.is()) 647 xPersist->storeOwn(); 648 649 AddEmbeddedObject( xObj, rNewName ); 650 } 651 catch ( uno::Exception& ) 652 { 653 } 654 655 return xObj; 656 } 657 658 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedLink( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, ::rtl::OUString& rNewName ) 659 { 660 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedLink" ); 661 662 if ( rNewName.isEmpty() ) 663 rNewName = CreateUniqueObjectName(); 664 665 uno::Reference < embed::XEmbeddedObject > xObj; 666 try 667 { 668 uno::Reference < embed::XLinkCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance( 669 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY ); 670 uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); 671 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) ); 672 aObjDescr[0].Value <<= pImpl->m_xModel.get(); 673 xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceLink( 674 pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY ); 675 676 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 677 678 OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED, 679 "A freshly create object should be running always!\n" ); 680 681 // possible optimization: store later! 682 if ( xPersist.is()) 683 xPersist->storeOwn(); 684 685 AddEmbeddedObject( xObj, rNewName ); 686 } 687 catch ( uno::Exception& ) 688 { 689 } 690 691 return xObj; 692 } 693 694 sal_Bool EmbeddedObjectContainer::TryToCopyGraphReplacement( EmbeddedObjectContainer& rSrc, 695 const ::rtl::OUString& aOrigName, 696 const ::rtl::OUString& aTargetName ) 697 { 698 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::TryToCopyGraphReplacement" ); 699 700 sal_Bool bResult = sal_False; 701 702 if ( ( &rSrc != this || !aOrigName.equals( aTargetName ) ) && !aOrigName.isEmpty() && !aTargetName.isEmpty() ) 703 { 704 ::rtl::OUString aMediaType; 705 uno::Reference < io::XInputStream > xGrStream = rSrc.GetGraphicStream( aOrigName, &aMediaType ); 706 if ( xGrStream.is() ) 707 bResult = InsertGraphicStream( xGrStream, aTargetName, aMediaType ); 708 } 709 710 return bResult; 711 } 712 713 sal_Bool EmbeddedObjectContainer::CopyEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName ) 714 { 715 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyEmbeddedObject" ); 716 717 OSL_ENSURE( sal_False, 718 "This method is depricated! Use EmbeddedObjectContainer::CopyAndGetEmbeddedObject() to copy object!\n" ); 719 720 // get the object name before(!) it is assigned to a new storage 721 ::rtl::OUString aOrigName; 722 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 723 if ( xPersist.is() ) 724 aOrigName = xPersist->getEntryName(); 725 726 if ( rName.isEmpty() ) 727 rName = CreateUniqueObjectName(); 728 729 if ( StoreEmbeddedObject( xObj, rName, sal_True ) ) 730 { 731 TryToCopyGraphReplacement( rSrc, aOrigName, rName ); 732 return sal_True; 733 } 734 735 return sal_False; 736 } 737 738 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName ) 739 { 740 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyAndGetEmbeddedObject" ); 741 742 uno::Reference< embed::XEmbeddedObject > xResult; 743 744 // TODO/LATER: For now only objects that implement XEmbedPersist have a replacement image, it might change in future 745 // do an incompatible change so that object name is provided in all the move and copy methods 746 ::rtl::OUString aOrigName; 747 try 748 { 749 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY_THROW ); 750 aOrigName = xPersist->getEntryName(); 751 } 752 catch( uno::Exception& ) 753 {} 754 755 if ( rName.isEmpty() ) 756 rName = CreateUniqueObjectName(); 757 758 // objects without persistence are not really stored by the method 759 if ( xObj.is() && StoreEmbeddedObject( xObj, rName, sal_True ) ) 760 { 761 xResult = Get_Impl( rName, xObj); 762 if ( !xResult.is() ) 763 { 764 // this is a case when object has no real persistence 765 // in such cases a new object should be explicitly created and initialized with the data of the old one 766 try 767 { 768 uno::Reference< embed::XLinkageSupport > xOrigLinkage( xObj, uno::UNO_QUERY ); 769 if ( xOrigLinkage.is() && xOrigLinkage->isLink() ) 770 { 771 // this is a OOo link, it has no persistence 772 ::rtl::OUString aURL = xOrigLinkage->getLinkURL(); 773 if ( aURL.isEmpty() ) 774 throw uno::RuntimeException(); 775 776 // create new linked object from the URL the link is based on 777 uno::Reference < embed::XLinkCreator > xCreator( 778 ::comphelper::getProcessServiceFactory()->createInstance( 779 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ), 780 uno::UNO_QUERY_THROW ); 781 782 uno::Sequence< beans::PropertyValue > aMediaDescr( 1 ); 783 aMediaDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); 784 aMediaDescr[0].Value <<= aURL; 785 uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); 786 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) ); 787 aObjDescr[0].Value <<= pImpl->m_xModel.get(); 788 xResult = uno::Reference < embed::XEmbeddedObject >( 789 xCreator->createInstanceLink( 790 pImpl->mxStorage, 791 rName, 792 aMediaDescr, 793 aObjDescr ), 794 uno::UNO_QUERY_THROW ); 795 } 796 else 797 { 798 // the component is required for copying of this object 799 if ( xObj->getCurrentState() == embed::EmbedStates::LOADED ) 800 xObj->changeState( embed::EmbedStates::RUNNING ); 801 802 // this must be an object based on properties, otherwise we can not copy it currently 803 uno::Reference< beans::XPropertySet > xOrigProps( xObj->getComponent(), uno::UNO_QUERY_THROW ); 804 805 // use object class ID to create a new one and transfer all the properties 806 uno::Reference < embed::XEmbedObjectCreator > xCreator( 807 ::comphelper::getProcessServiceFactory()->createInstance( 808 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ), 809 uno::UNO_QUERY_THROW ); 810 811 uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); 812 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) ); 813 aObjDescr[0].Value <<= pImpl->m_xModel.get(); 814 xResult = uno::Reference < embed::XEmbeddedObject >( 815 xCreator->createInstanceInitNew( 816 xObj->getClassID(), 817 xObj->getClassName(), 818 pImpl->mxStorage, 819 rName, 820 aObjDescr ), 821 uno::UNO_QUERY_THROW ); 822 823 if ( xResult->getCurrentState() == embed::EmbedStates::LOADED ) 824 xResult->changeState( embed::EmbedStates::RUNNING ); 825 826 uno::Reference< beans::XPropertySet > xTargetProps( xResult->getComponent(), uno::UNO_QUERY_THROW ); 827 828 // copy all the properties from xOrigProps to xTargetProps 829 uno::Reference< beans::XPropertySetInfo > xOrigInfo = xOrigProps->getPropertySetInfo(); 830 if ( !xOrigInfo.is() ) 831 throw uno::RuntimeException(); 832 833 uno::Sequence< beans::Property > aPropertiesList = xOrigInfo->getProperties(); 834 for ( sal_Int32 nInd = 0; nInd < aPropertiesList.getLength(); nInd++ ) 835 { 836 try 837 { 838 xTargetProps->setPropertyValue( 839 aPropertiesList[nInd].Name, 840 xOrigProps->getPropertyValue( aPropertiesList[nInd].Name ) ); 841 } 842 catch( beans::PropertyVetoException& ) 843 { 844 // impossibility to copy readonly property is not treated as an error for now 845 // but the assertion is helpful to detect such scenarios and review them 846 OSL_ENSURE( sal_False, "Could not copy readonly property!\n" ); 847 } 848 } 849 } 850 851 if ( xResult.is() ) 852 AddEmbeddedObject( xResult, rName ); 853 } 854 catch( uno::Exception& ) 855 { 856 if ( xResult.is() ) 857 { 858 try 859 { 860 xResult->close( sal_True ); 861 } 862 catch( uno::Exception& ) 863 {} 864 xResult = uno::Reference< embed::XEmbeddedObject >(); 865 } 866 } 867 } 868 } 869 870 OSL_ENSURE( xResult.is(), "Can not copy embedded object that has no persistence!\n" ); 871 872 if ( xResult.is() ) 873 { 874 // the object is successfully copied, try to copy graphical replacement 875 if ( !aOrigName.isEmpty() ) 876 TryToCopyGraphReplacement( rSrc, aOrigName, rName ); 877 878 // the object might need the size to be set 879 try 880 { 881 if ( xResult->getStatus( embed::Aspects::MSOLE_CONTENT ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ) 882 xResult->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, 883 xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ) ); 884 } 885 catch( uno::Exception& ) 886 {} 887 } 888 889 return xResult; 890 } 891 892 sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName ) 893 { 894 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Object )" ); 895 896 // get the object name before(!) it is assigned to a new storage 897 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 898 ::rtl::OUString aName; 899 if ( xPersist.is() ) 900 aName = xPersist->getEntryName(); 901 902 // now move the object to the new container; the returned name is the new persist name in this container 903 sal_Bool bRet; 904 905 try 906 { 907 bRet = InsertEmbeddedObject( xObj, rName ); 908 if ( bRet ) 909 TryToCopyGraphReplacement( rSrc, aName, rName ); 910 } 911 catch ( uno::Exception& e ) 912 { 913 (void)e; 914 OSL_ENSURE( sal_False, "Failed to insert embedded object into storage!" ); 915 bRet = sal_False; 916 } 917 918 if ( bRet ) 919 { 920 // now remove the object from the former container 921 bRet = sal_False; 922 EmbeddedObjectContainerNameMap::iterator aIt = rSrc.pImpl->maObjectContainer.begin(); 923 while ( aIt != rSrc.pImpl->maObjectContainer.end() ) 924 { 925 if ( (*aIt).second == xObj ) 926 { 927 rSrc.pImpl->maObjectContainer.erase( aIt ); 928 bRet = sal_True; 929 break; 930 } 931 932 aIt++; 933 } 934 935 OSL_ENSURE( bRet, "Object not found for removal!" ); 936 if ( xPersist.is() ) 937 { 938 // now it's time to remove the storage from the container storage 939 try 940 { 941 if ( xPersist.is() ) 942 rSrc.pImpl->mxStorage->removeElement( aName ); 943 } 944 catch ( uno::Exception& ) 945 { 946 OSL_ENSURE( sal_False, "Failed to remove object from storage!" ); 947 bRet = sal_False; 948 } 949 } 950 951 // rSrc.RemoveGraphicStream( aName ); 952 } 953 954 return bRet; 955 } 956 957 //sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const ::rtl::OUString& rName, sal_Bool bClose ) 958 // #i119941, bKeepToTempStorage: use to specify whether store the removed object to temporary storage+ 959 sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const ::rtl::OUString& rName, sal_Bool bClose, sal_Bool bKeepToTempStorage ) 960 { 961 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Name )" ); 962 963 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( rName ); 964 if ( xObj.is() ) 965 //return RemoveEmbeddedObject( xObj, bClose ); 966 return RemoveEmbeddedObject( xObj, bClose, bKeepToTempStorage ); 967 else 968 return sal_False; 969 } 970 971 sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( const ::rtl::OUString& rName, EmbeddedObjectContainer& rCnt ) 972 { 973 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Name )" ); 974 975 // find object entry 976 EmbeddedObjectContainerNameMap::iterator aIt2 = rCnt.pImpl->maObjectContainer.find( rName ); 977 OSL_ENSURE( aIt2 == rCnt.pImpl->maObjectContainer.end(), "Object does already exist in target container!" ); 978 979 if ( aIt2 != rCnt.pImpl->maObjectContainer.end() ) 980 return sal_False; 981 982 uno::Reference < embed::XEmbeddedObject > xObj; 983 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName ); 984 if ( aIt != pImpl->maObjectContainer.end() ) 985 { 986 xObj = (*aIt).second; 987 try 988 { 989 if ( xObj.is() ) 990 { 991 // move object 992 ::rtl::OUString aName( rName ); 993 rCnt.InsertEmbeddedObject( xObj, aName ); 994 pImpl->maObjectContainer.erase( aIt ); 995 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 996 if ( xPersist.is() ) 997 pImpl->mxStorage->removeElement( rName ); 998 } 999 else 1000 { 1001 // copy storages; object *must* have persistence! 1002 uno::Reference < embed::XStorage > xOld = pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READ ); 1003 uno::Reference < embed::XStorage > xNew = rCnt.pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READWRITE ); 1004 xOld->copyToStorage( xNew ); 1005 } 1006 1007 rCnt.TryToCopyGraphReplacement( *this, rName, rName ); 1008 // RemoveGraphicStream( rName ); 1009 1010 return sal_True; 1011 } 1012 catch ( uno::Exception& ) 1013 { 1014 OSL_ENSURE(0,"Could not move object!"); 1015 return sal_False; 1016 } 1017 1018 } 1019 else 1020 OSL_ENSURE(0,"Unknown object!"); 1021 return sal_False; 1022 } 1023 1024 //sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose ) 1025 // #i119941, bKeepToTempStorage: use to specify whether store the removed object to temporary storage+ 1026 sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose, sal_Bool bKeepToTempStorage ) 1027 { 1028 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Object )" ); 1029 1030 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 1031 ::rtl::OUString aName; 1032 if ( xPersist.is() ) 1033 aName = xPersist->getEntryName(); 1034 1035 #if OSL_DEBUG_LEVEL > 1 1036 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY ); 1037 uno::Reference < embed::XLinkageSupport > xLink( xPersist, uno::UNO_QUERY ); 1038 sal_Bool bIsNotEmbedded = !xPersist.is() || xLink.is() && xLink->isLink(); 1039 1040 // if the object has a persistence and the object is not a link than it must have persistence entry in the storage 1041 OSL_ENSURE( bIsNotEmbedded || xAccess->hasByName(aName), "Removing element not present in storage!" ); 1042 #endif 1043 1044 // try to close it if permitted 1045 if ( bClose ) 1046 { 1047 uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY ); 1048 try 1049 { 1050 xClose->close( sal_True ); 1051 } 1052 catch ( util::CloseVetoException& ) 1053 { 1054 bClose = sal_False; 1055 } 1056 } 1057 1058 if ( !bClose ) 1059 { 1060 // somebody still needs the object, so we must assign a temporary persistence 1061 try 1062 { 1063 // if ( xPersist.is() ) 1064 if ( xPersist.is() && bKeepToTempStorage ) // #i119941 1065 { 1066 /* 1067 // TODO/LATER: needs storage handling! Why not letting the object do it?! 1068 if ( !pImpl->mxTempStorage.is() ) 1069 pImpl->mxTempStorage = ::comphelper::OStorageHelper::GetTemporaryStorage(); 1070 uno::Sequence < beans::PropertyValue > aSeq; 1071 1072 ::rtl::OUString aTmpPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") ); 1073 aTmpPersistName += ::rtl::OUString::valueOf( (sal_Int32) pImpl->maTempObjectContainer.size() ); 1074 1075 xPersist->storeAsEntry( pImpl->mxTempStorage, aTmpPersistName, aSeq, aSeq ); 1076 xPersist->saveCompleted( sal_True ); 1077 1078 pImpl->maTempObjectContainer[ aTmpPersistName ] = uno::Reference < embed::XEmbeddedObject >(); 1079 */ 1080 1081 if ( !pImpl->mpTempObjectContainer ) 1082 { 1083 pImpl->mpTempObjectContainer = new EmbeddedObjectContainer(); 1084 try 1085 { 1086 // TODO/LATER: in future probably the temporary container will have two storages ( of two formats ) 1087 // the media type will be provided with object insertion 1088 ::rtl::OUString aOrigStorMediaType; 1089 uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW ); 1090 static const ::rtl::OUString s_sMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType")); 1091 xStorProps->getPropertyValue( s_sMediaType ) >>= aOrigStorMediaType; 1092 1093 OSL_ENSURE( !aOrigStorMediaType.isEmpty(), "No valuable media type in the storage!\n" ); 1094 1095 uno::Reference< beans::XPropertySet > xTargetStorProps( 1096 pImpl->mpTempObjectContainer->pImpl->mxStorage, 1097 uno::UNO_QUERY_THROW ); 1098 xTargetStorProps->setPropertyValue( s_sMediaType,uno::makeAny( aOrigStorMediaType ) ); 1099 } 1100 catch( uno::Exception& ) 1101 { 1102 OSL_ENSURE( sal_False, "Can not set the new media type to a storage!\n" ); 1103 } 1104 } 1105 1106 ::rtl::OUString aTempName, aMediaType; 1107 pImpl->mpTempObjectContainer->InsertEmbeddedObject( xObj, aTempName ); 1108 1109 uno::Reference < io::XInputStream > xStream = GetGraphicStream( xObj, &aMediaType ); 1110 if ( xStream.is() ) 1111 pImpl->mpTempObjectContainer->InsertGraphicStream( xStream, aTempName, aMediaType ); 1112 1113 // object is stored, so at least it can be set to loaded state 1114 xObj->changeState( embed::EmbedStates::LOADED ); 1115 } 1116 else 1117 // objects without persistence need to stay in running state if they shall not be closed 1118 xObj->changeState( embed::EmbedStates::RUNNING ); 1119 } 1120 catch ( uno::Exception& ) 1121 { 1122 return sal_False; 1123 } 1124 } 1125 1126 sal_Bool bFound = sal_False; 1127 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin(); 1128 while ( aIt != pImpl->maObjectContainer.end() ) 1129 { 1130 if ( (*aIt).second == xObj ) 1131 { 1132 pImpl->maObjectContainer.erase( aIt ); 1133 bFound = sal_True; 1134 uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY ); 1135 if ( xChild.is() ) 1136 xChild->setParent( uno::Reference < uno::XInterface >() ); 1137 break; 1138 } 1139 1140 aIt++; 1141 } 1142 1143 OSL_ENSURE( bFound, "Object not found for removal!" ); 1144 // if ( xPersist.is() ) 1145 if ( xPersist.is() && bKeepToTempStorage ) // #i119941 1146 { 1147 // remove replacement image (if there is one) 1148 RemoveGraphicStream( aName ); 1149 1150 // now it's time to remove the storage from the container storage 1151 try 1152 { 1153 #if OSL_DEBUG_LEVEL > 1 1154 // if the object has a persistence and the object is not a link than it must have persistence entry in storage 1155 OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" ); 1156 #endif 1157 if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) ) 1158 pImpl->mxStorage->removeElement( aName ); 1159 } 1160 catch ( uno::Exception& ) 1161 { 1162 OSL_ENSURE( sal_False, "Failed to remove object from storage!" ); 1163 return sal_False; 1164 } 1165 } 1166 1167 return sal_True; 1168 } 1169 1170 sal_Bool EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj ) 1171 { 1172 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CloseEmbeddedObject" ); 1173 1174 // disconnect the object from the container and close it if possible 1175 1176 sal_Bool bFound = sal_False; 1177 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin(); 1178 while ( aIt != pImpl->maObjectContainer.end() ) 1179 { 1180 if ( (*aIt).second == xObj ) 1181 { 1182 pImpl->maObjectContainer.erase( aIt ); 1183 bFound = sal_True; 1184 break; 1185 } 1186 1187 aIt++; 1188 } 1189 1190 if ( bFound ) 1191 { 1192 uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY ); 1193 try 1194 { 1195 xClose->close( sal_True ); 1196 } 1197 catch ( uno::Exception& ) 1198 { 1199 // it is no problem if the object is already closed 1200 // TODO/LATER: what if the object can not be closed? 1201 } 1202 } 1203 1204 return bFound; 1205 } 1206 1207 uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::rtl::OUString& aName, rtl::OUString* pMediaType ) 1208 { 1209 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Name )" ); 1210 1211 uno::Reference < io::XInputStream > xStream; 1212 1213 OSL_ENSURE( !aName.isEmpty(), "Retrieving graphic for unknown object!" ); 1214 if ( !aName.isEmpty() ) 1215 { 1216 try 1217 { 1218 uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements(); 1219 uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( aName, embed::ElementModes::READ ); 1220 xStream = xGraphicStream->getInputStream(); 1221 if ( pMediaType ) 1222 { 1223 uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY ); 1224 if ( xSet.is() ) 1225 { 1226 uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("MediaType") ); 1227 aAny >>= *pMediaType; 1228 } 1229 } 1230 } 1231 catch ( uno::Exception& ) 1232 { 1233 } 1234 } 1235 1236 return xStream; 1237 } 1238 1239 uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, rtl::OUString* pMediaType ) 1240 { 1241 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Object )" ); 1242 1243 // get the object name 1244 ::rtl::OUString aName; 1245 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin(); 1246 while ( aIt != pImpl->maObjectContainer.end() ) 1247 { 1248 if ( (*aIt).second == xObj ) 1249 { 1250 aName = (*aIt).first; 1251 break; 1252 } 1253 1254 aIt++; 1255 } 1256 1257 // try to load it from the container storage 1258 return GetGraphicStream( aName, pMediaType ); 1259 } 1260 1261 sal_Bool EmbeddedObjectContainer::InsertGraphicStream( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType ) 1262 { 1263 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStream" ); 1264 1265 try 1266 { 1267 uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements(); 1268 1269 // store it into the subfolder 1270 uno::Reference < io::XOutputStream > xOutStream; 1271 uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( rObjectName, 1272 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); 1273 xOutStream = xGraphicStream->getOutputStream(); 1274 ::comphelper::OStorageHelper::CopyInputToOutput( rStream, xOutStream ); 1275 xOutStream->flush(); 1276 1277 uno::Reference< beans::XPropertySet > xPropSet( xGraphicStream, uno::UNO_QUERY ); 1278 if ( !xPropSet.is() ) 1279 throw uno::RuntimeException(); 1280 1281 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ), 1282 uno::makeAny( (sal_Bool)sal_True ) ); 1283 uno::Any aAny; 1284 aAny <<= rMediaType; 1285 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii("MediaType"), aAny ); 1286 1287 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "Compressed" ), 1288 uno::makeAny( (sal_Bool)sal_True ) ); 1289 } 1290 catch( uno::Exception& ) 1291 { 1292 return sal_False; 1293 } 1294 1295 return sal_True; 1296 } 1297 1298 sal_Bool EmbeddedObjectContainer::InsertGraphicStreamDirectly( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType ) 1299 { 1300 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStreamDirectly" ); 1301 1302 try 1303 { 1304 uno::Reference < embed::XStorage > xReplacement = pImpl->GetReplacements(); 1305 uno::Reference < embed::XOptimizedStorage > xOptRepl( xReplacement, uno::UNO_QUERY_THROW ); 1306 1307 // store it into the subfolder 1308 uno::Sequence< beans::PropertyValue > aProps( 3 ); 1309 aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ); 1310 aProps[0].Value <<= rMediaType; 1311 aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) ); 1312 aProps[1].Value <<= (sal_Bool)sal_True; 1313 aProps[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ); 1314 aProps[2].Value <<= (sal_Bool)sal_True; 1315 1316 if ( xReplacement->hasByName( rObjectName ) ) 1317 xReplacement->removeElement( rObjectName ); 1318 1319 xOptRepl->insertStreamElementDirect( rObjectName, rStream, aProps ); 1320 } 1321 catch( uno::Exception& ) 1322 { 1323 return sal_False; 1324 } 1325 1326 return sal_True; 1327 } 1328 1329 1330 sal_Bool EmbeddedObjectContainer::RemoveGraphicStream( const ::rtl::OUString& rObjectName ) 1331 { 1332 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveGraphicStream" ); 1333 1334 try 1335 { 1336 uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements(); 1337 xReplacements->removeElement( rObjectName ); 1338 } 1339 catch( uno::Exception& ) 1340 { 1341 return sal_False; 1342 } 1343 1344 return sal_True; 1345 } 1346 namespace { 1347 void InsertStreamIntoPicturesStorage_Impl( const uno::Reference< embed::XStorage >& xDocStor, 1348 const uno::Reference< io::XInputStream >& xInStream, 1349 const ::rtl::OUString& aStreamName ) 1350 { 1351 OSL_ENSURE( !aStreamName.isEmpty() && xInStream.is() && xDocStor.is(), "Misuse of the method!\n" ); 1352 1353 try 1354 { 1355 uno::Reference< embed::XStorage > xPictures = xDocStor->openStorageElement( 1356 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pictures" ) ), 1357 embed::ElementModes::READWRITE ); 1358 uno::Reference< io::XStream > xObjReplStr = xPictures->openStreamElement( 1359 aStreamName, 1360 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); 1361 uno::Reference< io::XOutputStream > xOutStream( 1362 xObjReplStr->getInputStream(), uno::UNO_QUERY_THROW ); 1363 1364 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xOutStream ); 1365 xOutStream->closeOutput(); 1366 1367 uno::Reference< embed::XTransactedObject > xTransact( xPictures, uno::UNO_QUERY ); 1368 if ( xTransact.is() ) 1369 xTransact->commit(); 1370 } 1371 catch( uno::Exception& ) 1372 { 1373 OSL_ENSURE( sal_False, "The pictures storage is not available!\n" ); 1374 } 1375 } 1376 1377 } 1378 // ----------------------------------------------------------------------------- 1379 sal_Bool EmbeddedObjectContainer::StoreAsChildren(sal_Bool _bOasisFormat,sal_Bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage) 1380 { 1381 sal_Bool bResult = sal_False; 1382 try 1383 { 1384 comphelper::EmbeddedObjectContainer aCnt( _xStorage ); 1385 const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames(); 1386 const ::rtl::OUString* pIter = aNames.getConstArray(); 1387 const ::rtl::OUString* pEnd = pIter + aNames.getLength(); 1388 for(;pIter != pEnd;++pIter) 1389 { 1390 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter ); 1391 OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" ); 1392 if ( xObj.is() ) 1393 { 1394 sal_Bool bSwitchBackToLoaded = sal_False; 1395 uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY ); 1396 1397 uno::Reference < io::XInputStream > xStream; 1398 ::rtl::OUString aMediaType; 1399 1400 sal_Int32 nCurState = xObj->getCurrentState(); 1401 if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING ) 1402 { 1403 // means that the object is not active 1404 // copy replacement image from old to new container 1405 xStream = GetGraphicStream( xObj, &aMediaType ); 1406 } 1407 1408 if ( !xStream.is() && getUserAllowsLinkUpdate() ) 1409 { 1410 // the image must be regenerated 1411 // TODO/LATER: another aspect could be used 1412 if ( xObj->getCurrentState() == embed::EmbedStates::LOADED ) 1413 bSwitchBackToLoaded = sal_True; 1414 1415 xStream = GetGraphicReplacementStream( 1416 embed::Aspects::MSOLE_CONTENT, 1417 xObj, 1418 &aMediaType ); 1419 } 1420 1421 if ( _bOasisFormat || (xLink.is() && xLink->isLink()) ) 1422 { 1423 if ( xStream.is() ) 1424 { 1425 if ( _bOasisFormat ) 1426 { 1427 // if it is an embedded object or the optimized inserting fails the normal inserting should be done 1428 if ( _bCreateEmbedded 1429 || !aCnt.InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) ) 1430 aCnt.InsertGraphicStream( xStream, *pIter, aMediaType ); 1431 } 1432 else 1433 { 1434 // it is a linked object exported into SO7 format 1435 InsertStreamIntoPicturesStorage_Impl( _xStorage, xStream, *pIter ); 1436 } 1437 } 1438 } 1439 1440 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 1441 if ( xPersist.is() ) 1442 { 1443 uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 ); 1444 aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StoreVisualReplacement" ) ); 1445 aArgs[0].Value <<= (sal_Bool)( !_bOasisFormat ); 1446 1447 // if it is an embedded object or the optimized inserting fails the normal inserting should be done 1448 aArgs[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanTryOptimization" ) ); 1449 aArgs[1].Value <<= !_bCreateEmbedded; 1450 if ( !_bOasisFormat ) 1451 { 1452 // if object has no cached replacement it will use this one 1453 aArgs[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualReplacement" ) ); 1454 aArgs[2].Value <<= xStream; 1455 } 1456 1457 xPersist->storeAsEntry( _xStorage, 1458 xPersist->getEntryName(), 1459 uno::Sequence< beans::PropertyValue >(), 1460 aArgs ); 1461 } 1462 1463 if ( bSwitchBackToLoaded ) 1464 // switch back to loaded state; that way we have a minimum cache confusion 1465 xObj->changeState( embed::EmbedStates::LOADED ); 1466 } 1467 } 1468 1469 bResult = aCnt.CommitImageSubStorage(); 1470 1471 } 1472 catch ( uno::Exception& ) 1473 { 1474 // TODO/LATER: error handling 1475 bResult = sal_False; 1476 } 1477 1478 // the old SO6 format does not store graphical replacements 1479 if ( !_bOasisFormat && bResult ) 1480 { 1481 try 1482 { 1483 // the substorage still can not be locked by the embedded object container 1484 ::rtl::OUString aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) ); 1485 if ( _xStorage->hasByName( aObjReplElement ) && _xStorage->isStorageElement( aObjReplElement ) ) 1486 _xStorage->removeElement( aObjReplElement ); 1487 } 1488 catch ( uno::Exception& ) 1489 { 1490 // TODO/LATER: error handling; 1491 bResult = sal_False; 1492 } 1493 } 1494 return bResult; 1495 } 1496 // ----------------------------------------------------------------------------- 1497 sal_Bool EmbeddedObjectContainer::StoreChildren(sal_Bool _bOasisFormat,sal_Bool _bObjectsOnly) 1498 { 1499 sal_Bool bResult = sal_True; 1500 const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames(); 1501 const ::rtl::OUString* pIter = aNames.getConstArray(); 1502 const ::rtl::OUString* pEnd = pIter + aNames.getLength(); 1503 for(;pIter != pEnd;++pIter) 1504 { 1505 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter ); 1506 OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" ); 1507 if ( xObj.is() ) 1508 { 1509 sal_Int32 nCurState = xObj->getCurrentState(); 1510 if ( _bOasisFormat && nCurState != embed::EmbedStates::LOADED && nCurState != embed::EmbedStates::RUNNING ) 1511 { 1512 // means that the object is active 1513 // the image must be regenerated 1514 ::rtl::OUString aMediaType; 1515 1516 // TODO/LATER: another aspect could be used 1517 uno::Reference < io::XInputStream > xStream = 1518 GetGraphicReplacementStream( 1519 embed::Aspects::MSOLE_CONTENT, 1520 xObj, 1521 &aMediaType ); 1522 if ( xStream.is() ) 1523 { 1524 if ( !InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) ) 1525 InsertGraphicStream( xStream, *pIter, aMediaType ); 1526 } 1527 } 1528 1529 // TODO/LATER: currently the object by default does not cache replacement image 1530 // that means that if somebody loads SO7 document and store its objects using 1531 // this method the images might be lost. 1532 // Currently this method is only used on storing to alien formats, that means 1533 // that SO7 documents storing does not use it, and all other filters are 1534 // based on OASIS format. But if it changes the method must be fixed. The fix 1535 // must be done only on demand since it can affect performance. 1536 1537 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 1538 if ( xPersist.is() ) 1539 { 1540 try 1541 { 1542 // TODO/LATER: only storing if changed! 1543 //xPersist->storeOwn(); //commented, i120168 1544 1545 // begin:all charts will be persisted as xml format on disk when saving, which is time consuming. 1546 // '_bObjectsOnly' mean we are storing to alien formats. 1547 // 'isStorageElement' mean current object is NOT an MS OLE format. (may also include in future), i120168 1548 if (_bObjectsOnly && (nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING) 1549 && (pImpl->mxStorage->isStorageElement( *pIter ) )) 1550 { 1551 uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); 1552 if ( xModifiable.is() && xModifiable->isModified()) 1553 { 1554 xPersist->storeOwn(); 1555 } 1556 else 1557 { 1558 // do nothing. Embedded model is not modified, no need to persist. 1559 } 1560 } 1561 else // the embedded object is in active status, always store back it. 1562 { 1563 xPersist->storeOwn(); 1564 } 1565 // end i120168 1566 } 1567 catch( uno::Exception& ) 1568 { 1569 // TODO/LATER: error handling 1570 bResult = sal_False; 1571 break; 1572 } 1573 } 1574 1575 if ( !_bOasisFormat && !_bObjectsOnly ) 1576 { 1577 // copy replacement images for linked objects 1578 try 1579 { 1580 uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY ); 1581 if ( xLink.is() && xLink->isLink() ) 1582 { 1583 ::rtl::OUString aMediaType; 1584 uno::Reference < io::XInputStream > xInStream = GetGraphicStream( xObj, &aMediaType ); 1585 if ( xInStream.is() ) 1586 InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, *pIter ); 1587 } 1588 } 1589 catch( uno::Exception& ) 1590 { 1591 } 1592 } 1593 } 1594 } 1595 1596 if ( bResult && _bOasisFormat ) 1597 bResult = CommitImageSubStorage(); 1598 1599 if ( bResult && !_bObjectsOnly ) 1600 { 1601 try 1602 { 1603 ReleaseImageSubStorage(); 1604 ::rtl::OUString aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) ); 1605 if ( !_bOasisFormat && pImpl->mxStorage->hasByName( aObjReplElement ) && pImpl->mxStorage->isStorageElement( aObjReplElement ) ) 1606 pImpl->mxStorage->removeElement( aObjReplElement ); 1607 } 1608 catch( uno::Exception& ) 1609 { 1610 // TODO/LATER: error handling 1611 bResult = sal_False; 1612 } 1613 } 1614 return bResult; 1615 } 1616 // ----------------------------------------------------------------------------- 1617 uno::Reference< io::XInputStream > EmbeddedObjectContainer::GetGraphicReplacementStream( 1618 sal_Int64 nViewAspect, 1619 const uno::Reference< embed::XEmbeddedObject >& xObj, 1620 ::rtl::OUString* pMediaType ) 1621 { 1622 uno::Reference< io::XInputStream > xInStream; 1623 if ( xObj.is() ) 1624 { 1625 try 1626 { 1627 // retrieving of the visual representation can switch object to running state 1628 embed::VisualRepresentation aRep = xObj->getPreferredVisualRepresentation( nViewAspect ); 1629 if ( pMediaType ) 1630 *pMediaType = aRep.Flavor.MimeType; 1631 1632 uno::Sequence < sal_Int8 > aSeq; 1633 aRep.Data >>= aSeq; 1634 xInStream = new ::comphelper::SequenceInputStream( aSeq ); 1635 } 1636 catch ( uno::Exception& ) 1637 { 1638 } 1639 } 1640 1641 return xInStream; 1642 } 1643 // ----------------------------------------------------------------------------- 1644 sal_Bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed::XStorage >& _xStorage,bool _bClearModifedFlag) 1645 { 1646 sal_Bool bError = sal_False; 1647 const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames(); 1648 const ::rtl::OUString* pIter = aNames.getConstArray(); 1649 const ::rtl::OUString* pEnd = pIter + aNames.getLength(); 1650 for(;pIter != pEnd;++pIter) 1651 { 1652 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter ); 1653 OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" ); 1654 if ( xObj.is() ) 1655 { 1656 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 1657 if ( xPersist.is() ) 1658 { 1659 try 1660 { 1661 xPersist->setPersistentEntry( _xStorage, 1662 *pIter, 1663 embed::EntryInitModes::NO_INIT, 1664 uno::Sequence< beans::PropertyValue >(), 1665 uno::Sequence< beans::PropertyValue >() ); 1666 1667 } 1668 catch( uno::Exception& ) 1669 { 1670 // TODO/LATER: error handling 1671 bError = sal_True; 1672 break; 1673 } 1674 } 1675 if ( _bClearModifedFlag ) 1676 { 1677 // if this method is used as part of SaveCompleted the object must stay unmodified after execution 1678 try 1679 { 1680 uno::Reference< util::XModifiable > xModif( xObj->getComponent(), uno::UNO_QUERY_THROW ); 1681 if ( xModif->isModified() ) 1682 xModif->setModified( sal_False ); 1683 } 1684 catch( uno::Exception& ) 1685 { 1686 } 1687 } 1688 } 1689 } 1690 return bError; 1691 } 1692 1693 bool EmbeddedObjectContainer::getUserAllowsLinkUpdate() const 1694 { 1695 return pImpl->mbUserAllowsLinkUpdate; 1696 } 1697 1698 void EmbeddedObjectContainer::setUserAllowsLinkUpdate(bool bNew) 1699 { 1700 if(pImpl->mbUserAllowsLinkUpdate != bNew) 1701 { 1702 pImpl->mbUserAllowsLinkUpdate = bNew; 1703 } 1704 } 1705 1706 } 1707 1708 /* vim: set noet sw=4 ts=4: */ 1709