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