build fix
[LibreOffice.git] / embeddedobj / source / msole / olepersist.cxx
blobeb5737db49445c484d838e578fe37c41ba9c51f4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <oleembobj.hxx>
21 #include <olepersist.hxx>
22 #include <com/sun/star/embed/EmbedStates.hpp>
23 #include <com/sun/star/embed/EmbedVerbs.hpp>
24 #include <com/sun/star/embed/EntryInitModes.hpp>
25 #include <com/sun/star/embed/XStorage.hpp>
26 #include <com/sun/star/embed/XTransactedObject.hpp>
27 #include <com/sun/star/embed/ElementModes.hpp>
28 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
29 #include <com/sun/star/embed/Aspects.hpp>
30 #include <com/sun/star/embed/XOptimizedStorage.hpp>
31 #include <com/sun/star/lang/XComponent.hpp>
32 #include <com/sun/star/lang/DisposedException.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/container/XNameContainer.hpp>
35 #include <com/sun/star/io/TempFile.hpp>
36 #include <com/sun/star/io/XSeekable.hpp>
37 #include <com/sun/star/io/XTruncate.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/storagehelper.hxx>
43 #include <comphelper/mimeconfighelper.hxx>
44 #include <comphelper/classids.hxx>
45 #include <osl/diagnose.h>
46 #include <osl/thread.hxx>
48 #include <closepreventer.hxx>
50 #if defined(_WIN32)
51 #include <olecomponent.hxx>
52 #endif
54 using namespace ::com::sun::star;
55 using namespace ::comphelper;
58 bool KillFile_Impl( const OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
60 if ( !xFactory.is() )
61 return false;
63 bool bRet = false;
65 try
67 uno::Reference < ucb::XSimpleFileAccess3 > xAccess(
68 ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory) ) );
70 xAccess->kill( aURL );
71 bRet = true;
73 catch( const uno::Exception& )
77 return bRet;
81 OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
83 SAL_WARN_IF( !xFactory.is(), "embeddedobj.ole", "No factory is provided!" );
85 OUString aResult;
87 uno::Reference < beans::XPropertySet > xTempFile(
88 io::TempFile::create(comphelper::getComponentContext(xFactory)),
89 uno::UNO_QUERY_THROW );
91 try {
92 xTempFile->setPropertyValue("RemoveFile", uno::makeAny( false ) );
93 uno::Any aUrl = xTempFile->getPropertyValue("Uri");
94 aUrl >>= aResult;
96 catch ( const uno::Exception& )
100 if ( aResult.isEmpty() )
101 throw uno::RuntimeException(); // TODO: can not create tempfile
103 return aResult;
107 OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream,
108 const uno::Reference< lang::XMultiServiceFactory >& xFactory )
109 throw ( io::IOException,
110 uno::RuntimeException )
112 OSL_ENSURE( xInStream.is() && xFactory.is(), "Wrong parameters are provided!\n" );
114 OUString aResult = GetNewTempFileURL_Impl( xFactory );
116 if ( !aResult.isEmpty() )
118 try {
119 uno::Reference < ucb::XSimpleFileAccess3 > xTempAccess(
120 ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory) ) );
122 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aResult );
123 if ( xTempOutStream.is() )
125 // copy stream contents to the file
126 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
127 xTempOutStream->closeOutput();
128 xTempOutStream.clear();
130 else
131 throw io::IOException(); // TODO:
133 catch( const packages::WrongPasswordException& )
135 KillFile_Impl( aResult, xFactory );
136 throw io::IOException(); //TODO:
138 catch( const io::IOException& )
140 KillFile_Impl( aResult, xFactory );
141 throw;
143 catch( const uno::RuntimeException& )
145 KillFile_Impl( aResult, xFactory );
146 throw;
148 catch( const uno::Exception& )
150 KillFile_Impl( aResult, xFactory );
151 aResult.clear();
155 return aResult;
157 #ifdef _WIN32
158 OUString GetNewFilledTempFile_Impl( const uno::Reference< embed::XOptimizedStorage >& xParentStorage, const OUString& aEntryName, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
159 throw( io::IOException, uno::RuntimeException )
161 OUString aResult;
165 uno::Reference < beans::XPropertySet > xTempFile(
166 io::TempFile::create(comphelper::getComponentContext(xFactory)),
167 uno::UNO_QUERY );
168 uno::Reference < io::XStream > xTempStream( xTempFile, uno::UNO_QUERY_THROW );
170 xParentStorage->copyStreamElementData( aEntryName, xTempStream );
172 xTempFile->setPropertyValue("RemoveFile", uno::makeAny( false ) );
173 uno::Any aUrl = xTempFile->getPropertyValue("Uri");
174 aUrl >>= aResult;
176 catch( const uno::RuntimeException& )
178 throw;
180 catch( const uno::Exception& )
184 if ( aResult.isEmpty() )
185 throw io::IOException();
187 return aResult;
191 void SetStreamMediaType_Impl( const uno::Reference< io::XStream >& xStream, const OUString& aMediaType )
193 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY );
194 if ( !xPropSet.is() )
195 throw uno::RuntimeException(); // TODO: all the storage streams must support XPropertySet
197 xPropSet->setPropertyValue("MediaType", uno::makeAny( aMediaType ) );
199 #endif
201 void LetCommonStoragePassBeUsed_Impl( const uno::Reference< io::XStream >& xStream )
203 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY );
204 if ( !xPropSet.is() )
205 throw uno::RuntimeException(); // Only StorageStreams must be provided here, they must implement the interface
207 xPropSet->setPropertyValue("UseCommonStoragePasswordEncryption",
208 uno::makeAny( true ) );
210 #ifdef _WIN32
212 void VerbExecutionController::StartControlExecution()
214 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
216 // the class is used to detect STAMPIT object, that can never be active
217 if ( !m_bVerbExecutionInProgress && !m_bWasEverActive )
219 m_bVerbExecutionInProgress = true;
220 m_nVerbExecutionThreadIdentifier = osl::Thread::getCurrentIdentifier();
221 m_bChangedOnVerbExecution = false;
226 bool VerbExecutionController::EndControlExecution_WasModified()
228 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
230 bool bResult = false;
231 if ( m_bVerbExecutionInProgress && m_nVerbExecutionThreadIdentifier == osl::Thread::getCurrentIdentifier() )
233 bResult = m_bChangedOnVerbExecution;
234 m_bVerbExecutionInProgress = false;
237 return bResult;
241 void VerbExecutionController::ModificationNotificationIsDone()
243 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
245 if ( m_bVerbExecutionInProgress && osl::Thread::getCurrentIdentifier() == m_nVerbExecutionThreadIdentifier )
246 m_bChangedOnVerbExecution = true;
248 #endif
250 void VerbExecutionController::LockNotification()
252 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
253 if ( m_nNotificationLock < SAL_MAX_INT32 )
254 m_nNotificationLock++;
258 void VerbExecutionController::UnlockNotification()
260 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
261 if ( m_nNotificationLock > 0 )
262 m_nNotificationLock--;
266 uno::Reference< io::XStream > OleEmbeddedObject::GetNewFilledTempStream_Impl( const uno::Reference< io::XInputStream >& xInStream )
267 throw( io::IOException, uno::RuntimeException )
269 SAL_WARN_IF( !xInStream.is(), "embeddedobj.ole", "Wrong parameter is provided!" );
271 uno::Reference < io::XStream > xTempFile(
272 io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
273 uno::UNO_QUERY_THROW );
275 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream();
276 if ( xTempOutStream.is() )
278 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
279 xTempOutStream->flush();
281 else
282 throw io::IOException(); // TODO:
284 return xTempFile;
288 uno::Reference< io::XStream > OleEmbeddedObject::TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream )
289 throw ( uno::Exception )
291 // TODO/LATER: Actually this should be done by a centralized component ( may be a graphical filter )
292 if ( !m_xFactory.is() )
293 throw uno::RuntimeException();
295 uno::Reference< io::XInputStream > xInStream = xStream->getInputStream();
296 if ( !xInStream.is() )
297 throw uno::RuntimeException();
299 uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW );
300 xSeek->seek( 0 );
302 uno::Sequence< sal_Int8 > aData( 8 );
303 sal_Int32 nRead = xInStream->readBytes( aData, 8 );
304 xSeek->seek( 0 );
306 if ( ( nRead >= 2 && aData[0] == 'B' && aData[1] == 'M' )
307 || ( nRead >= 4 && aData[0] == 1 && aData[1] == 0 && aData[2] == 9 && aData[3] == 0 ) )
309 // it should be a bitmap or a Metafile
310 return xStream;
314 sal_uInt32 nHeaderOffset = 0;
315 if ( ( nRead >= 8 && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1 )
316 && ( aData[4] == 2 || aData[4] == 3 || aData[4] == 14 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 )
318 nHeaderOffset = 40;
319 xSeek->seek( 8 );
321 // TargetDevice might be used in future, currently the cache has specified NULL
322 uno::Sequence< sal_Int8 > aHeadData( 4 );
323 nRead = xInStream->readBytes( aHeadData, 4 );
324 sal_uInt32 nLen = 0;
325 if ( nRead == 4 && aHeadData.getLength() == 4 )
326 nLen = ( ( ( (sal_uInt32)aHeadData[3] * 0x100 + (sal_uInt32)aHeadData[2] ) * 0x100 ) + (sal_uInt32)aHeadData[1] ) * 0x100 + (sal_uInt32)aHeadData[0];
327 if ( nLen > 4 )
329 xInStream->skipBytes( nLen - 4 );
330 nHeaderOffset += nLen - 4;
334 else if ( nRead > 4 )
336 // check whether the first bytes represent the size
337 sal_uInt32 nSize = 0;
338 for ( sal_Int32 nInd = 3; nInd >= 0; nInd-- )
339 nSize = ( nSize << 8 ) + (sal_uInt8)aData[nInd];
341 if ( nSize == xSeek->getLength() - 4 )
342 nHeaderOffset = 4;
345 if ( nHeaderOffset )
347 // this is either a bitmap or a metafile clipboard format, retrieve the pure stream
348 uno::Reference < io::XStream > xResult(
349 io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
350 uno::UNO_QUERY_THROW );
351 uno::Reference < io::XSeekable > xResultSeek( xResult, uno::UNO_QUERY_THROW );
352 uno::Reference < io::XOutputStream > xResultOut = xResult->getOutputStream();
353 uno::Reference < io::XInputStream > xResultIn = xResult->getInputStream();
354 if ( !xResultOut.is() || !xResultIn.is() )
355 throw uno::RuntimeException();
357 xSeek->seek( nHeaderOffset ); // header size for these formats
358 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xResultOut );
359 xResultOut->closeOutput();
360 xResultSeek->seek( 0 );
361 xSeek->seek( 0 );
363 return xResult;
366 return uno::Reference< io::XStream >();
370 void OleEmbeddedObject::InsertVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream,
371 const uno::Reference< io::XStream >& xCachedVisualRepresentation )
372 throw ( uno::Exception )
374 OSL_ENSURE( xTargetStream.is() && xCachedVisualRepresentation.is(), "Invalid arguments!\n" );
376 if ( !xTargetStream.is() || !xCachedVisualRepresentation.is() )
377 throw uno::RuntimeException();
379 uno::Sequence< uno::Any > aArgs( 2 );
380 aArgs[0] <<= xTargetStream;
381 aArgs[1] <<= true; // do not create copy
383 uno::Reference< container::XNameContainer > xNameContainer(
384 m_xFactory->createInstanceWithArguments(
385 "com.sun.star.embed.OLESimpleStorage",
386 aArgs ),
387 uno::UNO_QUERY );
389 if ( !xNameContainer.is() )
390 throw uno::RuntimeException();
392 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY_THROW );
393 if ( xCachedSeek.is() )
394 xCachedSeek->seek( 0 );
396 uno::Reference < io::XStream > xTempFile(
397 io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
398 uno::UNO_QUERY_THROW );
400 uno::Reference< io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW );
401 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream();
402 if ( xTempOutStream.is() )
404 // the OlePres stream must have additional header
405 // TODO/LATER: might need to be extended in future (actually makes sense only for SO7 format)
406 uno::Reference< io::XInputStream > xInCacheStream = xCachedVisualRepresentation->getInputStream();
407 if ( !xInCacheStream.is() )
408 throw uno::RuntimeException();
410 // write 0xFFFFFFFF at the beginning
411 uno::Sequence< sal_Int8 > aData( 4 );
412 *( reinterpret_cast<sal_uInt32*>(aData.getArray()) ) = 0xFFFFFFFF;
414 xTempOutStream->writeBytes( aData );
416 // write clipboard format
417 uno::Sequence< sal_Int8 > aSigData( 2 );
418 xInCacheStream->readBytes( aSigData, 2 );
419 if ( aSigData.getLength() < 2 )
420 throw io::IOException();
422 if ( aSigData[0] == 'B' && aSigData[1] == 'M' )
424 // it's a bitmap
425 aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0;
427 else
429 // treat it as a metafile
430 aData[0] = 0x03; aData[1] = 0; aData[2] = 0; aData[3] = 0;
432 xTempOutStream->writeBytes( aData );
434 // write job related information
435 aData[0] = 0x04; aData[1] = 0; aData[2] = 0; aData[3] = 0;
436 xTempOutStream->writeBytes( aData );
438 // write aspect
439 aData[0] = 0x01; aData[1] = 0; aData[2] = 0; aData[3] = 0;
440 xTempOutStream->writeBytes( aData );
442 // write l-index
443 *( reinterpret_cast<sal_uInt32*>(aData.getArray()) ) = 0xFFFFFFFF;
444 xTempOutStream->writeBytes( aData );
446 // write adv. flags
447 aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0;
448 xTempOutStream->writeBytes( aData );
450 // write compression
451 *( reinterpret_cast<sal_uInt32*>(aData.getArray()) ) = 0x0;
452 xTempOutStream->writeBytes( aData );
454 // get the size
455 awt::Size aSize = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
456 sal_Int32 nIndex = 0;
458 // write width
459 for ( nIndex = 0; nIndex < 4; nIndex++ )
461 aData[nIndex] = (sal_Int8)( aSize.Width % 0x100 );
462 aSize.Width /= 0x100;
464 xTempOutStream->writeBytes( aData );
466 // write height
467 for ( nIndex = 0; nIndex < 4; nIndex++ )
469 aData[nIndex] = (sal_Int8)( aSize.Height % 0x100 );
470 aSize.Height /= 0x100;
472 xTempOutStream->writeBytes( aData );
474 // write garbage, it will be overwritten by the size
475 xTempOutStream->writeBytes( aData );
477 // write first bytes that was used to detect the type
478 xTempOutStream->writeBytes( aSigData );
480 // write the rest of the stream
481 ::comphelper::OStorageHelper::CopyInputToOutput( xInCacheStream, xTempOutStream );
483 // write the size of the stream
484 sal_Int64 nLength = xTempSeek->getLength() - 40;
485 if ( nLength < 0 || nLength >= 0xFFFFFFFF )
487 SAL_WARN( "embeddedobj.ole", "Length is not acceptable!" );
488 return;
490 for ( sal_Int32 nInd = 0; nInd < 4; nInd++ )
492 aData[nInd] = (sal_Int8)( ( (sal_uInt64) nLength ) % 0x100 );
493 nLength /= 0x100;
495 xTempSeek->seek( 36 );
496 xTempOutStream->writeBytes( aData );
498 xTempOutStream->flush();
500 xTempSeek->seek( 0 );
501 if ( xCachedSeek.is() )
502 xCachedSeek->seek( 0 );
504 else
505 throw io::IOException(); // TODO:
507 // insert the result file as replacement image
508 OUString aCacheName = "\002OlePres000";
509 if ( xNameContainer->hasByName( aCacheName ) )
510 xNameContainer->replaceByName( aCacheName, uno::makeAny( xTempFile ) );
511 else
512 xNameContainer->insertByName( aCacheName, uno::makeAny( xTempFile ) );
514 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY );
515 if ( !xTransacted.is() )
516 throw uno::RuntimeException();
518 xTransacted->commit();
522 void OleEmbeddedObject::RemoveVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream )
523 throw ( uno::Exception )
525 OSL_ENSURE( xTargetStream.is(), "Invalid argument!\n" );
526 if ( !xTargetStream.is() )
527 throw uno::RuntimeException();
529 uno::Sequence< uno::Any > aArgs( 2 );
530 aArgs[0] <<= xTargetStream;
531 aArgs[1] <<= true; // do not create copy
532 uno::Reference< container::XNameContainer > xNameContainer(
533 m_xFactory->createInstanceWithArguments(
534 "com.sun.star.embed.OLESimpleStorage",
535 aArgs ),
536 uno::UNO_QUERY );
538 if ( !xNameContainer.is() )
539 throw uno::RuntimeException();
541 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ )
543 OUString aStreamName = "\002OlePres00" + OUString::number( nInd );
544 if ( xNameContainer->hasByName( aStreamName ) )
545 xNameContainer->removeByName( aStreamName );
548 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY );
549 if ( !xTransacted.is() )
550 throw uno::RuntimeException();
552 xTransacted->commit();
556 void OleEmbeddedObject::SetVisReplInStream( bool bExists )
558 m_bVisReplInitialized = true;
559 m_bVisReplInStream = bExists;
563 bool OleEmbeddedObject::HasVisReplInStream()
565 if ( !m_bVisReplInitialized )
567 if ( m_xCachedVisualRepresentation.is() )
568 SetVisReplInStream( true );
569 else
571 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::HasVisualReplInStream, analyzing" );
573 uno::Reference< io::XInputStream > xStream;
575 OSL_ENSURE( !m_pOleComponent || !m_aTempURL.isEmpty(), "The temporary file must exist if there is a component!\n" );
576 if ( !m_aTempURL.isEmpty() )
580 // open temporary file for reading
581 uno::Reference < ucb::XSimpleFileAccess3 > xTempAccess(
582 ucb::SimpleFileAccess::create( comphelper::getComponentContext(m_xFactory) ) );
584 xStream = xTempAccess->openFileRead( m_aTempURL );
586 catch( const uno::Exception& )
590 if ( !xStream.is() )
591 xStream = m_xObjectStream->getInputStream();
593 if ( xStream.is() )
595 bool bExists = false;
597 uno::Sequence< uno::Any > aArgs( 2 );
598 aArgs[0] <<= xStream;
599 aArgs[1] <<= true; // do not create copy
600 uno::Reference< container::XNameContainer > xNameContainer(
601 m_xFactory->createInstanceWithArguments(
602 "com.sun.star.embed.OLESimpleStorage",
603 aArgs ),
604 uno::UNO_QUERY );
606 if ( xNameContainer.is() )
608 for ( sal_uInt8 nInd = 0; nInd < 10 && !bExists; nInd++ )
610 OUString aStreamName = "\002OlePres00" + OUString::number( nInd );
613 bExists = xNameContainer->hasByName( aStreamName );
615 catch( const uno::Exception& )
620 SetVisReplInStream( bExists );
625 return m_bVisReplInStream;
629 uno::Reference< io::XStream > OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation_Impl(
630 const uno::Reference< io::XStream >& xStream,
631 bool bAllowToRepair50 )
632 throw ()
634 uno::Reference< io::XStream > xResult;
636 if ( xStream.is() )
638 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation, retrieving" );
640 uno::Reference< container::XNameContainer > xNameContainer;
641 uno::Sequence< uno::Any > aArgs( 2 );
642 aArgs[0] <<= xStream;
643 aArgs[1] <<= true; // do not create copy
646 xNameContainer.set(
647 m_xFactory->createInstanceWithArguments(
648 "com.sun.star.embed.OLESimpleStorage",
649 aArgs ),
650 uno::UNO_QUERY );
652 catch( const uno::Exception& )
655 if ( xNameContainer.is() )
657 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ )
659 OUString aStreamName = "\002OlePres00" + OUString::number( nInd );
660 uno::Reference< io::XStream > xCachedCopyStream;
663 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() )
665 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream );
666 if ( xResult.is() )
667 break;
670 catch( const uno::Exception& )
673 if ( nInd == 0 )
675 // to be compatible with the old versions Ole10Native is checked after OlePress000
676 aStreamName = "\001Ole10Native";
679 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() )
681 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream );
682 if ( xResult.is() )
683 break;
686 catch( const uno::Exception& )
693 if ( bAllowToRepair50 && !xResult.is() )
695 OUString aOrigContName( "Ole-Object" );
696 if ( xNameContainer->hasByName( aOrigContName ) )
698 uno::Reference< embed::XClassifiedObject > xClassified( xNameContainer, uno::UNO_QUERY_THROW );
699 if ( MimeConfigurationHelper::ClassIDsEqual( xClassified->getClassID(), MimeConfigurationHelper::GetSequenceClassID( SO3_OUT_CLASSID ) ) )
701 // this is an OLE object wrongly stored in 5.0 format
702 // this object must be repaired since SO7 has done it
704 uno::Reference< io::XOutputStream > xOutputStream = xStream->getOutputStream();
705 uno::Reference< io::XTruncate > xTruncate( xOutputStream, uno::UNO_QUERY_THROW );
707 uno::Reference< io::XInputStream > xOrigInputStream;
708 if ( ( xNameContainer->getByName( aOrigContName ) >>= xOrigInputStream )
709 && xOrigInputStream.is() )
711 // the provided input stream must be based on temporary medium and must be independent
712 // from the stream the storage is based on
713 uno::Reference< io::XSeekable > xOrigSeekable( xOrigInputStream, uno::UNO_QUERY );
714 if ( xOrigSeekable.is() )
715 xOrigSeekable->seek( 0 );
717 uno::Reference< lang::XComponent > xNameContDisp( xNameContainer, uno::UNO_QUERY_THROW );
718 xNameContDisp->dispose(); // free the original stream
720 xTruncate->truncate();
721 ::comphelper::OStorageHelper::CopyInputToOutput( xOrigInputStream, xOutputStream );
722 xOutputStream->flush();
724 if ( xStream == m_xObjectStream )
726 if ( !m_aTempURL.isEmpty() )
728 // this is the own stream, so the temporary URL must be cleaned if it exists
729 KillFile_Impl( m_aTempURL, m_xFactory );
730 m_aTempURL.clear();
733 #ifdef _WIN32
734 // retry to create the component after recovering
735 GetRidOfComponent();
739 CreateOleComponentAndLoad_Impl();
740 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction
742 catch( const uno::Exception& )
744 GetRidOfComponent();
746 #endif
749 xResult = TryToRetrieveCachedVisualRepresentation_Impl( xStream );
755 catch( const uno::Exception& )
760 return xResult;
764 void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
765 const uno::Reference< io::XStream >& xNewObjectStream,
766 const OUString& aNewName )
768 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
770 SAL_WARN_IF( xNewObjectStream != m_xObjectStream, "embeddedobj.ole", "The streams must be the same!" );
771 return;
774 try {
775 uno::Reference< lang::XComponent > xComponent( m_xObjectStream, uno::UNO_QUERY );
776 OSL_ENSURE( !m_xObjectStream.is() || xComponent.is(), "Wrong stream implementation!" );
777 if ( xComponent.is() )
778 xComponent->dispose();
780 catch ( const uno::Exception& )
784 m_xObjectStream = xNewObjectStream;
785 m_xParentStorage = xNewParentStorage;
786 m_aEntryName = aNewName;
790 void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
791 const OUString& aNewName )
793 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
794 return;
796 sal_Int32 nStreamMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
798 uno::Reference< io::XStream > xNewOwnStream = xNewParentStorage->openStreamElement( aNewName, nStreamMode );
799 SAL_WARN_IF( !xNewOwnStream.is(), "embeddedobj.ole", "The method can not return empty reference!" );
801 SwitchOwnPersistence( xNewParentStorage, xNewOwnStream, aNewName );
804 #ifdef _WIN32
806 bool OleEmbeddedObject::SaveObject_Impl()
808 bool bResult = false;
810 if ( m_xClientSite.is() )
814 m_xClientSite->saveObject();
815 bResult = true;
817 catch( const uno::Exception& )
822 return bResult;
826 bool OleEmbeddedObject::OnShowWindow_Impl( bool bShow )
828 ::osl::ResettableMutexGuard aGuard( m_aMutex );
830 bool bResult = false;
832 SAL_WARN_IF( m_nObjectState == -1, "embeddedobj.ole", "The object has no persistence!" );
833 SAL_WARN_IF( m_nObjectState == embed::EmbedStates::LOADED, "embeddedobj.ole", "The object get OnShowWindow in loaded state!" );
834 if ( m_nObjectState == -1 || m_nObjectState == embed::EmbedStates::LOADED )
835 return false;
837 // the object is either activated or deactivated
838 sal_Int32 nOldState = m_nObjectState;
839 if ( bShow && m_nObjectState == embed::EmbedStates::RUNNING )
841 m_nObjectState = embed::EmbedStates::ACTIVE;
842 m_aVerbExecutionController.ObjectIsActive();
844 aGuard.clear();
845 StateChangeNotification_Impl( false, nOldState, m_nObjectState );
847 else if ( !bShow && m_nObjectState == embed::EmbedStates::ACTIVE )
849 m_nObjectState = embed::EmbedStates::RUNNING;
850 aGuard.clear();
851 StateChangeNotification_Impl( false, nOldState, m_nObjectState );
854 if ( m_xClientSite.is() )
858 m_xClientSite->visibilityChanged( bShow );
859 bResult = true;
861 catch( const uno::Exception& )
866 return bResult;
870 void OleEmbeddedObject::OnIconChanged_Impl()
872 // TODO/LATER: currently this notification seems to be impossible
873 // MakeEventListenerNotification_Impl( OUString( "OnIconChanged" ) );
877 void OleEmbeddedObject::OnViewChanged_Impl()
879 if ( m_bDisposed )
880 throw lang::DisposedException();
882 // For performance reasons the notification currently is ignored, STAMPIT object is the exception,
883 // it can never be active and never call SaveObject, so it is the only way to detect that it is changed
885 // ==== the STAMPIT related solution =============================
886 // the following variable is used to detect whether the object was modified during verb execution
887 m_aVerbExecutionController.ModificationNotificationIsDone();
889 // The following things are controlled by VerbExecutionController:
890 // - if the verb execution is in progress and the view is changed the object will be stored
891 // after the execution, so there is no need to send the notification.
892 // - the STAMPIT object can never be active.
893 if (m_aVerbExecutionController.CanDoNotification() &&
894 m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE &&
895 (MimeConfigurationHelper::ClassIDsEqual(m_aClassID, MimeConfigurationHelper::GetSequenceClassID(0x852ee1c9, 0x9058, 0x44ba, 0x8c, 0x6c, 0x0c, 0x5f, 0xc6, 0x6b, 0xdb, 0x8d)) ||
896 MimeConfigurationHelper::ClassIDsEqual(m_aClassID, MimeConfigurationHelper::GetSequenceClassID(0xcf1b4491, 0xbea3, 0x4c9f, 0xa7, 0x0f, 0x22, 0x1b, 0x1e, 0xca, 0xef, 0x3e)))
899 // The view is changed while the object is in running state, save the new object
900 m_xCachedVisualRepresentation.clear();
901 SaveObject_Impl();
902 MakeEventListenerNotification_Impl( "OnVisAreaChanged" );
908 void OleEmbeddedObject::OnClosed_Impl()
910 if ( m_bDisposed )
911 throw lang::DisposedException();
913 if ( m_nObjectState != embed::EmbedStates::LOADED )
915 sal_Int32 nOldState = m_nObjectState;
916 m_nObjectState = embed::EmbedStates::LOADED;
917 StateChangeNotification_Impl( false, nOldState, m_nObjectState );
922 OUString OleEmbeddedObject::CreateTempURLEmpty_Impl()
924 SAL_WARN_IF( !m_aTempURL.isEmpty(), "embeddedobj.ole", "The object has already the temporary file!" );
925 m_aTempURL = GetNewTempFileURL_Impl( m_xFactory );
927 return m_aTempURL;
931 OUString OleEmbeddedObject::GetTempURL_Impl()
933 if ( m_aTempURL.isEmpty() )
935 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::GetTempURL_Impl, tempfile creation" );
937 // if there is no temporary file, it will be created from the own entry
938 uno::Reference< embed::XOptimizedStorage > xOptParStorage( m_xParentStorage, uno::UNO_QUERY );
939 if ( xOptParStorage.is() )
941 m_aTempURL = GetNewFilledTempFile_Impl( xOptParStorage, m_aEntryName, m_xFactory );
943 else if ( m_xObjectStream.is() )
945 // load object from the stream
946 uno::Reference< io::XInputStream > xInStream = m_xObjectStream->getInputStream();
947 if ( !xInStream.is() )
948 throw io::IOException(); // TODO: access denied
950 m_aTempURL = GetNewFilledTempFile_Impl( xInStream, m_xFactory );
954 return m_aTempURL;
958 void OleEmbeddedObject::CreateOleComponent_Impl( OleComponent* pOleComponent )
960 if ( !m_pOleComponent )
962 m_pOleComponent = pOleComponent ? pOleComponent : new OleComponent( m_xFactory, this );
963 m_pOleComponent->acquire(); // TODO: needs holder?
965 if ( !m_xClosePreventer.is() )
966 m_xClosePreventer.set( static_cast< ::cppu::OWeakObject* >( new OClosePreventer ),
967 uno::UNO_QUERY );
969 m_pOleComponent->addCloseListener( m_xClosePreventer );
974 void OleEmbeddedObject::CreateOleComponentAndLoad_Impl( OleComponent* pOleComponent )
976 if ( !m_pOleComponent )
978 if ( !m_xObjectStream.is() )
979 throw uno::RuntimeException();
981 CreateOleComponent_Impl( pOleComponent );
983 // after the loading the object can appear as a link
984 // will be detected later by olecomponent
986 GetTempURL_Impl();
987 if ( m_aTempURL.isEmpty() )
988 throw uno::RuntimeException(); // TODO
990 m_pOleComponent->LoadEmbeddedObject( m_aTempURL );
995 void OleEmbeddedObject::CreateOleComponentFromClipboard_Impl( OleComponent* pOleComponent )
997 if ( !m_pOleComponent )
999 if ( !m_xObjectStream.is() )
1000 throw uno::RuntimeException();
1002 CreateOleComponent_Impl( pOleComponent );
1004 // after the loading the object can appear as a link
1005 // will be detected later by olecomponent
1006 m_pOleComponent->CreateObjectFromClipboard();
1011 uno::Reference< io::XOutputStream > OleEmbeddedObject::GetStreamForSaving()
1013 if ( !m_xObjectStream.is() )
1014 throw uno::RuntimeException(); //TODO:
1016 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream();
1017 if ( !xOutStream.is() )
1018 throw io::IOException(); //TODO: access denied
1020 uno::Reference< io::XTruncate > xTruncate( xOutStream, uno::UNO_QUERY );
1021 if ( !xTruncate.is() )
1022 throw uno::RuntimeException(); //TODO:
1024 xTruncate->truncate();
1026 return xOutStream;
1030 void OleEmbeddedObject::StoreObjectToStream( uno::Reference< io::XOutputStream > const & xOutStream )
1031 throw ( uno::Exception )
1033 // this method should be used only on windows
1034 if ( m_pOleComponent )
1035 m_pOleComponent->StoreOwnTmpIfNecessary();
1037 // now all the changes should be in temporary location
1038 if ( m_aTempURL.isEmpty() )
1039 throw uno::RuntimeException();
1041 // open temporary file for reading
1042 uno::Reference < ucb::XSimpleFileAccess3 > xTempAccess(
1043 ucb::SimpleFileAccess::create( comphelper::getComponentContext(m_xFactory) ) );
1045 uno::Reference< io::XInputStream > xTempInStream = xTempAccess->openFileRead( m_aTempURL );
1046 SAL_WARN_IF( !xTempInStream.is(), "embeddedobj.ole", "The object's temporary file can not be reopened for reading!" );
1048 // TODO: use bStoreVisReplace
1050 if ( xTempInStream.is() )
1052 // write all the contents to XOutStream
1053 uno::Reference< io::XTruncate > xTrunc( xOutStream, uno::UNO_QUERY );
1054 if ( !xTrunc.is() )
1055 throw uno::RuntimeException(); //TODO:
1057 xTrunc->truncate();
1059 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutStream );
1061 else
1062 throw io::IOException(); // TODO:
1064 // TODO: should the view replacement be in the stream ???
1065 // probably it must be specified on storing
1067 #endif
1069 void OleEmbeddedObject::StoreToLocation_Impl(
1070 const uno::Reference< embed::XStorage >& xStorage,
1071 const OUString& sEntName,
1072 const uno::Sequence< beans::PropertyValue >& lObjArgs,
1073 bool bSaveAs )
1074 throw ( uno::Exception )
1076 // TODO: use lObjArgs
1077 // TODO: exchange StoreVisualReplacement by SO file format version?
1079 if ( m_nObjectState == -1 )
1081 // the object is still not loaded
1082 throw embed::WrongStateException( "Can't store object without persistence!",
1083 static_cast< ::cppu::OWeakObject* >(this) );
1086 if ( m_bWaitSaveCompleted )
1087 throw embed::WrongStateException(
1088 "The object waits for saveCompleted() call!",
1089 static_cast< ::cppu::OWeakObject* >(this) );
1091 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" );
1093 bool bVisReplIsStored = false;
1095 bool bTryOptimization = false;
1096 bool bStoreVis = m_bStoreVisRepl;
1097 uno::Reference< io::XStream > xCachedVisualRepresentation;
1098 for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1100 if ( lObjArgs[nInd].Name == "StoreVisualReplacement" )
1101 lObjArgs[nInd].Value >>= bStoreVis;
1102 else if ( lObjArgs[nInd].Name == "VisualReplacement" )
1103 lObjArgs[nInd].Value >>= xCachedVisualRepresentation;
1104 else if ( lObjArgs[nInd].Name == "CanTryOptimization" )
1105 lObjArgs[nInd].Value >>= bTryOptimization;
1108 // ignore visual representation provided from outside if it should not be stored
1109 if ( !bStoreVis )
1110 xCachedVisualRepresentation.clear();
1112 if ( bStoreVis && !HasVisReplInStream() && !xCachedVisualRepresentation.is() )
1113 throw io::IOException(); // TODO: there is no cached visual representation and nothing is provided from outside
1115 // if the representation is provided from outside it should be copied to a local stream
1116 bool bNeedLocalCache = xCachedVisualRepresentation.is();
1118 uno::Reference< io::XStream > xTargetStream;
1120 bool bStoreLoaded = false;
1121 if ( m_nObjectState == embed::EmbedStates::LOADED
1122 #ifdef _WIN32
1123 // if the object was NOT modified after storing it can be just copied
1124 // as if it was in loaded state
1125 || ( m_pOleComponent && !m_pOleComponent->IsDirty() )
1126 #endif
1129 bool bOptimizedCopyingDone = false;
1131 if ( bTryOptimization && bStoreVis == HasVisReplInStream() )
1135 uno::Reference< embed::XOptimizedStorage > xSourceOptStor( m_xParentStorage, uno::UNO_QUERY_THROW );
1136 uno::Reference< embed::XOptimizedStorage > xTargetOptStor( xStorage, uno::UNO_QUERY_THROW );
1137 xSourceOptStor->copyElementDirectlyTo( m_aEntryName, xTargetOptStor, sEntName );
1138 bOptimizedCopyingDone = true;
1140 catch( const uno::Exception& )
1145 if ( !bOptimizedCopyingDone )
1147 // if optimized copying fails a normal one should be tried
1148 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
1151 // the locally retrieved representation is always preferable
1152 // since the object is in loaded state the representation is unchanged
1153 if ( m_xCachedVisualRepresentation.is() )
1155 xCachedVisualRepresentation = m_xCachedVisualRepresentation;
1156 bNeedLocalCache = false;
1159 bVisReplIsStored = HasVisReplInStream();
1160 bStoreLoaded = true;
1162 #ifdef _WIN32
1163 else if ( m_pOleComponent )
1165 xTargetStream =
1166 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE );
1167 if ( !xTargetStream.is() )
1168 throw io::IOException(); //TODO: access denied
1170 SetStreamMediaType_Impl( xTargetStream, "application/vnd.sun.star.oleobject" );
1171 uno::Reference< io::XOutputStream > xOutStream = xTargetStream->getOutputStream();
1172 if ( !xOutStream.is() )
1173 throw io::IOException(); //TODO: access denied
1175 StoreObjectToStream( xOutStream );
1176 bVisReplIsStored = true;
1178 if ( bSaveAs )
1180 // no need to do it on StoreTo since in this case the replacement is in the stream
1181 // and there is no need to cache it even if it is thrown away because the object
1182 // is not changed by StoreTo action
1184 uno::Reference< io::XStream > xTmpCVRepresentation =
1185 TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1187 // the locally retrieved representation is always preferable
1188 if ( xTmpCVRepresentation.is() )
1190 xCachedVisualRepresentation = xTmpCVRepresentation;
1191 bNeedLocalCache = false;
1195 #endif
1196 else
1198 throw io::IOException(); // TODO
1201 if ( !xTargetStream.is() )
1203 xTargetStream =
1204 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE );
1205 if ( !xTargetStream.is() )
1206 throw io::IOException(); //TODO: access denied
1209 LetCommonStoragePassBeUsed_Impl( xTargetStream );
1211 if ( bStoreVis != bVisReplIsStored )
1213 if ( bStoreVis )
1215 if ( !xCachedVisualRepresentation.is() )
1216 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1218 SAL_WARN_IF( !xCachedVisualRepresentation.is(), "embeddedobj.ole", "No representation is available!" );
1220 // the following copying will be done in case it is SaveAs anyway
1221 // if it is not SaveAs the seekable access is not required currently
1222 // TODO/LATER: may be required in future
1223 if ( bSaveAs )
1225 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY );
1226 if ( !xCachedSeek.is() )
1228 xCachedVisualRepresentation
1229 = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() );
1230 bNeedLocalCache = false;
1234 InsertVisualCache_Impl( xTargetStream, xCachedVisualRepresentation );
1236 else
1238 // the removed representation could be cached by this method
1239 if ( !xCachedVisualRepresentation.is() )
1240 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1242 RemoveVisualCache_Impl( xTargetStream );
1246 if ( bSaveAs )
1248 m_bWaitSaveCompleted = true;
1249 m_xNewObjectStream = xTargetStream;
1250 m_xNewParentStorage = xStorage;
1251 m_aNewEntryName = sEntName;
1252 m_bNewVisReplInStream = bStoreVis;
1253 m_bStoreLoaded = bStoreLoaded;
1255 if ( xCachedVisualRepresentation.is() )
1257 if ( bNeedLocalCache )
1258 m_xNewCachedVisRepl = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() );
1259 else
1260 m_xNewCachedVisRepl = xCachedVisualRepresentation;
1263 // TODO: register listeners for storages above, in case they are disposed
1264 // an exception will be thrown on saveCompleted( true )
1266 else
1268 uno::Reference< lang::XComponent > xComp( xTargetStream, uno::UNO_QUERY );
1269 if ( xComp.is() )
1271 try {
1272 xComp->dispose();
1273 } catch( const uno::Exception& )
1281 void SAL_CALL OleEmbeddedObject::setPersistentEntry(
1282 const uno::Reference< embed::XStorage >& xStorage,
1283 const OUString& sEntName,
1284 sal_Int32 nEntryConnectionMode,
1285 const uno::Sequence< beans::PropertyValue >& lArguments,
1286 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1287 throw ( lang::IllegalArgumentException,
1288 embed::WrongStateException,
1289 io::IOException,
1290 uno::Exception,
1291 uno::RuntimeException, std::exception )
1293 // begin wrapping related part ====================
1294 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1295 if ( xWrappedObject.is() )
1297 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1298 xWrappedObject->setPersistentEntry( xStorage, sEntName, nEntryConnectionMode, lArguments, lObjArgs );
1299 return;
1301 // end wrapping related part ====================
1303 // TODO: use lObjArgs
1305 // the type of the object must be already set
1306 // a kind of typedetection should be done in the factory;
1307 // the only exception is object initialized from a stream,
1308 // the class ID will be detected from the stream
1310 ::osl::MutexGuard aGuard( m_aMutex );
1311 if ( m_bDisposed )
1312 throw lang::DisposedException(); // TODO
1314 if ( !xStorage.is() )
1315 throw lang::IllegalArgumentException( "No parent storage is provided!",
1316 static_cast< ::cppu::OWeakObject* >(this),
1317 1 );
1319 if ( sEntName.isEmpty() )
1320 throw lang::IllegalArgumentException( "Empty element name is provided!",
1321 static_cast< ::cppu::OWeakObject* >(this),
1322 2 );
1324 // May be LOADED should be forbidden here ???
1325 if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1326 && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) )
1328 // if the object is not loaded
1329 // it can not get persistent representation without initialization
1331 // if the object is loaded
1332 // it can switch persistent representation only without initialization
1334 throw embed::WrongStateException(
1335 "Can't change persistent representation of activated object!",
1336 static_cast< ::cppu::OWeakObject* >(this) );
1339 if ( m_bWaitSaveCompleted )
1341 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1342 saveCompleted( ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) );
1343 else
1344 throw embed::WrongStateException(
1345 "The object waits for saveCompleted() call!",
1346 static_cast< ::cppu::OWeakObject* >(this) );
1349 uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
1350 if ( !xNameAccess.is() )
1351 throw uno::RuntimeException(); //TODO
1353 // detect entry existence
1354 bool bElExists = xNameAccess->hasByName( sEntName );
1356 m_bReadOnly = false;
1357 for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1358 if ( lArguments[nInd].Name == "ReadOnly" )
1359 lArguments[nInd].Value >>= m_bReadOnly;
1361 #ifdef _WIN32
1362 sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
1363 #endif
1365 SwitchOwnPersistence( xStorage, sEntName );
1367 for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1368 if ( lObjArgs[nInd].Name == "StoreVisualReplacement" )
1369 lObjArgs[nInd].Value >>= m_bStoreVisRepl;
1371 #ifdef _WIN32
1372 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT )
1374 if ( m_bFromClipboard )
1376 // the object should be initialized from clipboard
1377 // inpossibility to initialize the object means error here
1378 CreateOleComponentFromClipboard_Impl();
1379 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction
1380 m_pOleComponent->RunObject();
1381 m_nObjectState = embed::EmbedStates::RUNNING;
1383 else if ( bElExists )
1385 // load object from the stream
1386 // after the loading the object can appear as a link
1387 // will be detected by olecomponent
1390 CreateOleComponentAndLoad_Impl();
1391 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction
1393 catch( const uno::Exception& )
1395 // TODO/LATER: detect classID of the object if possible
1396 // means that the object inprocess server could not be successfully instantiated
1397 GetRidOfComponent();
1400 m_nObjectState = embed::EmbedStates::LOADED;
1402 else
1404 // create a new object
1405 CreateOleComponent_Impl();
1406 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID );
1407 m_pOleComponent->RunObject();
1408 m_nObjectState = embed::EmbedStates::RUNNING;
1411 else
1413 if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE )
1414 throw io::IOException();
1416 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1418 // the document just already changed its stream to store to;
1419 // the links to OLE documents switch their persistence in the same way
1420 // as normal embedded objects
1422 else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT )
1424 // create a new object, that will be stored in specified stream
1425 CreateOleComponent_Impl();
1427 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID );
1428 m_pOleComponent->RunObject();
1429 m_nObjectState = embed::EmbedStates::RUNNING;
1431 else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT )
1433 // use URL ( may be content or stream later ) from MediaDescriptor to initialize object
1434 OUString aURL;
1435 for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1436 if ( lArguments[nInd].Name == "URL" )
1437 lArguments[nInd].Value >>= aURL;
1439 if ( aURL.isEmpty() )
1440 throw lang::IllegalArgumentException(
1441 "Empty URL is provided in the media descriptor!",
1442 static_cast< ::cppu::OWeakObject* >(this),
1443 4 );
1445 CreateOleComponent_Impl();
1447 // TODO: the m_bIsLink value must be set already
1448 if ( !m_bIsLink )
1449 m_pOleComponent->CreateObjectFromFile( aURL );
1450 else
1451 m_pOleComponent->CreateLinkFromFile( aURL );
1453 m_pOleComponent->RunObject();
1454 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction
1456 m_nObjectState = embed::EmbedStates::RUNNING;
1458 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1460 //TODO:
1462 else
1463 throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
1464 static_cast< ::cppu::OWeakObject* >(this),
1465 3 );
1467 #else
1468 // On unix the ole object can not do anything except storing itself somewere
1469 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT && bElExists )
1471 // TODO/LATER: detect classID of the object
1472 // can be a real problem for the links
1474 m_nObjectState = embed::EmbedStates::LOADED;
1476 else if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1478 // do nothing, the object has already switched it's persistence
1480 else
1481 throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
1482 static_cast< ::cppu::OWeakObject* >(this),
1483 3 );
1485 #endif
1489 void SAL_CALL OleEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage,
1490 const OUString& sEntName,
1491 const uno::Sequence< beans::PropertyValue >& lArguments,
1492 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1493 throw ( lang::IllegalArgumentException,
1494 embed::WrongStateException,
1495 io::IOException,
1496 uno::Exception,
1497 uno::RuntimeException, std::exception )
1499 // begin wrapping related part ====================
1500 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1501 if ( xWrappedObject.is() )
1503 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1504 xWrappedObject->storeToEntry( xStorage, sEntName, lArguments, lObjArgs );
1505 return;
1507 // end wrapping related part ====================
1509 ::osl::MutexGuard aGuard( m_aMutex );
1510 if ( m_bDisposed )
1511 throw lang::DisposedException(); // TODO
1513 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
1515 StoreToLocation_Impl( xStorage, sEntName, lObjArgs, false );
1517 // TODO: should the listener notification be done?
1521 void SAL_CALL OleEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage,
1522 const OUString& sEntName,
1523 const uno::Sequence< beans::PropertyValue >& lArguments,
1524 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1525 throw ( lang::IllegalArgumentException,
1526 embed::WrongStateException,
1527 io::IOException,
1528 uno::Exception,
1529 uno::RuntimeException, std::exception )
1531 // begin wrapping related part ====================
1532 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1533 if ( xWrappedObject.is() )
1535 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1536 xWrappedObject->storeAsEntry( xStorage, sEntName, lArguments, lObjArgs );
1537 return;
1539 // end wrapping related part ====================
1541 ::osl::MutexGuard aGuard( m_aMutex );
1542 if ( m_bDisposed )
1543 throw lang::DisposedException(); // TODO
1545 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
1547 StoreToLocation_Impl( xStorage, sEntName, lObjArgs, true );
1549 // TODO: should the listener notification be done here or in saveCompleted?
1553 void SAL_CALL OleEmbeddedObject::saveCompleted( sal_Bool bUseNew )
1554 throw ( embed::WrongStateException,
1555 uno::Exception,
1556 uno::RuntimeException, std::exception )
1558 // begin wrapping related part ====================
1559 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1560 if ( xWrappedObject.is() )
1562 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1563 xWrappedObject->saveCompleted( bUseNew );
1564 return;
1566 // end wrapping related part ====================
1568 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1569 if ( m_bDisposed )
1570 throw lang::DisposedException(); // TODO
1572 if ( m_nObjectState == -1 )
1574 // the object is still not loaded
1575 throw embed::WrongStateException( "Can't store object without persistence!",
1576 static_cast< ::cppu::OWeakObject* >(this) );
1579 // it is allowed to call saveCompleted( false ) for nonstored objects
1580 if ( !m_bWaitSaveCompleted && !bUseNew )
1581 return;
1583 SAL_WARN_IF( !m_bWaitSaveCompleted, "embeddedobj.ole", "Unexpected saveCompleted() call!\n" );
1584 if ( !m_bWaitSaveCompleted )
1585 throw io::IOException(); // TODO: illegal call
1587 OSL_ENSURE( m_xNewObjectStream.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" );
1588 if ( !m_xNewObjectStream.is() || !m_xNewParentStorage.is() )
1589 throw uno::RuntimeException(); // TODO: broken internal information
1591 if ( bUseNew )
1593 SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStream, m_aNewEntryName );
1594 m_bStoreVisRepl = m_bNewVisReplInStream;
1595 SetVisReplInStream( m_bNewVisReplInStream );
1596 m_xCachedVisualRepresentation = m_xNewCachedVisRepl;
1598 else
1600 // close remembered stream
1601 try {
1602 uno::Reference< lang::XComponent > xComponent( m_xNewObjectStream, uno::UNO_QUERY );
1603 SAL_WARN_IF( !xComponent.is(), "embeddedobj.ole", "Wrong storage implementation!" );
1604 if ( xComponent.is() )
1605 xComponent->dispose();
1607 catch ( const uno::Exception& )
1612 bool bStoreLoaded = m_bStoreLoaded;
1614 m_xNewObjectStream.clear();
1615 m_xNewParentStorage.clear();
1616 m_aNewEntryName.clear();
1617 m_bWaitSaveCompleted = false;
1618 m_bNewVisReplInStream = false;
1619 m_xNewCachedVisRepl.clear();
1620 m_bStoreLoaded = false;
1622 if ( bUseNew && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded
1623 && m_nObjectState != embed::EmbedStates::LOADED )
1625 // the object replacement image should be updated, so the cached size as well
1626 m_bHasCachedSize = false;
1629 // the call will cache the size in case of success
1630 // probably it might need to be done earlier, while the object is in active state
1631 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1633 catch( const uno::Exception& )
1637 aGuard.clear();
1638 if ( bUseNew )
1640 MakeEventListenerNotification_Impl( "OnSaveAsDone");
1642 // the object can be changed only on windows
1643 // the notification should be done only if the object is not in loaded state
1644 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1646 MakeEventListenerNotification_Impl( "OnVisAreaChanged");
1652 sal_Bool SAL_CALL OleEmbeddedObject::hasEntry()
1653 throw ( embed::WrongStateException,
1654 uno::RuntimeException, std::exception )
1656 // begin wrapping related part ====================
1657 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1658 if ( xWrappedObject.is() )
1660 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1661 return xWrappedObject->hasEntry();
1663 // end wrapping related part ====================
1665 ::osl::MutexGuard aGuard( m_aMutex );
1666 if ( m_bDisposed )
1667 throw lang::DisposedException(); // TODO
1669 if ( m_bWaitSaveCompleted )
1670 throw embed::WrongStateException(
1671 "The object waits for saveCompleted() call!",
1672 static_cast< ::cppu::OWeakObject* >(this) );
1674 if ( m_xObjectStream.is() )
1675 return true;
1677 return false;
1681 OUString SAL_CALL OleEmbeddedObject::getEntryName()
1682 throw ( embed::WrongStateException,
1683 uno::RuntimeException, std::exception )
1685 // begin wrapping related part ====================
1686 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1687 if ( xWrappedObject.is() )
1689 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1690 return xWrappedObject->getEntryName();
1692 // end wrapping related part ====================
1694 ::osl::MutexGuard aGuard( m_aMutex );
1695 if ( m_bDisposed )
1696 throw lang::DisposedException(); // TODO
1698 if ( m_nObjectState == -1 )
1700 // the object is still not loaded
1701 throw embed::WrongStateException( "The object persistence is not initialized!",
1702 static_cast< ::cppu::OWeakObject* >(this) );
1705 if ( m_bWaitSaveCompleted )
1706 throw embed::WrongStateException(
1707 "The object waits for saveCompleted() call!",
1708 static_cast< ::cppu::OWeakObject* >(this) );
1710 return m_aEntryName;
1714 void SAL_CALL OleEmbeddedObject::storeOwn()
1715 throw ( embed::WrongStateException,
1716 io::IOException,
1717 uno::Exception,
1718 uno::RuntimeException, std::exception )
1720 // begin wrapping related part ====================
1721 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1722 if ( xWrappedObject.is() )
1724 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1725 xWrappedObject->storeOwn();
1726 return;
1728 // end wrapping related part ====================
1730 // during switching from Activated to Running and from Running to Loaded states the object will
1731 // ask container to store the object, the container has to make decision
1732 // to do so or not
1734 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1735 if ( m_bDisposed )
1736 throw lang::DisposedException(); // TODO
1738 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
1740 if ( m_nObjectState == -1 )
1742 // the object is still not loaded
1743 throw embed::WrongStateException( "Can't store object without persistence!",
1744 static_cast< ::cppu::OWeakObject* >(this) );
1747 if ( m_bWaitSaveCompleted )
1748 throw embed::WrongStateException(
1749 "The object waits for saveCompleted() call!",
1750 static_cast< ::cppu::OWeakObject* >(this) );
1752 if ( m_bReadOnly )
1753 throw io::IOException(); // TODO: access denied
1755 LetCommonStoragePassBeUsed_Impl( m_xObjectStream );
1757 bool bStoreLoaded = true;
1759 #ifdef _WIN32
1760 if ( m_nObjectState != embed::EmbedStates::LOADED && m_pOleComponent && m_pOleComponent->IsDirty() )
1762 bStoreLoaded = false;
1764 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" );
1766 if ( !m_xObjectStream.is() )
1767 throw io::IOException(); //TODO: access denied
1769 SetStreamMediaType_Impl( m_xObjectStream, "application/vnd.sun.star.oleobject" );
1770 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream();
1771 if ( !xOutStream.is() )
1772 throw io::IOException(); //TODO: access denied
1774 // TODO: does this work for links too?
1775 StoreObjectToStream( GetStreamForSaving() );
1777 // the replacement is changed probably, and it must be in the object stream
1778 if ( !m_pOleComponent->IsWorkaroundActive() )
1779 m_xCachedVisualRepresentation.clear();
1780 SetVisReplInStream( true );
1782 #endif
1784 if ( m_bStoreVisRepl != HasVisReplInStream() )
1786 if ( m_bStoreVisRepl )
1788 // the m_xCachedVisualRepresentation must be set or it should be already stored
1789 if ( m_xCachedVisualRepresentation.is() )
1790 InsertVisualCache_Impl( m_xObjectStream, m_xCachedVisualRepresentation );
1791 else
1793 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream );
1794 SAL_WARN_IF( !m_xCachedVisualRepresentation.is(), "embeddedobj.ole", "No representation is available!" );
1797 else
1799 if ( !m_xCachedVisualRepresentation.is() )
1800 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream );
1801 RemoveVisualCache_Impl( m_xObjectStream );
1804 SetVisReplInStream( m_bStoreVisRepl );
1807 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1809 // the object replacement image should be updated, so the cached size as well
1810 m_bHasCachedSize = false;
1813 // the call will cache the size in case of success
1814 // probably it might need to be done earlier, while the object is in active state
1815 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1817 catch( const uno::Exception& )
1821 aGuard.clear();
1823 MakeEventListenerNotification_Impl( "OnSaveDone");
1825 // the object can be changed only on Windows
1826 // the notification should be done only if the object is not in loaded state
1827 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1828 MakeEventListenerNotification_Impl( "OnVisAreaChanged");
1832 sal_Bool SAL_CALL OleEmbeddedObject::isReadonly()
1833 throw ( embed::WrongStateException,
1834 uno::RuntimeException, std::exception )
1836 // begin wrapping related part ====================
1837 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1838 if ( xWrappedObject.is() )
1840 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1841 return xWrappedObject->isReadonly();
1843 // end wrapping related part ====================
1845 ::osl::MutexGuard aGuard( m_aMutex );
1846 if ( m_bDisposed )
1847 throw lang::DisposedException(); // TODO
1849 if ( m_nObjectState == -1 )
1851 // the object is still not loaded
1852 throw embed::WrongStateException( "The object persistence is not initialized!",
1853 static_cast< ::cppu::OWeakObject* >(this) );
1856 if ( m_bWaitSaveCompleted )
1857 throw embed::WrongStateException(
1858 "The object waits for saveCompleted() call!",
1859 static_cast< ::cppu::OWeakObject* >(this) );
1861 return m_bReadOnly;
1865 void SAL_CALL OleEmbeddedObject::reload(
1866 const uno::Sequence< beans::PropertyValue >& lArguments,
1867 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1868 throw ( lang::IllegalArgumentException,
1869 embed::WrongStateException,
1870 io::IOException,
1871 uno::Exception,
1872 uno::RuntimeException, std::exception )
1874 // begin wrapping related part ====================
1875 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1876 if ( xWrappedObject.is() )
1878 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1879 xWrappedObject->reload( lArguments, lObjArgs );
1880 return;
1882 // end wrapping related part ====================
1884 // TODO: use lObjArgs
1886 ::osl::MutexGuard aGuard( m_aMutex );
1887 if ( m_bDisposed )
1888 throw lang::DisposedException(); // TODO
1890 if ( m_nObjectState == -1 )
1892 // the object is still not loaded
1893 throw embed::WrongStateException( "The object persistence is not initialized!",
1894 static_cast< ::cppu::OWeakObject* >(this) );
1897 if ( m_bWaitSaveCompleted )
1898 throw embed::WrongStateException(
1899 "The object waits for saveCompleted() call!",
1900 static_cast< ::cppu::OWeakObject* >(this) );
1902 // TODO:
1903 // throw away current document
1904 // load new document from current storage
1905 // use meaningfull part of lArguments
1909 void SAL_CALL OleEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage,
1910 const OUString& sEntName )
1911 throw ( lang::IllegalArgumentException,
1912 embed::WrongStateException,
1913 io::IOException,
1914 uno::Exception,
1915 uno::RuntimeException, std::exception )
1917 // begin wrapping related part ====================
1918 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1919 if ( xWrappedObject.is() )
1921 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1922 xWrappedObject->breakLink( xStorage, sEntName );
1923 return;
1925 // end wrapping related part ====================
1927 ::osl::MutexGuard aGuard( m_aMutex );
1928 if ( m_bDisposed )
1929 throw lang::DisposedException(); // TODO
1931 if ( !xStorage.is() )
1932 throw lang::IllegalArgumentException( "No parent storage is provided!",
1933 static_cast< ::cppu::OWeakObject* >(this),
1934 1 );
1936 if ( sEntName.isEmpty() )
1937 throw lang::IllegalArgumentException( "Empty element name is provided!",
1938 static_cast< ::cppu::OWeakObject* >(this),
1939 2 );
1941 // TODO: The object must be at least in Running state;
1942 if ( !m_bIsLink || m_nObjectState == -1 || !m_pOleComponent )
1944 // it must be a linked initialized object
1945 throw embed::WrongStateException(
1946 "The object is not a valid linked object!",
1947 static_cast< ::cppu::OWeakObject* >(this) );
1950 if ( m_bReadOnly )
1951 throw io::IOException(); // TODO: Access denied
1953 if ( m_bWaitSaveCompleted )
1954 throw embed::WrongStateException(
1955 "The object waits for saveCompleted() call!",
1956 static_cast< ::cppu::OWeakObject* >(this) );
1959 #ifdef _WIN32
1960 if ( m_pOleComponent )
1962 // TODO: create an object based on the link
1964 // disconnect the old temporary URL
1965 OUString aOldTempURL = m_aTempURL;
1966 m_aTempURL.clear();
1968 OleComponent* pNewOleComponent = new OleComponent( m_xFactory, this );
1969 try {
1970 pNewOleComponent->InitEmbeddedCopyOfLink( m_pOleComponent );
1972 catch ( const uno::Exception& )
1974 delete pNewOleComponent;
1975 if ( !m_aTempURL.isEmpty() )
1976 KillFile_Impl( m_aTempURL, m_xFactory );
1977 m_aTempURL = aOldTempURL;
1978 throw;
1981 try {
1982 GetRidOfComponent();
1984 catch( const uno::Exception& )
1986 delete pNewOleComponent;
1987 if ( !m_aTempURL.isEmpty() )
1988 KillFile_Impl( m_aTempURL, m_xFactory );
1989 m_aTempURL = aOldTempURL;
1990 throw;
1993 KillFile_Impl( aOldTempURL, m_xFactory );
1995 CreateOleComponent_Impl( pNewOleComponent );
1997 if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) )
1998 SwitchOwnPersistence( xStorage, sEntName );
2000 if ( m_nObjectState != embed::EmbedStates::LOADED )
2002 // TODO: should we activate the new object if the link was activated?
2004 sal_Int32 nTargetState = m_nObjectState;
2005 m_nObjectState = embed::EmbedStates::LOADED;
2007 if ( m_nObjectState == embed::EmbedStates::RUNNING )
2008 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed
2009 else // m_nObjectState == embed::EmbedStates::ACTIVE
2011 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed
2012 m_pOleComponent->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN );
2015 m_nObjectState = nTargetState;
2018 m_bIsLink = false;
2019 m_aLinkURL.clear();
2021 else
2022 #endif
2024 throw io::IOException(); //TODO:
2029 sal_Bool SAL_CALL OleEmbeddedObject::isLink()
2030 throw ( embed::WrongStateException,
2031 uno::RuntimeException, std::exception )
2033 // begin wrapping related part ====================
2034 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
2035 if ( xWrappedObject.is() )
2037 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
2038 return xWrappedObject->isLink();
2040 // end wrapping related part ====================
2042 ::osl::MutexGuard aGuard( m_aMutex );
2043 if ( m_bDisposed )
2044 throw lang::DisposedException(); // TODO
2046 return m_bIsLink;
2050 OUString SAL_CALL OleEmbeddedObject::getLinkURL()
2051 throw ( embed::WrongStateException,
2052 uno::Exception,
2053 uno::RuntimeException, std::exception )
2055 // begin wrapping related part ====================
2056 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
2057 if ( xWrappedObject.is() )
2059 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
2060 return xWrappedObject->getLinkURL();
2062 // end wrapping related part ====================
2064 ::osl::MutexGuard aGuard( m_aMutex );
2065 if ( m_bDisposed )
2066 throw lang::DisposedException(); // TODO
2068 if ( m_bWaitSaveCompleted )
2069 throw embed::WrongStateException(
2070 "The object waits for saveCompleted() call!",
2071 static_cast< ::cppu::OWeakObject* >(this) );
2073 if ( !m_bIsLink )
2074 throw embed::WrongStateException(
2075 "The object is not a link object!",
2076 static_cast< ::cppu::OWeakObject* >(this) );
2078 // TODO: probably the link URL can be retrieved from OLE
2080 return m_aLinkURL;
2083 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */