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