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_embeddedobj.hxx" 30 31 #include <oleembobj.hxx> 32 #include <com/sun/star/embed/EmbedStates.hpp> 33 #include <com/sun/star/embed/EmbedVerbs.hpp> 34 #include <com/sun/star/embed/EntryInitModes.hpp> 35 #include <com/sun/star/embed/XStorage.hpp> 36 #include <com/sun/star/embed/XTransactedObject.hpp> 37 #include <com/sun/star/embed/ElementModes.hpp> 38 #include <com/sun/star/embed/EmbedUpdateModes.hpp> 39 #include <com/sun/star/embed/Aspects.hpp> 40 #include <com/sun/star/embed/XOptimizedStorage.hpp> 41 #include <com/sun/star/lang/XComponent.hpp> 42 #include <com/sun/star/lang/DisposedException.hpp> 43 #include <com/sun/star/container/XNameAccess.hpp> 44 #include <com/sun/star/container/XNameContainer.hpp> 45 #include <com/sun/star/io/XSeekable.hpp> 46 #include <com/sun/star/io/XTruncate.hpp> 47 #include <com/sun/star/beans/XPropertySet.hpp> 48 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 49 50 #include <rtl/logfile.hxx> 51 52 #include <comphelper/storagehelper.hxx> 53 #include <comphelper/mimeconfighelper.hxx> 54 #include <comphelper/classids.hxx> 55 56 57 #include <olecomponent.hxx> 58 #include <closepreventer.hxx> 59 60 using namespace ::com::sun::star; 61 using namespace ::comphelper; 62 63 //------------------------------------------------------------------------- 64 sal_Bool KillFile_Impl( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 65 { 66 if ( !xFactory.is() ) 67 return sal_False; 68 69 sal_Bool bRet = sal_False; 70 71 try 72 { 73 uno::Reference < ucb::XSimpleFileAccess > xAccess( 74 xFactory->createInstance ( 75 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 76 uno::UNO_QUERY ); 77 78 if ( xAccess.is() ) 79 { 80 xAccess->kill( aURL ); 81 bRet = sal_True; 82 } 83 } 84 catch( uno::Exception& ) 85 { 86 } 87 88 return bRet; 89 } 90 91 //---------------------------------------------- 92 ::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 93 { 94 OSL_ENSURE( xFactory.is(), "No factory is provided!\n" ); 95 96 ::rtl::OUString aResult; 97 98 uno::Reference < beans::XPropertySet > xTempFile( 99 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 100 uno::UNO_QUERY ); 101 102 if ( !xTempFile.is() ) 103 throw uno::RuntimeException(); // TODO 104 105 try { 106 xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) ); 107 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ); 108 aUrl >>= aResult; 109 } 110 catch ( uno::Exception& ) 111 { 112 } 113 114 if ( !aResult.getLength() ) 115 throw uno::RuntimeException(); // TODO: can not create tempfile 116 117 return aResult; 118 } 119 120 //----------------------------------------------- 121 ::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream, 122 const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 123 throw ( io::IOException, 124 uno::RuntimeException ) 125 { 126 OSL_ENSURE( xInStream.is() && xFactory.is(), "Wrong parameters are provided!\n" ); 127 128 ::rtl::OUString aResult = GetNewTempFileURL_Impl( xFactory ); 129 130 if ( aResult.getLength() ) 131 { 132 try { 133 uno::Reference < ucb::XSimpleFileAccess > xTempAccess( 134 xFactory->createInstance ( 135 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 136 uno::UNO_QUERY ); 137 138 if ( !xTempAccess.is() ) 139 throw uno::RuntimeException(); // TODO: 140 141 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aResult ); 142 if ( xTempOutStream.is() ) 143 { 144 // copy stream contents to the file 145 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream ); 146 xTempOutStream->closeOutput(); 147 xTempOutStream = uno::Reference< io::XOutputStream >(); 148 } 149 else 150 throw io::IOException(); // TODO: 151 } 152 catch( packages::WrongPasswordException& ) 153 { 154 KillFile_Impl( aResult, xFactory ); 155 throw io::IOException(); //TODO: 156 } 157 catch( io::IOException& ) 158 { 159 KillFile_Impl( aResult, xFactory ); 160 throw; 161 } 162 catch( uno::RuntimeException& ) 163 { 164 KillFile_Impl( aResult, xFactory ); 165 throw; 166 } 167 catch( uno::Exception& ) 168 { 169 KillFile_Impl( aResult, xFactory ); 170 aResult = ::rtl::OUString(); 171 } 172 } 173 174 return aResult; 175 } 176 #ifdef WNT 177 ::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< embed::XOptimizedStorage >& xParentStorage, const ::rtl::OUString& aEntryName, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 178 throw( io::IOException, uno::RuntimeException ) 179 { 180 ::rtl::OUString aResult; 181 182 try 183 { 184 uno::Reference < beans::XPropertySet > xTempFile( 185 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 186 uno::UNO_QUERY ); 187 uno::Reference < io::XStream > xTempStream( xTempFile, uno::UNO_QUERY_THROW ); 188 189 xParentStorage->copyStreamElementData( aEntryName, xTempStream ); 190 191 xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) ); 192 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ); 193 aUrl >>= aResult; 194 } 195 catch( uno::RuntimeException& ) 196 { 197 throw; 198 } 199 catch( uno::Exception& ) 200 { 201 } 202 203 if ( !aResult.getLength() ) 204 throw io::IOException(); 205 206 return aResult; 207 } 208 209 //------------------------------------------------------ 210 void SetStreamMediaType_Impl( const uno::Reference< io::XStream >& xStream, const ::rtl::OUString& aMediaType ) 211 { 212 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY ); 213 if ( !xPropSet.is() ) 214 throw uno::RuntimeException(); // TODO: all the storage streams must support XPropertySet 215 216 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ), uno::makeAny( aMediaType ) ); 217 } 218 #endif 219 //------------------------------------------------------ 220 void LetCommonStoragePassBeUsed_Impl( const uno::Reference< io::XStream >& xStream ) 221 { 222 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY ); 223 if ( !xPropSet.is() ) 224 throw uno::RuntimeException(); // Only StorageStreams must be provided here, they must implement the interface 225 226 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ), 227 uno::makeAny( (sal_Bool)sal_True ) ); 228 } 229 #ifdef WNT 230 //------------------------------------------------------ 231 void VerbExecutionController::StartControlExecution() 232 { 233 osl::MutexGuard aGuard( m_aVerbExecutionMutex ); 234 235 // the class is used to detect STAMPIT object, that can never be active 236 if ( !m_bVerbExecutionInProgress && !m_bWasEverActive ) 237 { 238 m_bVerbExecutionInProgress = sal_True; 239 m_nVerbExecutionThreadIdentifier = osl_getThreadIdentifier( NULL ); 240 m_bChangedOnVerbExecution = sal_False; 241 } 242 } 243 244 //------------------------------------------------------ 245 sal_Bool VerbExecutionController::EndControlExecution_WasModified() 246 { 247 osl::MutexGuard aGuard( m_aVerbExecutionMutex ); 248 249 sal_Bool bResult = sal_False; 250 if ( m_bVerbExecutionInProgress && m_nVerbExecutionThreadIdentifier == osl_getThreadIdentifier( NULL ) ) 251 { 252 bResult = m_bChangedOnVerbExecution; 253 m_bVerbExecutionInProgress = sal_False; 254 } 255 256 return bResult; 257 } 258 259 //------------------------------------------------------ 260 void VerbExecutionController::ModificationNotificationIsDone() 261 { 262 osl::MutexGuard aGuard( m_aVerbExecutionMutex ); 263 264 if ( m_bVerbExecutionInProgress && osl_getThreadIdentifier( NULL ) == m_nVerbExecutionThreadIdentifier ) 265 m_bChangedOnVerbExecution = sal_True; 266 } 267 #endif 268 //----------------------------------------------- 269 void VerbExecutionController::LockNotification() 270 { 271 osl::MutexGuard aGuard( m_aVerbExecutionMutex ); 272 if ( m_nNotificationLock < SAL_MAX_INT32 ) 273 m_nNotificationLock++; 274 } 275 276 //----------------------------------------------- 277 void VerbExecutionController::UnlockNotification() 278 { 279 osl::MutexGuard aGuard( m_aVerbExecutionMutex ); 280 if ( m_nNotificationLock > 0 ) 281 m_nNotificationLock--; 282 } 283 284 //----------------------------------------------- 285 uno::Reference< io::XStream > OleEmbeddedObject::GetNewFilledTempStream_Impl( const uno::Reference< io::XInputStream >& xInStream ) 286 throw( io::IOException ) 287 { 288 OSL_ENSURE( xInStream.is(), "Wrong parameter is provided!\n" ); 289 290 uno::Reference < io::XStream > xTempFile( 291 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 292 uno::UNO_QUERY_THROW ); 293 294 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream(); 295 if ( xTempOutStream.is() ) 296 { 297 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream ); 298 xTempOutStream->flush(); 299 } 300 else 301 throw io::IOException(); // TODO: 302 303 return xTempFile; 304 } 305 306 //------------------------------------------------------ 307 uno::Reference< io::XStream > OleEmbeddedObject::TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream ) 308 throw ( uno::Exception ) 309 { 310 // TODO/LATER: Actually this should be done by a centralized component ( may be a graphical filter ) 311 if ( !m_xFactory.is() ) 312 throw uno::RuntimeException(); 313 314 uno::Reference< io::XInputStream > xInStream = xStream->getInputStream(); 315 if ( !xInStream.is() ) 316 throw uno::RuntimeException(); 317 318 uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW ); 319 xSeek->seek( 0 ); 320 321 uno::Sequence< sal_Int8 > aData( 8 ); 322 sal_Int32 nRead = xInStream->readBytes( aData, 8 ); 323 xSeek->seek( 0 ); 324 325 if ( ( nRead >= 2 && aData[0] == 'B' && aData[1] == 'M' ) 326 || ( nRead >= 4 && aData[0] == 1 && aData[1] == 0 && aData[2] == 9 && aData[3] == 0 ) ) 327 { 328 // it should be a bitmap or a Metafile 329 return xStream; 330 } 331 332 // sal_Bool bSetSizeToRepl = sal_False; 333 // awt::Size aSizeToSet; 334 335 sal_uInt32 nHeaderOffset = 0; 336 if ( ( nRead >= 8 && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1 ) 337 && ( aData[4] == 2 || aData[4] == 3 || aData[4] == 14 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 ) 338 { 339 nHeaderOffset = 40; 340 xSeek->seek( 8 ); 341 342 // TargetDevice might be used in future, currently the cache has specified NULL 343 uno::Sequence< sal_Int8 > aHeadData( 4 ); 344 nRead = xInStream->readBytes( aHeadData, 4 ); 345 sal_uInt32 nLen = 0; 346 if ( nRead == 4 && aHeadData.getLength() == 4 ) 347 nLen = ( ( ( (sal_uInt32)aHeadData[3] * 0x100 + (sal_uInt32)aHeadData[2] ) * 0x100 ) + (sal_uInt32)aHeadData[1] ) * 0x100 + (sal_uInt32)aHeadData[0]; 348 if ( nLen > 4 ) 349 { 350 xInStream->skipBytes( nLen - 4 ); 351 nHeaderOffset += nLen - 4; 352 } 353 354 // if ( aData[4] == 3 ) 355 // { 356 // try 357 // { 358 // 359 // aSizeToSet = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); 360 // aSizeToSet.Width /= 364; //2540; // let the size be in inches, as wmf requires 361 // aSizeToSet.Height /= 364; //2540; // let the size be in inches, as wmf requires 362 // bSetSizeToRepl = sal_True; 363 // } 364 // catch( uno::Exception& ) 365 // {} 366 // } 367 } 368 else if ( nRead > 4 ) 369 { 370 // check whether the first bytes represent the size 371 sal_uInt32 nSize = 0; 372 for ( sal_Int32 nInd = 3; nInd >= 0; nInd-- ) 373 nSize = ( nSize << 8 ) + (sal_uInt8)aData[nInd]; 374 375 if ( nSize == xSeek->getLength() - 4 ) 376 nHeaderOffset = 4; 377 } 378 379 if ( nHeaderOffset ) 380 { 381 // this is either a bitmap or a metafile clipboard format, retrieve the pure stream 382 uno::Reference < io::XStream > xResult( 383 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 384 uno::UNO_QUERY_THROW ); 385 uno::Reference < io::XSeekable > xResultSeek( xResult, uno::UNO_QUERY_THROW ); 386 uno::Reference < io::XOutputStream > xResultOut = xResult->getOutputStream(); 387 uno::Reference < io::XInputStream > xResultIn = xResult->getInputStream(); 388 if ( !xResultOut.is() || !xResultIn.is() ) 389 throw uno::RuntimeException(); 390 391 // if it is windows metafile the size must be provided 392 // the solution is not used currently 393 // if ( bSetSizeToRepl && abs( aSizeToSet.Width ) < 0xFFFF && abs( aSizeToSet.Height ) < 0xFFFF ) 394 // { 395 // uno::Sequence< sal_Int8 > aHeader(22); 396 // sal_uInt8* pBuffer = (sal_uInt8*)aHeader.getArray(); 397 // 398 // // write 0x9ac6cdd7L 399 // pBuffer[0] = 0xd7; 400 // pBuffer[1] = 0xcd; 401 // pBuffer[2] = 0xc6; 402 // pBuffer[3] = 0x9a; 403 // 404 // // following data seems to have no value 405 // pBuffer[4] = 0; 406 // pBuffer[5] = 0; 407 // 408 // // must be set to 0 409 // pBuffer[6] = 0; 410 // pBuffer[7] = 0; 411 // pBuffer[8] = 0; 412 // pBuffer[9] = 0; 413 // 414 // // width of the picture 415 // pBuffer[10] = abs( aSizeToSet.Width ) % 0x100; 416 // pBuffer[11] = ( abs( aSizeToSet.Width ) / 0x100 ) % 0x100; 417 // 418 // // height of the picture 419 // pBuffer[12] = abs( aSizeToSet.Height ) % 0x100; 420 // pBuffer[13] = ( abs( aSizeToSet.Height ) / 0x100 ) % 0x100; 421 // 422 // // write 2540 423 // pBuffer[14] = 0x6c; //0xec; 424 // pBuffer[15] = 0x01; //0x09; 425 // 426 // // fill with 0 427 // for ( sal_Int32 nInd = 16; nInd < 22; nInd++ ) 428 // pBuffer[nInd] = 0; 429 // 430 // xResultOut->writeBytes( aHeader ); 431 // } 432 433 xSeek->seek( nHeaderOffset ); // header size for these formats 434 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xResultOut ); 435 xResultOut->closeOutput(); 436 xResultSeek->seek( 0 ); 437 xSeek->seek( 0 ); 438 439 return xResult; 440 } 441 442 return uno::Reference< io::XStream >(); 443 } 444 445 //------------------------------------------------------ 446 void OleEmbeddedObject::InsertVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream, 447 const uno::Reference< io::XStream >& xCachedVisualRepresentation ) 448 throw ( uno::Exception ) 449 { 450 OSL_ENSURE( xTargetStream.is() && xCachedVisualRepresentation.is(), "Invalid argumants!\n" ); 451 452 if ( !xTargetStream.is() || !xCachedVisualRepresentation.is() ) 453 throw uno::RuntimeException(); 454 455 uno::Sequence< uno::Any > aArgs( 2 ); 456 aArgs[0] <<= xTargetStream; 457 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy 458 459 uno::Reference< container::XNameContainer > xNameContainer( 460 m_xFactory->createInstanceWithArguments( 461 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), 462 aArgs ), 463 uno::UNO_QUERY ); 464 465 if ( !xNameContainer.is() ) 466 throw uno::RuntimeException(); 467 468 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY_THROW ); 469 if ( xCachedSeek.is() ) 470 xCachedSeek->seek( 0 ); 471 472 uno::Reference < io::XStream > xTempFile( 473 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 474 uno::UNO_QUERY_THROW ); 475 476 uno::Reference< io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW ); 477 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream(); 478 if ( xTempOutStream.is() ) 479 { 480 // the OlePres stream must have additional header 481 // TODO/LATER: might need to be extended in future ( actually makes sence only for SO7 format ) 482 uno::Reference< io::XInputStream > xInCacheStream = xCachedVisualRepresentation->getInputStream(); 483 if ( !xInCacheStream.is() ) 484 throw uno::RuntimeException(); 485 486 // write 0xFFFFFFFF at the beginning 487 uno::Sequence< sal_Int8 > aData( 4 ); 488 *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF; 489 490 xTempOutStream->writeBytes( aData ); 491 492 // write clipboard format 493 uno::Sequence< sal_Int8 > aSigData( 2 ); 494 xInCacheStream->readBytes( aSigData, 2 ); 495 if ( aSigData.getLength() < 2 ) 496 throw io::IOException(); 497 498 if ( aSigData[0] == 'B' && aSigData[1] == 'M' ) 499 { 500 // it's a bitmap 501 aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0; 502 } 503 else 504 { 505 // treat it as a metafile 506 aData[0] = 0x03; aData[1] = 0; aData[2] = 0; aData[3] = 0; 507 } 508 xTempOutStream->writeBytes( aData ); 509 510 // write job related information 511 aData[0] = 0x04; aData[1] = 0; aData[2] = 0; aData[3] = 0; 512 xTempOutStream->writeBytes( aData ); 513 514 // write aspect 515 aData[0] = 0x01; aData[1] = 0; aData[2] = 0; aData[3] = 0; 516 xTempOutStream->writeBytes( aData ); 517 518 // write l-index 519 *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF; 520 xTempOutStream->writeBytes( aData ); 521 522 // write adv. flags 523 aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0; 524 xTempOutStream->writeBytes( aData ); 525 526 // write compression 527 *( (sal_uInt32*)aData.getArray() ) = 0x0; 528 xTempOutStream->writeBytes( aData ); 529 530 // get the size 531 awt::Size aSize = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); 532 sal_Int32 nIndex = 0; 533 534 // write width 535 for ( nIndex = 0; nIndex < 4; nIndex++ ) 536 { 537 aData[nIndex] = (sal_Int8)( aSize.Width % 0x100 ); 538 aSize.Width /= 0x100; 539 } 540 xTempOutStream->writeBytes( aData ); 541 542 // write height 543 for ( nIndex = 0; nIndex < 4; nIndex++ ) 544 { 545 aData[nIndex] = (sal_Int8)( aSize.Height % 0x100 ); 546 aSize.Height /= 0x100; 547 } 548 xTempOutStream->writeBytes( aData ); 549 550 // write garbage, it will be overwritten by the size 551 xTempOutStream->writeBytes( aData ); 552 553 // write first bytes that was used to detect the type 554 xTempOutStream->writeBytes( aSigData ); 555 556 // write the rest of the stream 557 ::comphelper::OStorageHelper::CopyInputToOutput( xInCacheStream, xTempOutStream ); 558 559 // write the size of the stream 560 sal_Int64 nLength = xTempSeek->getLength() - 40; 561 if ( nLength < 0 || nLength >= 0xFFFFFFFF ) 562 { 563 OSL_ENSURE( sal_False, "Length is not acceptable!" ); 564 return; 565 } 566 for ( sal_Int32 nInd = 0; nInd < 4; nInd++ ) 567 { 568 aData[nInd] = (sal_Int8)( ( (sal_uInt64) nLength ) % 0x100 ); 569 nLength /= 0x100; 570 } 571 xTempSeek->seek( 36 ); 572 xTempOutStream->writeBytes( aData ); 573 574 xTempOutStream->flush(); 575 576 xTempSeek->seek( 0 ); 577 if ( xCachedSeek.is() ) 578 xCachedSeek->seek( 0 ); 579 } 580 else 581 throw io::IOException(); // TODO: 582 583 // insert the result file as replacement image 584 ::rtl::OUString aCacheName = ::rtl::OUString::createFromAscii( "\002OlePres000" ); 585 if ( xNameContainer->hasByName( aCacheName ) ) 586 xNameContainer->replaceByName( aCacheName, uno::makeAny( xTempFile ) ); 587 else 588 xNameContainer->insertByName( aCacheName, uno::makeAny( xTempFile ) ); 589 590 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY ); 591 if ( !xTransacted.is() ) 592 throw uno::RuntimeException(); 593 594 xTransacted->commit(); 595 } 596 597 //------------------------------------------------------ 598 void OleEmbeddedObject::RemoveVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream ) 599 throw ( uno::Exception ) 600 { 601 OSL_ENSURE( xTargetStream.is(), "Invalid argumant!\n" ); 602 if ( !xTargetStream.is() ) 603 throw uno::RuntimeException(); 604 605 uno::Sequence< uno::Any > aArgs( 2 ); 606 aArgs[0] <<= xTargetStream; 607 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy 608 uno::Reference< container::XNameContainer > xNameContainer( 609 m_xFactory->createInstanceWithArguments( 610 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), 611 aArgs ), 612 uno::UNO_QUERY ); 613 614 if ( !xNameContainer.is() ) 615 throw uno::RuntimeException(); 616 617 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ ) 618 { 619 ::rtl::OUString aStreamName = ::rtl::OUString::createFromAscii( "\002OlePres00" ); 620 aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd ); 621 if ( xNameContainer->hasByName( aStreamName ) ) 622 xNameContainer->removeByName( aStreamName ); 623 } 624 625 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY ); 626 if ( !xTransacted.is() ) 627 throw uno::RuntimeException(); 628 629 xTransacted->commit(); 630 } 631 632 //------------------------------------------------------ 633 void OleEmbeddedObject::SetVisReplInStream( sal_Bool bExists ) 634 { 635 m_bVisReplInitialized = sal_True; 636 m_bVisReplInStream = bExists; 637 } 638 639 //------------------------------------------------------ 640 sal_Bool OleEmbeddedObject::HasVisReplInStream() 641 { 642 if ( !m_bVisReplInitialized ) 643 { 644 if ( m_xCachedVisualRepresentation.is() ) 645 SetVisReplInStream( sal_True ); 646 else 647 { 648 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::HasVisualReplInStream, analizing" ); 649 650 uno::Reference< io::XInputStream > xStream; 651 652 OSL_ENSURE( !m_pOleComponent || m_aTempURL.getLength(), "The temporary file must exist if there is a component!\n" ); 653 if ( m_aTempURL.getLength() ) 654 { 655 try 656 { 657 // open temporary file for reading 658 uno::Reference < ucb::XSimpleFileAccess > xTempAccess( 659 m_xFactory->createInstance ( 660 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 661 uno::UNO_QUERY ); 662 663 if ( !xTempAccess.is() ) 664 throw uno::RuntimeException(); // TODO: 665 666 xStream = xTempAccess->openFileRead( m_aTempURL ); 667 } 668 catch( uno::Exception& ) 669 {} 670 } 671 672 if ( !xStream.is() ) 673 xStream = m_xObjectStream->getInputStream(); 674 675 if ( xStream.is() ) 676 { 677 sal_Bool bExists = sal_False; 678 679 uno::Sequence< uno::Any > aArgs( 2 ); 680 aArgs[0] <<= xStream; 681 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy 682 uno::Reference< container::XNameContainer > xNameContainer( 683 m_xFactory->createInstanceWithArguments( 684 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), 685 aArgs ), 686 uno::UNO_QUERY ); 687 688 if ( xNameContainer.is() ) 689 { 690 for ( sal_uInt8 nInd = 0; nInd < 10 && !bExists; nInd++ ) 691 { 692 ::rtl::OUString aStreamName = ::rtl::OUString::createFromAscii( "\002OlePres00" ); 693 aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd ); 694 try 695 { 696 bExists = xNameContainer->hasByName( aStreamName ); 697 } 698 catch( uno::Exception& ) 699 {} 700 } 701 } 702 703 SetVisReplInStream( bExists ); 704 } 705 } 706 } 707 708 return m_bVisReplInStream; 709 } 710 711 //------------------------------------------------------ 712 uno::Reference< io::XStream > OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation_Impl( 713 const uno::Reference< io::XStream >& xStream, 714 sal_Bool bAllowToRepair50 ) 715 throw () 716 { 717 uno::Reference< io::XStream > xResult; 718 719 if ( xStream.is() ) 720 { 721 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation, retrieving" ); 722 723 uno::Reference< container::XNameContainer > xNameContainer; 724 uno::Sequence< uno::Any > aArgs( 2 ); 725 aArgs[0] <<= xStream; 726 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy 727 try 728 { 729 xNameContainer = uno::Reference< container::XNameContainer >( 730 m_xFactory->createInstanceWithArguments( 731 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), 732 aArgs ), 733 uno::UNO_QUERY ); 734 } 735 catch( uno::Exception& ) 736 {} 737 738 if ( xNameContainer.is() ) 739 { 740 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ ) 741 { 742 ::rtl::OUString aStreamName = ::rtl::OUString::createFromAscii( "\002OlePres00" ); 743 aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd ); 744 uno::Reference< io::XStream > xCachedCopyStream; 745 try 746 { 747 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() ) 748 { 749 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream ); 750 if ( xResult.is() ) 751 break; 752 } 753 } 754 catch( uno::Exception& ) 755 {} 756 757 if ( nInd == 0 ) 758 { 759 // to be compatible with the old versions Ole10Native is checked after OlePress000 760 aStreamName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\001Ole10Native" ) ); 761 try 762 { 763 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() ) 764 { 765 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream ); 766 if ( xResult.is() ) 767 break; 768 } 769 } 770 catch( uno::Exception& ) 771 {} 772 } 773 } 774 775 try 776 { 777 if ( bAllowToRepair50 && !xResult.is() ) 778 { 779 ::rtl::OUString aOrigContName( RTL_CONSTASCII_USTRINGPARAM( "Ole-Object" ) ); 780 if ( xNameContainer->hasByName( aOrigContName ) ) 781 { 782 uno::Reference< embed::XClassifiedObject > xClassified( xNameContainer, uno::UNO_QUERY_THROW ); 783 uno::Sequence< sal_Int8 > aClassID; 784 if ( MimeConfigurationHelper::ClassIDsEqual( xClassified->getClassID(), MimeConfigurationHelper::GetSequenceClassID( SO3_OUT_CLASSID ) ) ) 785 { 786 // this is an OLE object wrongly stored in 5.0 format 787 // this object must be repaired since SO7 has done it 788 789 uno::Reference< io::XOutputStream > xOutputStream = xStream->getOutputStream(); 790 uno::Reference< io::XTruncate > xTruncate( xOutputStream, uno::UNO_QUERY_THROW ); 791 792 uno::Reference< io::XInputStream > xOrigInputStream; 793 if ( ( xNameContainer->getByName( aOrigContName ) >>= xOrigInputStream ) 794 && xOrigInputStream.is() ) 795 { 796 // the provided input stream must be based on temporary medium and must be independent 797 // from the stream the storage is based on 798 uno::Reference< io::XSeekable > xOrigSeekable( xOrigInputStream, uno::UNO_QUERY ); 799 if ( xOrigSeekable.is() ) 800 xOrigSeekable->seek( 0 ); 801 802 uno::Reference< lang::XComponent > xNameContDisp( xNameContainer, uno::UNO_QUERY_THROW ); 803 xNameContDisp->dispose(); // free the original stream 804 805 xTruncate->truncate(); 806 ::comphelper::OStorageHelper::CopyInputToOutput( xOrigInputStream, xOutputStream ); 807 xOutputStream->flush(); 808 809 if ( xStream == m_xObjectStream ) 810 { 811 if ( m_aTempURL.getLength() ) 812 { 813 // this is the own stream, so the temporary URL must be cleaned if it exists 814 KillFile_Impl( m_aTempURL, m_xFactory ); 815 m_aTempURL = ::rtl::OUString(); 816 } 817 818 #ifdef WNT 819 // retry to create the component after recovering 820 GetRidOfComponent(); 821 822 try 823 { 824 CreateOleComponentAndLoad_Impl( NULL ); 825 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction 826 } 827 catch( uno::Exception& ) 828 { 829 GetRidOfComponent(); 830 } 831 #endif 832 } 833 834 xResult = TryToRetrieveCachedVisualRepresentation_Impl( xStream, sal_False ); 835 } 836 } 837 } 838 } 839 } 840 catch( uno::Exception& ) 841 {} 842 } 843 } 844 845 return xResult; 846 } 847 848 //------------------------------------------------------ 849 void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage, 850 const uno::Reference< io::XStream >& xNewObjectStream, 851 const ::rtl::OUString& aNewName ) 852 { 853 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) ) 854 { 855 OSL_ENSURE( xNewObjectStream == m_xObjectStream, "The streams must be the same!\n" ); 856 return; 857 } 858 859 try { 860 uno::Reference< lang::XComponent > xComponent( m_xObjectStream, uno::UNO_QUERY ); 861 OSL_ENSURE( !m_xObjectStream.is() || xComponent.is(), "Wrong stream implementation!" ); 862 if ( xComponent.is() ) 863 xComponent->dispose(); 864 } 865 catch ( uno::Exception& ) 866 { 867 } 868 869 m_xObjectStream = xNewObjectStream; 870 m_xParentStorage = xNewParentStorage; 871 m_aEntryName = aNewName; 872 } 873 874 //------------------------------------------------------ 875 void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage, 876 const ::rtl::OUString& aNewName ) 877 { 878 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) ) 879 return; 880 881 sal_Int32 nStreamMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE; 882 883 uno::Reference< io::XStream > xNewOwnStream = xNewParentStorage->openStreamElement( aNewName, nStreamMode ); 884 OSL_ENSURE( xNewOwnStream.is(), "The method can not return empty reference!" ); 885 886 SwitchOwnPersistence( xNewParentStorage, xNewOwnStream, aNewName ); 887 } 888 889 #ifdef WNT 890 //---------------------------------------------- 891 sal_Bool OleEmbeddedObject::SaveObject_Impl() 892 { 893 sal_Bool bResult = sal_False; 894 895 if ( m_xClientSite.is() ) 896 { 897 try 898 { 899 m_xClientSite->saveObject(); 900 bResult = sal_True; 901 } 902 catch( uno::Exception& ) 903 { 904 } 905 } 906 907 return bResult; 908 } 909 910 //---------------------------------------------- 911 sal_Bool OleEmbeddedObject::OnShowWindow_Impl( sal_Bool bShow ) 912 { 913 ::osl::ResettableMutexGuard aGuard( m_aMutex ); 914 915 sal_Bool bResult = sal_False; 916 917 OSL_ENSURE( m_nObjectState != -1, "The object has no persistence!\n" ); 918 OSL_ENSURE( m_nObjectState != embed::EmbedStates::LOADED, "The object get OnShowWindow in loaded state!\n" ); 919 if ( m_nObjectState == -1 || m_nObjectState == embed::EmbedStates::LOADED ) 920 return sal_False; 921 922 // the object is either activated or deactivated 923 sal_Int32 nOldState = m_nObjectState; 924 if ( bShow && m_nObjectState == embed::EmbedStates::RUNNING ) 925 { 926 m_nObjectState = embed::EmbedStates::ACTIVE; 927 m_aVerbExecutionController.ObjectIsActive(); 928 929 aGuard.clear(); 930 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); 931 } 932 else if ( !bShow && m_nObjectState == embed::EmbedStates::ACTIVE ) 933 { 934 m_nObjectState = embed::EmbedStates::RUNNING; 935 aGuard.clear(); 936 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); 937 } 938 939 if ( m_xClientSite.is() ) 940 { 941 try 942 { 943 m_xClientSite->visibilityChanged( bShow ); 944 bResult = sal_True; 945 } 946 catch( uno::Exception& ) 947 { 948 } 949 } 950 951 return bResult; 952 } 953 954 //------------------------------------------------------ 955 void OleEmbeddedObject::OnIconChanged_Impl() 956 { 957 // TODO/LATER: currently this notification seems to be impossible 958 // MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnIconChanged" ) ); 959 } 960 961 //------------------------------------------------------ 962 void OleEmbeddedObject::OnViewChanged_Impl() 963 { 964 if ( m_bDisposed ) 965 throw lang::DisposedException(); 966 967 // For performance reasons the notification currently is ignored, STAMPIT object is the exception, 968 // it can never be active and never call SaveObject, so it is the only way to detect that it is changed 969 970 // ==== the STAMPIT related solution ============================= 971 // the following variable is used to detect whether the object was modified during verb execution 972 m_aVerbExecutionController.ModificationNotificationIsDone(); 973 974 // The following things are controlled by VerbExecutionController: 975 // - if the verb execution is in progress and the view is changed the object will be stored 976 // after the execution, so there is no need to send the notification. 977 // - the STAMPIT object can never be active. 978 if ( m_aVerbExecutionController.CanDoNotification() 979 && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE ) 980 { 981 OSL_ENSURE( MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0x852ee1c9, 0x9058, 0x44ba, 0x8c,0x6c,0x0c,0x5f,0xc6,0x6b,0xdb,0x8d ) ) 982 || MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0xcf1b4491, 0xbea3, 0x4c9f, 0xa7,0x0f,0x22,0x1b,0x1e,0xca,0xef,0x3e ) ), 983 "Expected to be triggered for STAMPIT only! Please contact developers!\n" ); 984 985 // The view is changed while the object is in running state, save the new object 986 m_xCachedVisualRepresentation = uno::Reference< io::XStream >(); 987 SaveObject_Impl(); 988 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnVisAreaChanged" ) ); 989 } 990 // =============================================================== 991 } 992 993 //------------------------------------------------------ 994 void OleEmbeddedObject::OnClosed_Impl() 995 { 996 if ( m_bDisposed ) 997 throw lang::DisposedException(); 998 999 if ( m_nObjectState != embed::EmbedStates::LOADED ) 1000 { 1001 sal_Int32 nOldState = m_nObjectState; 1002 m_nObjectState = embed::EmbedStates::LOADED; 1003 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); 1004 } 1005 } 1006 1007 //------------------------------------------------------ 1008 ::rtl::OUString OleEmbeddedObject::CreateTempURLEmpty_Impl() 1009 { 1010 OSL_ENSURE( !m_aTempURL.getLength(), "The object has already the temporary file!" ); 1011 m_aTempURL = GetNewTempFileURL_Impl( m_xFactory ); 1012 1013 return m_aTempURL; 1014 } 1015 1016 //------------------------------------------------------ 1017 ::rtl::OUString OleEmbeddedObject::GetTempURL_Impl() 1018 { 1019 if ( !m_aTempURL.getLength() ) 1020 { 1021 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::GetTempURL_Impl, tempfile creation" ); 1022 1023 // if there is no temporary file, it will be created from the own entry 1024 uno::Reference< embed::XOptimizedStorage > xOptParStorage( m_xParentStorage, uno::UNO_QUERY ); 1025 if ( xOptParStorage.is() ) 1026 { 1027 m_aTempURL = GetNewFilledTempFile_Impl( xOptParStorage, m_aEntryName, m_xFactory ); 1028 } 1029 else if ( m_xObjectStream.is() ) 1030 { 1031 // load object from the stream 1032 uno::Reference< io::XInputStream > xInStream = m_xObjectStream->getInputStream(); 1033 if ( !xInStream.is() ) 1034 throw io::IOException(); // TODO: access denied 1035 1036 m_aTempURL = GetNewFilledTempFile_Impl( xInStream, m_xFactory ); 1037 } 1038 } 1039 1040 return m_aTempURL; 1041 } 1042 1043 //------------------------------------------------------ 1044 void OleEmbeddedObject::CreateOleComponent_Impl( OleComponent* pOleComponent ) 1045 { 1046 if ( !m_pOleComponent ) 1047 { 1048 m_pOleComponent = pOleComponent ? pOleComponent : new OleComponent( m_xFactory, this ); 1049 m_pOleComponent->acquire(); // TODO: needs holder? 1050 1051 if ( !m_xClosePreventer.is() ) 1052 m_xClosePreventer = uno::Reference< util::XCloseListener >( 1053 static_cast< ::cppu::OWeakObject* >( new OClosePreventer ), 1054 uno::UNO_QUERY ); 1055 1056 m_pOleComponent->addCloseListener( m_xClosePreventer ); 1057 } 1058 } 1059 1060 //------------------------------------------------------ 1061 void OleEmbeddedObject::CreateOleComponentAndLoad_Impl( OleComponent* pOleComponent ) 1062 { 1063 if ( !m_pOleComponent ) 1064 { 1065 if ( !m_xObjectStream.is() ) 1066 throw uno::RuntimeException(); 1067 1068 CreateOleComponent_Impl( pOleComponent ); 1069 1070 // after the loading the object can appear as a link 1071 // will be detected later by olecomponent 1072 1073 GetTempURL_Impl(); 1074 if ( !m_aTempURL.getLength() ) 1075 throw uno::RuntimeException(); // TODO 1076 1077 m_pOleComponent->LoadEmbeddedObject( m_aTempURL ); 1078 } 1079 } 1080 1081 //------------------------------------------------------ 1082 void OleEmbeddedObject::CreateOleComponentFromClipboard_Impl( OleComponent* pOleComponent ) 1083 { 1084 if ( !m_pOleComponent ) 1085 { 1086 if ( !m_xObjectStream.is() ) 1087 throw uno::RuntimeException(); 1088 1089 CreateOleComponent_Impl( pOleComponent ); 1090 1091 // after the loading the object can appear as a link 1092 // will be detected later by olecomponent 1093 m_pOleComponent->CreateObjectFromClipboard(); 1094 } 1095 } 1096 1097 //------------------------------------------------------ 1098 uno::Reference< io::XOutputStream > OleEmbeddedObject::GetStreamForSaving() 1099 { 1100 if ( !m_xObjectStream.is() ) 1101 throw uno::RuntimeException(); //TODO: 1102 1103 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream(); 1104 if ( !xOutStream.is() ) 1105 throw io::IOException(); //TODO: access denied 1106 1107 uno::Reference< io::XTruncate > xTruncate( xOutStream, uno::UNO_QUERY ); 1108 if ( !xTruncate.is() ) 1109 throw uno::RuntimeException(); //TODO: 1110 1111 xTruncate->truncate(); 1112 1113 return xOutStream; 1114 } 1115 1116 //---------------------------------------------- 1117 void OleEmbeddedObject::StoreObjectToStream( uno::Reference< io::XOutputStream > xOutStream ) 1118 throw ( uno::Exception ) 1119 { 1120 // this method should be used only on windows 1121 if ( m_pOleComponent ) 1122 m_pOleComponent->StoreOwnTmpIfNecessary(); 1123 1124 // now all the changes should be in temporary location 1125 if ( !m_aTempURL ) 1126 throw uno::RuntimeException(); 1127 1128 // open temporary file for reading 1129 uno::Reference < ucb::XSimpleFileAccess > xTempAccess( 1130 m_xFactory->createInstance ( 1131 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 1132 uno::UNO_QUERY ); 1133 1134 if ( !xTempAccess.is() ) 1135 throw uno::RuntimeException(); // TODO: 1136 1137 uno::Reference< io::XInputStream > xTempInStream = xTempAccess->openFileRead( m_aTempURL ); 1138 OSL_ENSURE( xTempInStream.is(), "The object's temporary file can not be reopened for reading!\n" ); 1139 1140 // TODO: use bStoreVisReplace 1141 1142 if ( xTempInStream.is() ) 1143 { 1144 // write all the contents to XOutStream 1145 uno::Reference< io::XTruncate > xTrunc( xOutStream, uno::UNO_QUERY ); 1146 if ( !xTrunc.is() ) 1147 throw uno::RuntimeException(); //TODO: 1148 1149 xTrunc->truncate(); 1150 1151 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutStream ); 1152 } 1153 else 1154 throw io::IOException(); // TODO: 1155 1156 // TODO: should the view replacement be in the stream ??? 1157 // probably it must be specified on storing 1158 } 1159 #endif 1160 //------------------------------------------------------ 1161 void OleEmbeddedObject::StoreToLocation_Impl( 1162 const uno::Reference< embed::XStorage >& xStorage, 1163 const ::rtl::OUString& sEntName, 1164 const uno::Sequence< beans::PropertyValue >& /*lArguments*/, 1165 const uno::Sequence< beans::PropertyValue >& lObjArgs, 1166 sal_Bool bSaveAs ) 1167 throw ( uno::Exception ) 1168 { 1169 // TODO: use lObjArgs 1170 // TODO: exchange StoreVisualReplacement by SO file format version? 1171 1172 if ( m_nObjectState == -1 ) 1173 { 1174 // the object is still not loaded 1175 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), 1176 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1177 } 1178 1179 if ( m_bWaitSaveCompleted ) 1180 throw embed::WrongStateException( 1181 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1182 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1183 1184 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" ); 1185 1186 sal_Bool bVisReplIsStored = sal_False; 1187 1188 sal_Bool bTryOptimization = sal_False; 1189 sal_Bool bStoreVis = m_bStoreVisRepl; 1190 uno::Reference< io::XStream > xCachedVisualRepresentation; 1191 for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) 1192 { 1193 if ( lObjArgs[nInd].Name.equalsAscii( "StoreVisualReplacement" ) ) 1194 lObjArgs[nInd].Value >>= bStoreVis; 1195 else if ( lObjArgs[nInd].Name.equalsAscii( "VisualReplacement" ) ) 1196 lObjArgs[nInd].Value >>= xCachedVisualRepresentation; 1197 else if ( lObjArgs[nInd].Name.equalsAscii( "CanTryOptimization" ) ) 1198 lObjArgs[nInd].Value >>= bTryOptimization; 1199 } 1200 1201 // ignore visual representation provided from outside if it should not be stored 1202 if ( !bStoreVis ) 1203 xCachedVisualRepresentation = uno::Reference< io::XStream >(); 1204 1205 if ( bStoreVis && !HasVisReplInStream() && !xCachedVisualRepresentation.is() ) 1206 throw io::IOException(); // TODO: there is no cached visual representation and nothing is provided from outside 1207 1208 // if the representation is provided from outside it should be copied to a local stream 1209 sal_Bool bNeedLocalCache = xCachedVisualRepresentation.is(); 1210 1211 uno::Reference< io::XStream > xTargetStream; 1212 1213 sal_Bool bStoreLoaded = sal_False; 1214 if ( m_nObjectState == embed::EmbedStates::LOADED 1215 #ifdef WNT 1216 // if the object was NOT modified after storing it can be just copied 1217 // as if it was in loaded state 1218 || ( m_pOleComponent && !m_pOleComponent->IsDirty() ) 1219 #endif 1220 ) 1221 { 1222 sal_Bool bOptimizedCopyingDone = sal_False; 1223 1224 if ( bTryOptimization && bStoreVis == HasVisReplInStream() ) 1225 { 1226 try 1227 { 1228 uno::Reference< embed::XOptimizedStorage > xSourceOptStor( m_xParentStorage, uno::UNO_QUERY_THROW ); 1229 uno::Reference< embed::XOptimizedStorage > xTargetOptStor( xStorage, uno::UNO_QUERY_THROW ); 1230 xSourceOptStor->copyElementDirectlyTo( m_aEntryName, xTargetOptStor, sEntName ); 1231 bOptimizedCopyingDone = sal_True; 1232 } 1233 catch( uno::Exception& ) 1234 { 1235 } 1236 } 1237 1238 if ( !bOptimizedCopyingDone ) 1239 { 1240 // if optimized copying fails a normal one should be tried 1241 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName ); 1242 } 1243 1244 // the locally retrieved representation is always preferable 1245 // since the object is in loaded state the representation is unchanged 1246 if ( m_xCachedVisualRepresentation.is() ) 1247 { 1248 xCachedVisualRepresentation = m_xCachedVisualRepresentation; 1249 bNeedLocalCache = sal_False; 1250 } 1251 1252 bVisReplIsStored = HasVisReplInStream(); 1253 bStoreLoaded = sal_True; 1254 } 1255 #ifdef WNT 1256 else if ( m_pOleComponent ) 1257 { 1258 xTargetStream = 1259 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE ); 1260 if ( !xTargetStream.is() ) 1261 throw io::IOException(); //TODO: access denied 1262 1263 SetStreamMediaType_Impl( xTargetStream, ::rtl::OUString::createFromAscii( "application/vnd.sun.star.oleobject" ) ); 1264 uno::Reference< io::XOutputStream > xOutStream = xTargetStream->getOutputStream(); 1265 if ( !xOutStream.is() ) 1266 throw io::IOException(); //TODO: access denied 1267 1268 StoreObjectToStream( xOutStream ); 1269 bVisReplIsStored = sal_True; 1270 1271 if ( bSaveAs ) 1272 { 1273 // no need to do it on StoreTo since in this case the replacement is in the stream 1274 // and there is no need to cache it even if it is thrown away because the object 1275 // is not changed by StoreTo action 1276 1277 uno::Reference< io::XStream > xTmpCVRepresentation = 1278 TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream ); 1279 1280 // the locally retrieved representation is always preferable 1281 if ( xTmpCVRepresentation.is() ) 1282 { 1283 xCachedVisualRepresentation = xTmpCVRepresentation; 1284 bNeedLocalCache = sal_False; 1285 } 1286 } 1287 } 1288 #endif 1289 else 1290 { 1291 throw io::IOException(); // TODO 1292 } 1293 1294 if ( !xTargetStream.is() ) 1295 { 1296 xTargetStream = 1297 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE ); 1298 if ( !xTargetStream.is() ) 1299 throw io::IOException(); //TODO: access denied 1300 } 1301 1302 LetCommonStoragePassBeUsed_Impl( xTargetStream ); 1303 1304 if ( bStoreVis != bVisReplIsStored ) 1305 { 1306 if ( bStoreVis ) 1307 { 1308 if ( !xCachedVisualRepresentation.is() ) 1309 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream ); 1310 1311 OSL_ENSURE( xCachedVisualRepresentation.is(), "No representation is available!" ); 1312 1313 // the following copying will be done in case it is SaveAs anyway 1314 // if it is not SaveAs the seekable access is not required currently 1315 // TODO/LATER: may be required in future 1316 if ( bSaveAs ) 1317 { 1318 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY ); 1319 if ( !xCachedSeek.is() ) 1320 { 1321 xCachedVisualRepresentation 1322 = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() ); 1323 bNeedLocalCache = sal_False; 1324 } 1325 } 1326 1327 InsertVisualCache_Impl( xTargetStream, xCachedVisualRepresentation ); 1328 } 1329 else 1330 { 1331 // the removed representation could be cached by this method 1332 if ( !xCachedVisualRepresentation.is() ) 1333 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream ); 1334 1335 RemoveVisualCache_Impl( xTargetStream ); 1336 } 1337 } 1338 1339 if ( bSaveAs ) 1340 { 1341 m_bWaitSaveCompleted = sal_True; 1342 m_xNewObjectStream = xTargetStream; 1343 m_xNewParentStorage = xStorage; 1344 m_aNewEntryName = sEntName; 1345 m_bNewVisReplInStream = bStoreVis; 1346 m_bStoreLoaded = bStoreLoaded; 1347 1348 if ( xCachedVisualRepresentation.is() ) 1349 { 1350 if ( bNeedLocalCache ) 1351 m_xNewCachedVisRepl = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() ); 1352 else 1353 m_xNewCachedVisRepl = xCachedVisualRepresentation; 1354 } 1355 1356 // TODO: register listeners for storages above, in case they are disposed 1357 // an exception will be thrown on saveCompleted( true ) 1358 } 1359 else 1360 { 1361 uno::Reference< lang::XComponent > xComp( xTargetStream, uno::UNO_QUERY ); 1362 if ( xComp.is() ) 1363 { 1364 try { 1365 xComp->dispose(); 1366 } catch( uno::Exception& ) 1367 { 1368 } 1369 } 1370 } 1371 } 1372 1373 //------------------------------------------------------ 1374 void SAL_CALL OleEmbeddedObject::setPersistentEntry( 1375 const uno::Reference< embed::XStorage >& xStorage, 1376 const ::rtl::OUString& sEntName, 1377 sal_Int32 nEntryConnectionMode, 1378 const uno::Sequence< beans::PropertyValue >& lArguments, 1379 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 1380 throw ( lang::IllegalArgumentException, 1381 embed::WrongStateException, 1382 io::IOException, 1383 uno::Exception, 1384 uno::RuntimeException ) 1385 { 1386 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::setPersistentEntry" ); 1387 1388 // begin wrapping related part ==================== 1389 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 1390 if ( xWrappedObject.is() ) 1391 { 1392 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 1393 xWrappedObject->setPersistentEntry( xStorage, sEntName, nEntryConnectionMode, lArguments, lObjArgs ); 1394 return; 1395 } 1396 // end wrapping related part ==================== 1397 1398 // TODO: use lObjArgs 1399 1400 // the type of the object must be already set 1401 // a kind of typedetection should be done in the factory; 1402 // the only exception is object initialized from a stream, 1403 // the class ID will be detected from the stream 1404 1405 ::osl::MutexGuard aGuard( m_aMutex ); 1406 if ( m_bDisposed ) 1407 throw lang::DisposedException(); // TODO 1408 1409 if ( !xStorage.is() ) 1410 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 1411 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 1412 1 ); 1413 1414 if ( !sEntName.getLength() ) 1415 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 1416 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 1417 2 ); 1418 1419 // May be LOADED should be forbidden here ??? 1420 if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) 1421 && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) ) 1422 { 1423 // if the object is not loaded 1424 // it can not get persistant representation without initialization 1425 1426 // if the object is loaded 1427 // it can switch persistant representation only without initialization 1428 1429 throw embed::WrongStateException( 1430 ::rtl::OUString::createFromAscii( "Can't change persistant representation of activated object!\n" ), 1431 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1432 } 1433 1434 if ( m_bWaitSaveCompleted ) 1435 { 1436 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) 1437 saveCompleted( ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) ); 1438 else 1439 throw embed::WrongStateException( 1440 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1441 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1442 } 1443 1444 uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY ); 1445 if ( !xNameAccess.is() ) 1446 throw uno::RuntimeException(); //TODO 1447 1448 // detect entry existence 1449 sal_Bool bElExists = xNameAccess->hasByName( sEntName ); 1450 1451 m_bReadOnly = sal_False; 1452 sal_Int32 nInd = 0; 1453 for ( nInd = 0; nInd < lArguments.getLength(); nInd++ ) 1454 if ( lArguments[nInd].Name.equalsAscii( "ReadOnly" ) ) 1455 lArguments[nInd].Value >>= m_bReadOnly; 1456 1457 #ifdef WNT 1458 sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE; 1459 #endif 1460 1461 SwitchOwnPersistence( xStorage, sEntName ); 1462 1463 for ( nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) 1464 if ( lObjArgs[nInd].Name.equalsAscii( "StoreVisualReplacement" ) ) 1465 lObjArgs[nInd].Value >>= m_bStoreVisRepl; 1466 1467 #ifdef WNT 1468 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT ) 1469 { 1470 if ( m_bFromClipboard ) 1471 { 1472 // the object should be initialized from clipboard 1473 // inpossibility to initialize the object means error here 1474 CreateOleComponentFromClipboard_Impl( NULL ); 1475 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction 1476 m_pOleComponent->RunObject(); 1477 m_nObjectState = embed::EmbedStates::RUNNING; 1478 } 1479 else if ( bElExists ) 1480 { 1481 // load object from the stream 1482 // after the loading the object can appear as a link 1483 // will be detected by olecomponent 1484 try 1485 { 1486 CreateOleComponentAndLoad_Impl( NULL ); 1487 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction 1488 } 1489 catch( uno::Exception& ) 1490 { 1491 // TODO/LATER: detect classID of the object if possible 1492 // means that the object inprocess server could not be successfuly instantiated 1493 GetRidOfComponent(); 1494 } 1495 1496 m_nObjectState = embed::EmbedStates::LOADED; 1497 } 1498 else 1499 { 1500 // create a new object 1501 CreateOleComponent_Impl(); 1502 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID ); 1503 m_pOleComponent->RunObject(); 1504 m_nObjectState = embed::EmbedStates::RUNNING; 1505 } 1506 } 1507 else 1508 { 1509 if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE ) 1510 throw io::IOException(); 1511 1512 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) 1513 { 1514 // the document just already changed its stream to store to; 1515 // the links to OLE documents switch their persistence in the same way 1516 // as normal embedded objects 1517 } 1518 else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT ) 1519 { 1520 // create a new object, that will be stored in specified stream 1521 CreateOleComponent_Impl(); 1522 1523 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID ); 1524 m_pOleComponent->RunObject(); 1525 m_nObjectState = embed::EmbedStates::RUNNING; 1526 } 1527 else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT ) 1528 { 1529 // use URL ( may be content or stream later ) from MediaDescriptor to initialize object 1530 ::rtl::OUString aURL; 1531 for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ ) 1532 if ( lArguments[nInd].Name.equalsAscii( "URL" ) ) 1533 lArguments[nInd].Value >>= aURL; 1534 1535 if ( !aURL.getLength() ) 1536 throw lang::IllegalArgumentException( 1537 ::rtl::OUString::createFromAscii( "Empty URL is provided in the media descriptor!\n" ), 1538 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 1539 4 ); 1540 1541 CreateOleComponent_Impl(); 1542 1543 // TODO: the m_bIsLink value must be set already 1544 if ( !m_bIsLink ) 1545 m_pOleComponent->CreateObjectFromFile( aURL ); 1546 else 1547 m_pOleComponent->CreateLinkFromFile( aURL ); 1548 1549 m_pOleComponent->RunObject(); 1550 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction 1551 1552 m_nObjectState = embed::EmbedStates::RUNNING; 1553 } 1554 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT ) 1555 //{ 1556 //TODO: 1557 //} 1558 else 1559 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong connection mode is provided!\n" ), 1560 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 1561 3 ); 1562 } 1563 #else 1564 // On unix the ole object can not do anything except storing itself somewere 1565 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT && bElExists ) 1566 { 1567 // TODO/LATER: detect classID of the object 1568 // can be a real problem for the links 1569 1570 m_nObjectState = embed::EmbedStates::LOADED; 1571 } 1572 else if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) 1573 { 1574 // do nothing, the object has already switched it's persistence 1575 } 1576 else 1577 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong connection mode is provided!\n" ), 1578 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 1579 3 ); 1580 1581 #endif 1582 } 1583 1584 //------------------------------------------------------ 1585 void SAL_CALL OleEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage, 1586 const ::rtl::OUString& sEntName, 1587 const uno::Sequence< beans::PropertyValue >& lArguments, 1588 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 1589 throw ( lang::IllegalArgumentException, 1590 embed::WrongStateException, 1591 io::IOException, 1592 uno::Exception, 1593 uno::RuntimeException ) 1594 { 1595 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeToEntry" ); 1596 1597 // begin wrapping related part ==================== 1598 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 1599 if ( xWrappedObject.is() ) 1600 { 1601 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 1602 xWrappedObject->storeToEntry( xStorage, sEntName, lArguments, lObjArgs ); 1603 return; 1604 } 1605 // end wrapping related part ==================== 1606 1607 ::osl::MutexGuard aGuard( m_aMutex ); 1608 if ( m_bDisposed ) 1609 throw lang::DisposedException(); // TODO 1610 1611 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); 1612 1613 StoreToLocation_Impl( xStorage, sEntName, lArguments, lObjArgs, sal_False ); 1614 1615 // TODO: should the listener notification be done? 1616 } 1617 1618 //------------------------------------------------------ 1619 void SAL_CALL OleEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage, 1620 const ::rtl::OUString& sEntName, 1621 const uno::Sequence< beans::PropertyValue >& lArguments, 1622 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 1623 throw ( lang::IllegalArgumentException, 1624 embed::WrongStateException, 1625 io::IOException, 1626 uno::Exception, 1627 uno::RuntimeException ) 1628 { 1629 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeAsEntry" ); 1630 1631 // begin wrapping related part ==================== 1632 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 1633 if ( xWrappedObject.is() ) 1634 { 1635 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 1636 xWrappedObject->storeAsEntry( xStorage, sEntName, lArguments, lObjArgs ); 1637 return; 1638 } 1639 // end wrapping related part ==================== 1640 1641 ::osl::MutexGuard aGuard( m_aMutex ); 1642 if ( m_bDisposed ) 1643 throw lang::DisposedException(); // TODO 1644 1645 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); 1646 1647 StoreToLocation_Impl( xStorage, sEntName, lArguments, lObjArgs, sal_True ); 1648 1649 // TODO: should the listener notification be done here or in saveCompleted? 1650 } 1651 1652 //------------------------------------------------------ 1653 void SAL_CALL OleEmbeddedObject::saveCompleted( sal_Bool bUseNew ) 1654 throw ( embed::WrongStateException, 1655 uno::Exception, 1656 uno::RuntimeException ) 1657 { 1658 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::saveCompleted" ); 1659 1660 // begin wrapping related part ==================== 1661 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 1662 if ( xWrappedObject.is() ) 1663 { 1664 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 1665 xWrappedObject->saveCompleted( bUseNew ); 1666 return; 1667 } 1668 // end wrapping related part ==================== 1669 1670 ::osl::ResettableMutexGuard aGuard( m_aMutex ); 1671 if ( m_bDisposed ) 1672 throw lang::DisposedException(); // TODO 1673 1674 if ( m_nObjectState == -1 ) 1675 { 1676 // the object is still not loaded 1677 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), 1678 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1679 } 1680 1681 // it is allowed to call saveCompleted( false ) for nonstored objects 1682 if ( !m_bWaitSaveCompleted && !bUseNew ) 1683 return; 1684 1685 OSL_ENSURE( m_bWaitSaveCompleted, "Unexpected saveCompleted() call!\n" ); 1686 if ( !m_bWaitSaveCompleted ) 1687 throw io::IOException(); // TODO: illegal call 1688 1689 OSL_ENSURE( m_xNewObjectStream.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" ); 1690 if ( !m_xNewObjectStream.is() || !m_xNewParentStorage.is() ) 1691 throw uno::RuntimeException(); // TODO: broken internal information 1692 1693 if ( bUseNew ) 1694 { 1695 SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStream, m_aNewEntryName ); 1696 m_bStoreVisRepl = m_bNewVisReplInStream; 1697 SetVisReplInStream( m_bNewVisReplInStream ); 1698 m_xCachedVisualRepresentation = m_xNewCachedVisRepl; 1699 } 1700 else 1701 { 1702 // close remembered stream 1703 try { 1704 uno::Reference< lang::XComponent > xComponent( m_xNewObjectStream, uno::UNO_QUERY ); 1705 OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" ); 1706 if ( xComponent.is() ) 1707 xComponent->dispose(); 1708 } 1709 catch ( uno::Exception& ) 1710 { 1711 } 1712 } 1713 1714 sal_Bool bStoreLoaded = m_bStoreLoaded; 1715 1716 m_xNewObjectStream = uno::Reference< io::XStream >(); 1717 m_xNewParentStorage = uno::Reference< embed::XStorage >(); 1718 m_aNewEntryName = ::rtl::OUString(); 1719 m_bWaitSaveCompleted = sal_False; 1720 m_bNewVisReplInStream = sal_False; 1721 m_xNewCachedVisRepl = uno::Reference< io::XStream >(); 1722 m_bStoreLoaded = sal_False; 1723 1724 if ( bUseNew && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded 1725 && m_nObjectState != embed::EmbedStates::LOADED ) 1726 { 1727 // the object replacement image should be updated, so the cached size as well 1728 m_bHasCachedSize = sal_False; 1729 try 1730 { 1731 // the call will cache the size in case of success 1732 // probably it might need to be done earlier, while the object is in active state 1733 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); 1734 } 1735 catch( uno::Exception& ) 1736 {} 1737 } 1738 1739 aGuard.clear(); 1740 if ( bUseNew ) 1741 { 1742 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnSaveAsDone" ) ); 1743 1744 // the object can be changed only on windows 1745 // the notification should be done only if the object is not in loaded state 1746 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded ) 1747 { 1748 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnVisAreaChanged" ) ); 1749 } 1750 } 1751 } 1752 1753 //------------------------------------------------------ 1754 sal_Bool SAL_CALL OleEmbeddedObject::hasEntry() 1755 throw ( embed::WrongStateException, 1756 uno::RuntimeException ) 1757 { 1758 // begin wrapping related part ==================== 1759 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 1760 if ( xWrappedObject.is() ) 1761 { 1762 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 1763 return xWrappedObject->hasEntry(); 1764 } 1765 // end wrapping related part ==================== 1766 1767 ::osl::MutexGuard aGuard( m_aMutex ); 1768 if ( m_bDisposed ) 1769 throw lang::DisposedException(); // TODO 1770 1771 if ( m_bWaitSaveCompleted ) 1772 throw embed::WrongStateException( 1773 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1774 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1775 1776 if ( m_xObjectStream.is() ) 1777 return sal_True; 1778 1779 return sal_False; 1780 } 1781 1782 //------------------------------------------------------ 1783 ::rtl::OUString SAL_CALL OleEmbeddedObject::getEntryName() 1784 throw ( embed::WrongStateException, 1785 uno::RuntimeException ) 1786 { 1787 // begin wrapping related part ==================== 1788 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 1789 if ( xWrappedObject.is() ) 1790 { 1791 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 1792 return xWrappedObject->getEntryName(); 1793 } 1794 // end wrapping related part ==================== 1795 1796 ::osl::MutexGuard aGuard( m_aMutex ); 1797 if ( m_bDisposed ) 1798 throw lang::DisposedException(); // TODO 1799 1800 if ( m_nObjectState == -1 ) 1801 { 1802 // the object is still not loaded 1803 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ), 1804 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1805 } 1806 1807 if ( m_bWaitSaveCompleted ) 1808 throw embed::WrongStateException( 1809 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1810 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1811 1812 return m_aEntryName; 1813 } 1814 1815 1816 //------------------------------------------------------ 1817 void SAL_CALL OleEmbeddedObject::storeOwn() 1818 throw ( embed::WrongStateException, 1819 io::IOException, 1820 uno::Exception, 1821 uno::RuntimeException ) 1822 { 1823 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeOwn" ); 1824 1825 // begin wrapping related part ==================== 1826 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 1827 if ( xWrappedObject.is() ) 1828 { 1829 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 1830 xWrappedObject->storeOwn(); 1831 return; 1832 } 1833 // end wrapping related part ==================== 1834 1835 // during switching from Activated to Running and from Running to Loaded states the object will 1836 // ask container to store the object, the container has to make decision 1837 // to do so or not 1838 1839 ::osl::ResettableMutexGuard aGuard( m_aMutex ); 1840 if ( m_bDisposed ) 1841 throw lang::DisposedException(); // TODO 1842 1843 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); 1844 1845 if ( m_nObjectState == -1 ) 1846 { 1847 // the object is still not loaded 1848 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), 1849 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1850 } 1851 1852 if ( m_bWaitSaveCompleted ) 1853 throw embed::WrongStateException( 1854 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1855 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1856 1857 if ( m_bReadOnly ) 1858 throw io::IOException(); // TODO: access denied 1859 1860 LetCommonStoragePassBeUsed_Impl( m_xObjectStream ); 1861 1862 sal_Bool bStoreLoaded = sal_True; 1863 1864 #ifdef WNT 1865 if ( m_nObjectState != embed::EmbedStates::LOADED && m_pOleComponent && m_pOleComponent->IsDirty() ) 1866 { 1867 bStoreLoaded = sal_False; 1868 1869 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" ); 1870 1871 if ( !m_xObjectStream.is() ) 1872 throw io::IOException(); //TODO: access denied 1873 1874 SetStreamMediaType_Impl( m_xObjectStream, ::rtl::OUString::createFromAscii( "application/vnd.sun.star.oleobject" ) ); 1875 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream(); 1876 if ( !xOutStream.is() ) 1877 throw io::IOException(); //TODO: access denied 1878 1879 if ( m_bIsLink ) 1880 { 1881 // just let the link store itself 1882 // in case visual repersentation must be stored also 1883 // the procedure should be the same as for embedded objects 1884 1885 uno::Reference< io::XOutputStream > xOutStream = GetStreamForSaving(); 1886 1887 // should the component detect that it is a link??? 1888 StoreObjectToStream( xOutStream ); 1889 } 1890 else 1891 { 1892 uno::Reference< io::XOutputStream > xOutStream = GetStreamForSaving(); 1893 StoreObjectToStream( xOutStream ); 1894 } 1895 1896 // the replacement is changed probably, and it must be in the object stream 1897 if ( !m_pOleComponent->IsWorkaroundActive() ) 1898 m_xCachedVisualRepresentation = uno::Reference< io::XStream >(); 1899 SetVisReplInStream( sal_True ); 1900 } 1901 #endif 1902 1903 if ( m_bStoreVisRepl != HasVisReplInStream() ) 1904 { 1905 if ( m_bStoreVisRepl ) 1906 { 1907 // the m_xCachedVisualRepresentation must be set or it should be already stored 1908 if ( m_xCachedVisualRepresentation.is() ) 1909 InsertVisualCache_Impl( m_xObjectStream, m_xCachedVisualRepresentation ); 1910 else 1911 { 1912 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream ); 1913 OSL_ENSURE( m_xCachedVisualRepresentation.is(), "No representation is available!" ); 1914 } 1915 } 1916 else 1917 { 1918 if ( !m_xCachedVisualRepresentation.is() ) 1919 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream ); 1920 RemoveVisualCache_Impl( m_xObjectStream ); 1921 } 1922 1923 SetVisReplInStream( m_bStoreVisRepl ); 1924 } 1925 1926 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded ) 1927 { 1928 // the object replacement image should be updated, so the cached size as well 1929 m_bHasCachedSize = sal_False; 1930 try 1931 { 1932 // the call will cache the size in case of success 1933 // probably it might need to be done earlier, while the object is in active state 1934 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); 1935 } 1936 catch( uno::Exception& ) 1937 {} 1938 } 1939 1940 aGuard.clear(); 1941 1942 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnSaveDone" ) ); 1943 1944 // the object can be changed only on Windows 1945 // the notification should be done only if the object is not in loaded state 1946 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded ) 1947 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnVisAreaChanged" ) ); 1948 } 1949 1950 //------------------------------------------------------ 1951 sal_Bool SAL_CALL OleEmbeddedObject::isReadonly() 1952 throw ( embed::WrongStateException, 1953 uno::RuntimeException ) 1954 { 1955 // begin wrapping related part ==================== 1956 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 1957 if ( xWrappedObject.is() ) 1958 { 1959 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 1960 return xWrappedObject->isReadonly(); 1961 } 1962 // end wrapping related part ==================== 1963 1964 ::osl::MutexGuard aGuard( m_aMutex ); 1965 if ( m_bDisposed ) 1966 throw lang::DisposedException(); // TODO 1967 1968 if ( m_nObjectState == -1 ) 1969 { 1970 // the object is still not loaded 1971 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ), 1972 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1973 } 1974 1975 if ( m_bWaitSaveCompleted ) 1976 throw embed::WrongStateException( 1977 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 1978 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 1979 1980 return m_bReadOnly; 1981 } 1982 1983 //------------------------------------------------------ 1984 void SAL_CALL OleEmbeddedObject::reload( 1985 const uno::Sequence< beans::PropertyValue >& lArguments, 1986 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 1987 throw ( lang::IllegalArgumentException, 1988 embed::WrongStateException, 1989 io::IOException, 1990 uno::Exception, 1991 uno::RuntimeException ) 1992 { 1993 // begin wrapping related part ==================== 1994 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 1995 if ( xWrappedObject.is() ) 1996 { 1997 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 1998 xWrappedObject->reload( lArguments, lObjArgs ); 1999 return; 2000 } 2001 // end wrapping related part ==================== 2002 2003 // TODO: use lObjArgs 2004 2005 ::osl::MutexGuard aGuard( m_aMutex ); 2006 if ( m_bDisposed ) 2007 throw lang::DisposedException(); // TODO 2008 2009 if ( m_nObjectState == -1 ) 2010 { 2011 // the object is still not loaded 2012 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ), 2013 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 2014 } 2015 2016 if ( m_bWaitSaveCompleted ) 2017 throw embed::WrongStateException( 2018 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 2019 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 2020 2021 // TODO: 2022 // throw away current document 2023 // load new document from current storage 2024 // use meaningfull part of lArguments 2025 } 2026 2027 //------------------------------------------------------ 2028 void SAL_CALL OleEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage, 2029 const ::rtl::OUString& sEntName ) 2030 throw ( lang::IllegalArgumentException, 2031 embed::WrongStateException, 2032 io::IOException, 2033 uno::Exception, 2034 uno::RuntimeException ) 2035 { 2036 // begin wrapping related part ==================== 2037 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 2038 if ( xWrappedObject.is() ) 2039 { 2040 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 2041 xWrappedObject->breakLink( xStorage, sEntName ); 2042 return; 2043 } 2044 // end wrapping related part ==================== 2045 2046 ::osl::MutexGuard aGuard( m_aMutex ); 2047 if ( m_bDisposed ) 2048 throw lang::DisposedException(); // TODO 2049 2050 if ( !xStorage.is() ) 2051 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 2052 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 2053 1 ); 2054 2055 if ( !sEntName.getLength() ) 2056 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 2057 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 2058 2 ); 2059 2060 // TODO: The object must be at least in Running state; 2061 if ( !m_bIsLink || m_nObjectState == -1 || !m_pOleComponent ) 2062 { 2063 // it must be a linked initialized object 2064 throw embed::WrongStateException( 2065 ::rtl::OUString::createFromAscii( "The object is not a valid linked object!\n" ), 2066 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 2067 } 2068 2069 if ( m_bReadOnly ) 2070 throw io::IOException(); // TODO: Access denied 2071 2072 if ( m_bWaitSaveCompleted ) 2073 throw embed::WrongStateException( 2074 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 2075 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 2076 2077 2078 #ifdef WNT 2079 if ( m_pOleComponent ) 2080 { 2081 // TODO: create an object based on the link 2082 2083 // disconnect the old temporary URL 2084 ::rtl::OUString aOldTempURL = m_aTempURL; 2085 m_aTempURL = ::rtl::OUString(); 2086 2087 OleComponent* pNewOleComponent = new OleComponent( m_xFactory, this ); 2088 try { 2089 pNewOleComponent->InitEmbeddedCopyOfLink( m_pOleComponent ); 2090 } 2091 catch ( uno::Exception& ) 2092 { 2093 delete pNewOleComponent; 2094 if ( m_aTempURL ) 2095 KillFile_Impl( m_aTempURL, m_xFactory ); 2096 m_aTempURL = aOldTempURL; 2097 throw; 2098 } 2099 2100 try { 2101 GetRidOfComponent(); 2102 } 2103 catch( uno::Exception& ) 2104 { 2105 delete pNewOleComponent; 2106 if ( m_aTempURL ) 2107 KillFile_Impl( m_aTempURL, m_xFactory ); 2108 m_aTempURL = aOldTempURL; 2109 throw; 2110 } 2111 2112 KillFile_Impl( aOldTempURL, m_xFactory ); 2113 2114 CreateOleComponent_Impl( pNewOleComponent ); 2115 2116 if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) 2117 SwitchOwnPersistence( xStorage, sEntName ); 2118 2119 if ( m_nObjectState != embed::EmbedStates::LOADED ) 2120 { 2121 // TODO: should we activate the new object if the link was activated? 2122 2123 sal_Int32 nTargetState = m_nObjectState; 2124 m_nObjectState = embed::EmbedStates::LOADED; 2125 2126 if ( m_nObjectState == embed::EmbedStates::RUNNING ) 2127 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed 2128 else // m_nObjectState == embed::EmbedStates::ACTIVE 2129 { 2130 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed 2131 m_pOleComponent->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN ); 2132 } 2133 2134 m_nObjectState = nTargetState; 2135 } 2136 2137 m_bIsLink = sal_False; 2138 m_aLinkURL = ::rtl::OUString(); 2139 } 2140 else 2141 #endif 2142 { 2143 throw io::IOException(); //TODO: 2144 } 2145 } 2146 2147 //------------------------------------------------------ 2148 sal_Bool SAL_CALL OleEmbeddedObject::isLink() 2149 throw ( embed::WrongStateException, 2150 uno::RuntimeException ) 2151 { 2152 // begin wrapping related part ==================== 2153 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 2154 if ( xWrappedObject.is() ) 2155 { 2156 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 2157 return xWrappedObject->isLink(); 2158 } 2159 // end wrapping related part ==================== 2160 2161 ::osl::MutexGuard aGuard( m_aMutex ); 2162 if ( m_bDisposed ) 2163 throw lang::DisposedException(); // TODO 2164 2165 return m_bIsLink; 2166 } 2167 2168 //------------------------------------------------------ 2169 ::rtl::OUString SAL_CALL OleEmbeddedObject::getLinkURL() 2170 throw ( embed::WrongStateException, 2171 uno::Exception, 2172 uno::RuntimeException ) 2173 { 2174 // begin wrapping related part ==================== 2175 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); 2176 if ( xWrappedObject.is() ) 2177 { 2178 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 2179 return xWrappedObject->getLinkURL(); 2180 } 2181 // end wrapping related part ==================== 2182 2183 ::osl::MutexGuard aGuard( m_aMutex ); 2184 if ( m_bDisposed ) 2185 throw lang::DisposedException(); // TODO 2186 2187 if ( m_bWaitSaveCompleted ) 2188 throw embed::WrongStateException( 2189 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), 2190 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 2191 2192 if ( !m_bIsLink ) 2193 throw embed::WrongStateException( 2194 ::rtl::OUString::createFromAscii( "The object is not a link object!\n" ), 2195 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 2196 2197 // TODO: probably the link URL can be retrieved from OLE 2198 2199 return m_aLinkURL; 2200 } 2201 2202