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