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_svx.hxx" 26 27 #include <stdio.h> 28 #include <com/sun/star/io/XStream.hpp> 29 #include <com/sun/star/embed/XTransactedObject.hpp> 30 #include <com/sun/star/embed/XEmbedObjectCreator.hpp> 31 #include <com/sun/star/embed/XEmbedObjectFactory.hpp> 32 #include <com/sun/star/embed/ElementModes.hpp> 33 #include <com/sun/star/embed/XEmbeddedObject.hpp> 34 #ifndef _COM_SUN_STAR_EMBED_XEMBED_PERSIST_HPP_ 35 #include <com/sun/star/embed/XEmbedPersist.hpp> 36 #endif 37 #include <com/sun/star/embed/EntryInitModes.hpp> 38 #include <com/sun/star/embed/EmbedStates.hpp> 39 #include <com/sun/star/embed/Aspects.hpp> 40 #include <com/sun/star/beans/XPropertySet.hpp> 41 #include <tools/debug.hxx> 42 #include <unotools/streamwrap.hxx> 43 #include <unotools/tempfile.hxx> 44 45 #include <svtools/embedhlp.hxx> 46 #include <unotools/ucbstreamhelper.hxx> 47 #include <comphelper/processfactory.hxx> 48 #include <comphelper/storagehelper.hxx> 49 #include <comphelper/embeddedobjectcontainer.hxx> 50 51 #ifndef _SO_CLSIDS_HXX 52 #include <sot/clsids.hxx> 53 #endif 54 #include <map> 55 #include "svx/xmleohlp.hxx" 56 57 // ----------- 58 // - Defines - 59 // ----------- 60 61 using namespace ::osl; 62 using namespace ::cppu; 63 using namespace ::utl; 64 using namespace ::com::sun::star; 65 using namespace ::com::sun::star::document; 66 using namespace ::com::sun::star::uno; 67 using namespace ::com::sun::star::container; 68 using namespace ::com::sun::star::io; 69 using namespace ::com::sun::star::lang; 70 71 #define XML_CONTAINERSTORAGE_NAME_60 "Pictures" 72 #define XML_CONTAINERSTORAGE_NAME "ObjectReplacements" 73 #define XML_EMBEDDEDOBJECT_URL_BASE "vnd.sun.star.EmbeddedObject:" 74 #define XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE "vnd.sun.star.GraphicObject:" 75 76 // ----------------------------------------------------------------------------- 77 78 // ----------------------------------------------------------------------------- 79 80 class OutputStorageWrapper_Impl : public ::cppu::WeakImplHelper1<XOutputStream> 81 { 82 ::osl::Mutex maMutex; 83 Reference < XOutputStream > xOut; 84 TempFile aTempFile; 85 sal_Bool bStreamClosed : 1; 86 SvStream* pStream; 87 88 public: 89 OutputStorageWrapper_Impl(); 90 virtual ~OutputStorageWrapper_Impl(); 91 92 // stario::XOutputStream 93 virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData); 94 virtual void SAL_CALL flush(); 95 virtual void SAL_CALL closeOutput(); 96 97 SvStream* GetStream(); 98 }; 99 100 OutputStorageWrapper_Impl::OutputStorageWrapper_Impl() 101 : bStreamClosed( sal_False ) 102 , pStream(0) 103 { 104 aTempFile.EnableKillingFile(); 105 pStream = aTempFile.GetStream( STREAM_READWRITE ); 106 xOut = new OOutputStreamWrapper( *pStream ); 107 } 108 109 OutputStorageWrapper_Impl::~OutputStorageWrapper_Impl() 110 { 111 } 112 113 SvStream *OutputStorageWrapper_Impl::GetStream() 114 { 115 if( bStreamClosed ) 116 return pStream; 117 return NULL; 118 } 119 120 void SAL_CALL OutputStorageWrapper_Impl::writeBytes( 121 const Sequence< sal_Int8 >& aData) 122 { 123 MutexGuard aGuard( maMutex ); 124 xOut->writeBytes( aData ); 125 } 126 127 void SAL_CALL OutputStorageWrapper_Impl::flush() 128 { 129 MutexGuard aGuard( maMutex ); 130 xOut->flush(); 131 } 132 133 void SAL_CALL OutputStorageWrapper_Impl::closeOutput() 134 { 135 MutexGuard aGuard( maMutex ); 136 xOut->closeOutput(); 137 bStreamClosed = sal_True; 138 } 139 140 // ----------------------------------------------------------------------------- 141 142 struct OUStringLess 143 { 144 bool operator() ( const ::rtl::OUString& r1, const ::rtl::OUString& r2 ) const 145 { 146 return (r1 < r2) != sal_False; 147 } 148 }; 149 150 // ----------------------------------------------------------------------------- 151 152 // ----------------------------- 153 // - SvXMLEmbeddedObjectHelper - 154 // ----------------------------- 155 DBG_NAME(SvXMLEmbeddedObjectHelper) 156 SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper() : 157 WeakComponentImplHelper2< XEmbeddedObjectResolver, XNameAccess >( maMutex ), 158 maReplacementGraphicsContainerStorageName( RTL_CONSTASCII_USTRINGPARAM(XML_CONTAINERSTORAGE_NAME) ), 159 maReplacementGraphicsContainerStorageName60( RTL_CONSTASCII_USTRINGPARAM(XML_CONTAINERSTORAGE_NAME_60) ), 160 mpDocPersist( 0 ), 161 meCreateMode( EMBEDDEDOBJECTHELPER_MODE_READ ), 162 mpStreamMap( 0 ) 163 { 164 DBG_CTOR(SvXMLEmbeddedObjectHelper,NULL); 165 } 166 167 SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper( ::comphelper::IEmbeddedHelper& rDocPersist, SvXMLEmbeddedObjectHelperMode eCreateMode ) : 168 WeakComponentImplHelper2< XEmbeddedObjectResolver, XNameAccess >( maMutex ), 169 maReplacementGraphicsContainerStorageName( RTL_CONSTASCII_USTRINGPARAM(XML_CONTAINERSTORAGE_NAME) ), 170 maReplacementGraphicsContainerStorageName60( RTL_CONSTASCII_USTRINGPARAM(XML_CONTAINERSTORAGE_NAME_60) ), 171 mpDocPersist( 0 ), 172 meCreateMode( EMBEDDEDOBJECTHELPER_MODE_READ ), 173 mpStreamMap( 0 ) 174 { 175 DBG_CTOR(SvXMLEmbeddedObjectHelper,NULL); 176 Init( 0, rDocPersist, eCreateMode ); 177 } 178 179 180 // ----------------------------------------------------------------------------- 181 182 SvXMLEmbeddedObjectHelper::~SvXMLEmbeddedObjectHelper() 183 { 184 DBG_DTOR(SvXMLEmbeddedObjectHelper,NULL); 185 if( mpStreamMap ) 186 { 187 SvXMLEmbeddedObjectHelper_Impl::iterator aIter = mpStreamMap->begin(); 188 SvXMLEmbeddedObjectHelper_Impl::iterator aEnd = mpStreamMap->end(); 189 for( ; aIter != aEnd; aIter++ ) 190 { 191 if( aIter->second ) 192 { 193 aIter->second->release(); 194 aIter->second = 0; 195 } 196 } 197 } 198 } 199 200 // ----------------------------------------------------------------------------- 201 202 void SAL_CALL SvXMLEmbeddedObjectHelper::disposing() 203 { 204 Flush(); 205 } 206 207 // ----------------------------------------------------------------------------- 208 209 sal_Bool SvXMLEmbeddedObjectHelper::ImplGetStorageNames( 210 const ::rtl::OUString& rURLStr, 211 ::rtl::OUString& rContainerStorageName, 212 ::rtl::OUString& rObjectStorageName, 213 sal_Bool bInternalToExternal, 214 sal_Bool *pGraphicRepl, 215 sal_Bool *pOasisFormat ) const 216 { 217 // internal URL: vnd.sun.star.EmbeddedObject:<object-name> 218 // or: vnd.sun.star.EmbeddedObject:<path>/<object-name> 219 // internal replacement images: 220 // vnd.sun.star.EmbeddedObjectGraphic:<object-name> 221 // or: vnd.sun.star.EmbeddedObjectGraphic:<path>/<object-name> 222 // external URL: ./<path>/<object-name> 223 // or: <path>/<object-name> 224 // or: <object-name> 225 // currently, path may only consist of a single directory name 226 // it is also possible to have additional arguments at the end of URL: <main URL>[?<name>=<value>[,<name>=<value>]*] 227 228 if( pGraphicRepl ) 229 *pGraphicRepl = sal_False; 230 231 if( pOasisFormat ) 232 *pOasisFormat = sal_True; // the default value 233 234 if( !rURLStr.getLength() ) 235 return sal_False; 236 237 // get rid of arguments 238 sal_Int32 nPos = rURLStr.indexOf( '?' ); 239 ::rtl::OUString aURLNoPar; 240 if ( nPos == -1 ) 241 aURLNoPar = rURLStr; 242 else 243 { 244 aURLNoPar = rURLStr.copy( 0, nPos ); 245 246 // check the arguments 247 nPos++; 248 while( nPos >= 0 && nPos < rURLStr.getLength() ) 249 { 250 ::rtl::OUString aToken = rURLStr.getToken( 0, ',', nPos ); 251 if ( aToken.equalsIgnoreAsciiCase( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "oasis=false" ) ) ) ) 252 { 253 if ( pOasisFormat ) 254 *pOasisFormat = sal_False; 255 break; 256 } 257 else 258 { 259 DBG_ASSERT( sal_False, "invalid arguments was found in URL!" ); 260 } 261 } 262 } 263 264 if( bInternalToExternal ) 265 { 266 nPos = aURLNoPar.indexOf( ':' ); 267 if( -1 == nPos ) 268 return sal_False; 269 sal_Bool bObjUrl = 270 0 == aURLNoPar.compareToAscii( XML_EMBEDDEDOBJECT_URL_BASE, 271 sizeof( XML_EMBEDDEDOBJECT_URL_BASE ) -1 ); 272 sal_Bool bGrUrl = !bObjUrl && 273 0 == aURLNoPar.compareToAscii( XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE, 274 sizeof( XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE ) -1 ); 275 if( !(bObjUrl || bGrUrl) ) 276 return sal_False; 277 278 sal_Int32 nPathStart = nPos + 1; 279 nPos = aURLNoPar.lastIndexOf( '/' ); 280 if( -1 == nPos ) 281 { 282 rContainerStorageName = ::rtl::OUString(); 283 rObjectStorageName = aURLNoPar.copy( nPathStart ); 284 } 285 else if( nPos > nPathStart ) 286 { 287 rContainerStorageName = aURLNoPar.copy( nPathStart, nPos-nPathStart); 288 rObjectStorageName = aURLNoPar.copy( nPos+1 ); 289 } 290 else 291 return sal_False; 292 293 if( bGrUrl ) 294 { 295 sal_Bool bOASIS = mxRootStorage.is() && 296 ( SotStorage::GetVersion( mxRootStorage ) > SOFFICE_FILEFORMAT_60 ); 297 rContainerStorageName = bOASIS 298 ? maReplacementGraphicsContainerStorageName 299 : maReplacementGraphicsContainerStorageName60; 300 301 if( pGraphicRepl ) 302 *pGraphicRepl = sal_True; 303 } 304 305 306 } 307 else 308 { 309 DBG_ASSERT( '#' != aURLNoPar[0], "invalid object URL" ); 310 311 sal_Int32 _nPos = aURLNoPar.lastIndexOf( '/' ); 312 if( -1 == _nPos ) 313 { 314 rContainerStorageName = ::rtl::OUString(); 315 rObjectStorageName = aURLNoPar; 316 } 317 else 318 { 319 //eliminate 'superfluous' slashes at start and end 320 //#i103076# load objects with all allowed xlink:href syntaxes 321 { 322 //eliminate './' at start 323 sal_Int32 nStart = 0; 324 sal_Int32 nCount = aURLNoPar.getLength(); 325 if( 0 == aURLNoPar.compareToAscii( "./", 2 ) ) 326 { 327 nStart = 2; 328 nCount -= 2; 329 } 330 331 //eliminate '/' at end 332 sal_Int32 nEnd = aURLNoPar.lastIndexOf( '/' ); 333 if( nEnd == aURLNoPar.getLength()-1 && nEnd != (nStart-1) ) 334 nCount--; 335 336 aURLNoPar = aURLNoPar.copy( nStart, nCount ); 337 } 338 339 _nPos = aURLNoPar.lastIndexOf( '/' ); 340 if( _nPos >= 0 ) 341 rContainerStorageName = aURLNoPar.copy( 0, _nPos ); 342 rObjectStorageName = aURLNoPar.copy( _nPos+1 ); 343 } 344 } 345 346 if( -1 != rContainerStorageName.indexOf( '/' ) ) 347 { 348 DBG_ERROR( "SvXMLEmbeddedObjectHelper: invalid path name" ); 349 return sal_False; 350 } 351 352 return sal_True; 353 } 354 355 356 // ----------------------------------------------------------------------------- 357 358 uno::Reference < embed::XStorage > SvXMLEmbeddedObjectHelper::ImplGetContainerStorage( 359 const ::rtl::OUString& rStorageName ) 360 { 361 DBG_ASSERT( -1 == rStorageName.indexOf( '/' ) && 362 -1 == rStorageName.indexOf( '\\' ), 363 "nested embedded storages aren't supported" ); 364 if( !mxContainerStorage.is() || 365 ( rStorageName != maCurContainerStorageName ) ) 366 { 367 if( mxContainerStorage.is() && 368 maCurContainerStorageName.getLength() > 0 && 369 EMBEDDEDOBJECTHELPER_MODE_WRITE == meCreateMode ) 370 { 371 uno::Reference < embed::XTransactedObject > xTrans( mxContainerStorage, uno::UNO_QUERY ); 372 if ( xTrans.is() ) 373 xTrans->commit(); 374 } 375 376 if( rStorageName.getLength() > 0 && mxRootStorage.is() ) 377 { 378 sal_Int32 nMode = EMBEDDEDOBJECTHELPER_MODE_WRITE == meCreateMode 379 ? ::embed::ElementModes::READWRITE 380 : ::embed::ElementModes::READ; 381 mxContainerStorage = mxRootStorage->openStorageElement( rStorageName, 382 nMode ); 383 } 384 else 385 { 386 mxContainerStorage = mxRootStorage; 387 } 388 maCurContainerStorageName = rStorageName; 389 } 390 391 return mxContainerStorage; 392 } 393 394 // ----------------------------------------------------------------------------- 395 396 sal_Bool SvXMLEmbeddedObjectHelper::ImplReadObject( 397 const ::rtl::OUString& rContainerStorageName, 398 ::rtl::OUString& rObjName, 399 const SvGlobalName *pClassId, 400 SvStream* pTemp ) 401 { 402 (void)pClassId; 403 404 uno::Reference < embed::XStorage > xDocStor( mpDocPersist->getStorage() ); 405 uno::Reference < embed::XStorage > xCntnrStor( ImplGetContainerStorage( rContainerStorageName ) ); 406 407 if( !xCntnrStor.is() && !pTemp ) 408 return sal_False; 409 410 String aSrcObjName( rObjName ); 411 comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer(); 412 413 // Is the object name unique? 414 // if the object is already instantiated by GetEmbeddedObject 415 // that means that the duplication is being loaded 416 sal_Bool bDuplicate = rContainer.HasInstantiatedEmbeddedObject( rObjName ); 417 DBG_ASSERT( !bDuplicate, "An object in the document is referenced twice!" ); 418 419 if( xDocStor != xCntnrStor || pTemp || bDuplicate ) 420 { 421 // TODO/LATER: make this altogether a method in the EmbeddedObjectContainer 422 423 // create a unique name for the duplicate object 424 if( bDuplicate ) 425 rObjName = rContainer.CreateUniqueObjectName(); 426 427 if( pTemp ) 428 { 429 try 430 { 431 pTemp->Seek( 0 ); 432 uno::Reference < io::XStream > xStm = xDocStor->openStreamElement( rObjName, 433 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); 434 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStm ); 435 *pTemp >> *pStream; 436 delete pStream; 437 438 // TODO/LATER: what to do when other types of objects are based on substream persistence? 439 // This is an ole object 440 uno::Reference< beans::XPropertySet > xProps( xStm, uno::UNO_QUERY_THROW ); 441 xProps->setPropertyValue( 442 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), 443 uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) ); 444 445 xStm->getOutputStream()->closeOutput(); 446 } 447 catch ( uno::Exception& ) 448 { 449 return sal_False; 450 } 451 } 452 else 453 { 454 try 455 { 456 xCntnrStor->copyElementTo( aSrcObjName, xDocStor, rObjName ); 457 } 458 catch ( uno::Exception& ) 459 { 460 return sal_False; 461 } 462 } 463 } 464 465 // make object known to the container 466 // TODO/LATER: could be done a little bit more efficient! 467 ::rtl::OUString aName( rObjName ); 468 469 // TODO/LATER: The provided pClassId is ignored for now. 470 // The stream contains OLE storage internally and this storage already has a class id specifying the 471 // server that was used to create the object. pClassId could be used to specify the server that should 472 // be used for the next opening, but this information seems to be out of the file format responsibility 473 // area. 474 rContainer.GetEmbeddedObject( aName ); 475 476 return sal_True; 477 } 478 479 // ----------------------------------------------------------------------------- 480 481 ::rtl::OUString SvXMLEmbeddedObjectHelper::ImplInsertEmbeddedObjectURL( 482 const ::rtl::OUString& rURLStr ) 483 { 484 ::rtl::OUString sRetURL; 485 486 ::rtl::OUString aContainerStorageName, aObjectStorageName; 487 if( !ImplGetStorageNames( rURLStr, aContainerStorageName, 488 aObjectStorageName, 489 EMBEDDEDOBJECTHELPER_MODE_WRITE == meCreateMode ) ) 490 return sRetURL; 491 492 if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode ) 493 { 494 OutputStorageWrapper_Impl *pOut = 0; 495 SvXMLEmbeddedObjectHelper_Impl::iterator aIter; 496 497 if( mpStreamMap ) 498 { 499 aIter = mpStreamMap->find( rURLStr ); 500 if( aIter != mpStreamMap->end() && aIter->second ) 501 pOut = aIter->second; 502 } 503 504 SvGlobalName aClassId, *pClassId = 0; 505 sal_Int32 nPos = aObjectStorageName.lastIndexOf( '!' ); 506 if( -1 != nPos && aClassId.MakeId( aObjectStorageName.copy( nPos+1 ) ) ) 507 { 508 aObjectStorageName = aObjectStorageName.copy( 0, nPos ); 509 pClassId = &aClassId; 510 } 511 512 ImplReadObject( aContainerStorageName, aObjectStorageName, pClassId, pOut ? pOut->GetStream() : 0 ); 513 sRetURL = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(XML_EMBEDDEDOBJECT_URL_BASE) ); 514 sRetURL += aObjectStorageName; 515 516 if( pOut ) 517 { 518 mpStreamMap->erase( aIter ); 519 pOut->release(); 520 } 521 } 522 else 523 { 524 // Objects are written using ::comphelper::IEmbeddedHelper::SaveAs 525 sRetURL = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("./") ); 526 if( aContainerStorageName.getLength() ) 527 { 528 sRetURL += aContainerStorageName; 529 sRetURL += ::rtl::OUString( '/' ); 530 } 531 sRetURL += aObjectStorageName; 532 } 533 534 return sRetURL; 535 } 536 537 // ----------------------------------------------------------------------------- 538 539 uno::Reference< io::XInputStream > SvXMLEmbeddedObjectHelper::ImplGetReplacementImage( 540 const uno::Reference< embed::XEmbeddedObject >& xObj ) 541 { 542 uno::Reference< io::XInputStream > xStream; 543 544 if( xObj.is() ) 545 { 546 try 547 { 548 sal_Bool bSwitchBackToLoaded = sal_False; 549 sal_Int32 nCurState = xObj->getCurrentState(); 550 if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING ) 551 { 552 // means that the object is not active 553 // copy replacement image from old to new container 554 ::rtl::OUString aMediaType; 555 xStream = mpDocPersist->getEmbeddedObjectContainer().GetGraphicStream( xObj, &aMediaType ); 556 } 557 558 if ( !xStream.is() ) 559 { 560 // the image must be regenerated 561 // TODO/LATER: another aspect could be used 562 if ( nCurState == embed::EmbedStates::LOADED ) 563 bSwitchBackToLoaded = sal_True; 564 565 ::rtl::OUString aMediaType; 566 xStream = svt::EmbeddedObjectRef::GetGraphicReplacementStream( 567 embed::Aspects::MSOLE_CONTENT, 568 xObj, 569 &aMediaType ); 570 } 571 572 if ( bSwitchBackToLoaded ) 573 // switch back to loaded state; that way we have a minimum cache confusion 574 xObj->changeState( embed::EmbedStates::LOADED ); 575 } 576 catch( uno::Exception& ) 577 {} 578 } 579 580 return xStream; 581 } 582 583 // ----------------------------------------------------------------------------- 584 585 void SvXMLEmbeddedObjectHelper::Init( 586 const uno::Reference < embed::XStorage >& rRootStorage, 587 ::comphelper::IEmbeddedHelper& rPersist, 588 SvXMLEmbeddedObjectHelperMode eCreateMode ) 589 { 590 mxRootStorage = rRootStorage; 591 mpDocPersist = &rPersist; 592 meCreateMode = eCreateMode; 593 } 594 595 // ----------------------------------------------------------------------------- 596 597 SvXMLEmbeddedObjectHelper* SvXMLEmbeddedObjectHelper::Create( 598 const uno::Reference < embed::XStorage >& rRootStorage, 599 ::comphelper::IEmbeddedHelper& rDocPersist, 600 SvXMLEmbeddedObjectHelperMode eCreateMode, 601 sal_Bool bDirect ) 602 { 603 (void)bDirect; 604 605 SvXMLEmbeddedObjectHelper* pThis = new SvXMLEmbeddedObjectHelper; 606 607 pThis->acquire(); 608 pThis->Init( rRootStorage, rDocPersist, eCreateMode ); 609 610 return pThis; 611 } 612 613 SvXMLEmbeddedObjectHelper* SvXMLEmbeddedObjectHelper::Create( 614 ::comphelper::IEmbeddedHelper& rDocPersist, 615 SvXMLEmbeddedObjectHelperMode eCreateMode ) 616 { 617 SvXMLEmbeddedObjectHelper* pThis = new SvXMLEmbeddedObjectHelper; 618 619 pThis->acquire(); 620 pThis->Init( 0, rDocPersist, eCreateMode ); 621 622 return pThis; 623 } 624 625 // ----------------------------------------------------------------------------- 626 627 void SvXMLEmbeddedObjectHelper::Destroy( 628 SvXMLEmbeddedObjectHelper* pSvXMLEmbeddedObjectHelper ) 629 { 630 if( pSvXMLEmbeddedObjectHelper ) 631 { 632 pSvXMLEmbeddedObjectHelper->dispose(); 633 pSvXMLEmbeddedObjectHelper->release(); 634 } 635 } 636 637 // ----------------------------------------------------------------------------- 638 639 void SvXMLEmbeddedObjectHelper::Flush() 640 { 641 if( mxTempStorage.is() ) 642 { 643 Reference < XComponent > xComp( mxTempStorage, UNO_QUERY ); 644 xComp->dispose(); 645 } 646 } 647 648 // XGraphicObjectResolver: alien objects! 649 ::rtl::OUString SAL_CALL SvXMLEmbeddedObjectHelper::resolveEmbeddedObjectURL( const ::rtl::OUString& aURL ) 650 { 651 MutexGuard aGuard( maMutex ); 652 653 return ImplInsertEmbeddedObjectURL( aURL ); 654 } 655 656 // XNameAccess: alien objects! 657 Any SAL_CALL SvXMLEmbeddedObjectHelper::getByName( 658 const ::rtl::OUString& rURLStr ) 659 { 660 MutexGuard aGuard( maMutex ); 661 Any aRet; 662 if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode ) 663 { 664 Reference < XOutputStream > xStrm; 665 if( mpStreamMap ) 666 { 667 SvXMLEmbeddedObjectHelper_Impl::iterator aIter = 668 mpStreamMap->find( rURLStr ); 669 if( aIter != mpStreamMap->end() && aIter->second ) 670 xStrm = aIter->second; 671 } 672 if( !xStrm.is() ) 673 { 674 OutputStorageWrapper_Impl *pOut = new OutputStorageWrapper_Impl; 675 pOut->acquire(); 676 if( !mpStreamMap ) 677 mpStreamMap = new SvXMLEmbeddedObjectHelper_Impl; 678 (*mpStreamMap)[rURLStr] = pOut; 679 xStrm = pOut; 680 } 681 682 aRet <<= xStrm; 683 } 684 else 685 { 686 sal_Bool bGraphicRepl = sal_False; 687 sal_Bool bOasisFormat = sal_True; 688 Reference < XInputStream > xStrm; 689 ::rtl::OUString aContainerStorageName, aObjectStorageName; 690 if( ImplGetStorageNames( rURLStr, aContainerStorageName, 691 aObjectStorageName, 692 sal_True, 693 &bGraphicRepl, 694 &bOasisFormat ) ) 695 { 696 try 697 { 698 comphelper::EmbeddedObjectContainer& rContainer = 699 mpDocPersist->getEmbeddedObjectContainer(); 700 701 Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( aObjectStorageName ); 702 DBG_ASSERT( xObj.is(), "Didn't get object" ); 703 704 if( xObj.is() ) 705 { 706 if( bGraphicRepl ) 707 { 708 xStrm = ImplGetReplacementImage( xObj ); 709 } 710 else 711 { 712 Reference < embed::XEmbedPersist > xPersist( xObj, UNO_QUERY ); 713 if( xPersist.is() ) 714 { 715 if( !mxTempStorage.is() ) 716 mxTempStorage = 717 comphelper::OStorageHelper::GetTemporaryStorage(); 718 Sequence < beans::PropertyValue > aDummy( 0 ), aEmbDescr( 1 ); 719 aEmbDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StoreVisualReplacement" ) ); 720 aEmbDescr[0].Value <<= (sal_Bool)(!bOasisFormat); 721 if ( !bOasisFormat ) 722 { 723 ::rtl::OUString aMimeType; 724 uno::Reference< io::XInputStream > xGrInStream = ImplGetReplacementImage( xObj ); 725 if ( xGrInStream.is() ) 726 { 727 aEmbDescr.realloc( 2 ); 728 aEmbDescr[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualReplacement" ) ); 729 aEmbDescr[1].Value <<= xGrInStream; 730 } 731 } 732 733 xPersist->storeToEntry( mxTempStorage, aObjectStorageName, 734 aDummy, aEmbDescr ); 735 Reference < io::XStream > xStream = 736 mxTempStorage->openStreamElement( 737 aObjectStorageName, 738 embed::ElementModes::READ); 739 if( xStream.is() ) 740 xStrm = xStream->getInputStream(); 741 } 742 } 743 } 744 } 745 catch ( uno::Exception& ) 746 { 747 } 748 } 749 750 aRet <<= xStrm; 751 } 752 753 return aRet; 754 } 755 756 Sequence< ::rtl::OUString > SAL_CALL SvXMLEmbeddedObjectHelper::getElementNames() 757 { 758 MutexGuard aGuard( maMutex ); 759 return Sequence< ::rtl::OUString >(0); 760 } 761 762 sal_Bool SAL_CALL SvXMLEmbeddedObjectHelper::hasByName( const ::rtl::OUString& rURLStr ) 763 { 764 MutexGuard aGuard( maMutex ); 765 if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode ) 766 { 767 return sal_True; 768 } 769 else 770 { 771 ::rtl::OUString aContainerStorageName, aObjectStorageName; 772 if( !ImplGetStorageNames( rURLStr, aContainerStorageName, 773 aObjectStorageName, 774 sal_True ) ) 775 return sal_False; 776 777 comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer(); 778 return aObjectStorageName.getLength() > 0 && 779 rContainer.HasEmbeddedObject( aObjectStorageName ); 780 } 781 } 782 783 // XNameAccess 784 Type SAL_CALL SvXMLEmbeddedObjectHelper::getElementType() 785 { 786 MutexGuard aGuard( maMutex ); 787 if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode ) 788 return ::getCppuType((const Reference<XOutputStream>*)0); 789 else 790 return ::getCppuType((const Reference<XInputStream>*)0); 791 } 792 793 sal_Bool SAL_CALL SvXMLEmbeddedObjectHelper::hasElements() 794 { 795 MutexGuard aGuard( maMutex ); 796 if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode ) 797 { 798 return sal_True; 799 } 800 else 801 { 802 comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer(); 803 return rContainer.HasEmbeddedObjects(); 804 } 805 } 806