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