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