1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
51 #include <olecomponent.hxx>
54 using namespace ::com::sun::star
;
55 using namespace ::comphelper
;
58 bool KillFile_Impl( const OUString
& aURL
, const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
)
67 uno::Reference
< ucb::XSimpleFileAccess3
> xAccess(
68 ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory
) ) );
70 xAccess
->kill( aURL
);
73 catch( const uno::Exception
& )
81 OUString
GetNewTempFileURL_Impl( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
)
83 SAL_WARN_IF( !xFactory
.is(), "embeddedobj.ole", "No factory is provided!" );
87 uno::Reference
< beans::XPropertySet
> xTempFile(
88 io::TempFile::create(comphelper::getComponentContext(xFactory
)),
89 uno::UNO_QUERY_THROW
);
92 xTempFile
->setPropertyValue("RemoveFile", uno::makeAny( sal_False
) );
93 uno::Any aUrl
= xTempFile
->getPropertyValue("Uri");
96 catch ( const uno::Exception
& )
100 if ( aResult
.isEmpty() )
101 throw uno::RuntimeException(); // TODO: can not create tempfile
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() )
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
= uno::Reference
< io::XOutputStream
>();
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
);
143 catch( const uno::RuntimeException
& )
145 KillFile_Impl( aResult
, xFactory
);
148 catch( const uno::Exception
& )
150 KillFile_Impl( aResult
, xFactory
);
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
)
165 uno::Reference
< beans::XPropertySet
> xTempFile(
166 io::TempFile::create(comphelper::getComponentContext(xFactory
)),
168 uno::Reference
< io::XStream
> xTempStream( xTempFile
, uno::UNO_QUERY_THROW
);
170 xParentStorage
->copyStreamElementData( aEntryName
, xTempStream
);
172 xTempFile
->setPropertyValue("RemoveFile", uno::makeAny( sal_False
) );
173 uno::Any aUrl
= xTempFile
->getPropertyValue("Uri");
176 catch( const uno::RuntimeException
& )
180 catch( const uno::Exception
& )
184 if ( aResult
.isEmpty() )
185 throw io::IOException();
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
) );
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 ) );
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
= sal_True
;
220 m_nVerbExecutionThreadIdentifier
= osl::Thread::getCurrentIdentifier();
221 m_bChangedOnVerbExecution
= sal_False
;
226 sal_Bool
VerbExecutionController::EndControlExecution_WasModified()
228 osl::MutexGuard
aGuard( m_aVerbExecutionMutex
);
230 sal_Bool bResult
= sal_False
;
231 if ( m_bVerbExecutionInProgress
&& m_nVerbExecutionThreadIdentifier
== osl::Thread::getCurrentIdentifier() )
233 bResult
= m_bChangedOnVerbExecution
;
234 m_bVerbExecutionInProgress
= sal_False
;
241 void VerbExecutionController::ModificationNotificationIsDone()
243 osl::MutexGuard
aGuard( m_aVerbExecutionMutex
);
245 if ( m_bVerbExecutionInProgress
&& osl::Thread::getCurrentIdentifier() == m_nVerbExecutionThreadIdentifier
)
246 m_bChangedOnVerbExecution
= sal_True
;
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();
282 throw io::IOException(); // TODO:
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
);
302 uno::Sequence
< sal_Int8
> aData( 8 );
303 sal_Int32 nRead
= xInStream
->readBytes( aData
, 8 );
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
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 )
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 );
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];
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 )
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 );
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 argumants!\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 OUString( "com.sun.star.embed.OLESimpleStorage" ),
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' )
425 aData
[0] = 0x02; aData
[1] = 0; aData
[2] = 0; aData
[3] = 0;
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
);
439 aData
[0] = 0x01; aData
[1] = 0; aData
[2] = 0; aData
[3] = 0;
440 xTempOutStream
->writeBytes( aData
);
443 *( reinterpret_cast<sal_uInt32
*>(aData
.getArray()) ) = 0xFFFFFFFF;
444 xTempOutStream
->writeBytes( aData
);
447 aData
[0] = 0x02; aData
[1] = 0; aData
[2] = 0; aData
[3] = 0;
448 xTempOutStream
->writeBytes( aData
);
451 *( reinterpret_cast<sal_uInt32
*>(aData
.getArray()) ) = 0x0;
452 xTempOutStream
->writeBytes( aData
);
455 awt::Size aSize
= getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
456 sal_Int32 nIndex
= 0;
459 for ( nIndex
= 0; nIndex
< 4; nIndex
++ )
461 aData
[nIndex
] = (sal_Int8
)( aSize
.Width
% 0x100 );
462 aSize
.Width
/= 0x100;
464 xTempOutStream
->writeBytes( aData
);
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!" );
490 for ( sal_Int32 nInd
= 0; nInd
< 4; nInd
++ )
492 aData
[nInd
] = (sal_Int8
)( ( (sal_uInt64
) 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 );
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
) );
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 argumant!\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 OUString( "com.sun.star.embed.OLESimpleStorage" ),
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 );
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
& )
591 xStream
= m_xObjectStream
->getInputStream();
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 OUString( "com.sun.star.embed.OLESimpleStorage" ),
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
)
634 uno::Reference
< io::XStream
> xResult
;
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
= uno::Reference
< container::XNameContainer
>(
647 m_xFactory
->createInstanceWithArguments(
648 OUString( "com.sun.star.embed.OLESimpleStorage" ),
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
);
670 catch( const uno::Exception
& )
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
);
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
);
734 // retry to create the component after recovering
739 CreateOleComponentAndLoad_Impl( NULL
);
740 m_aClassID
= m_pOleComponent
->GetCLSID(); // was not set during consruction
742 catch( const uno::Exception
& )
749 xResult
= TryToRetrieveCachedVisualRepresentation_Impl( xStream
, false );
755 catch( const uno::Exception
& )
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!" );
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
) )
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
);
806 sal_Bool
OleEmbeddedObject::SaveObject_Impl()
808 sal_Bool bResult
= sal_False
;
810 if ( m_xClientSite
.is() )
814 m_xClientSite
->saveObject();
817 catch( const uno::Exception
& )
826 sal_Bool
OleEmbeddedObject::OnShowWindow_Impl( sal_Bool bShow
)
828 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
830 sal_Bool bResult
= sal_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
)
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();
845 StateChangeNotification_Impl( sal_False
, nOldState
, m_nObjectState
);
847 else if ( !bShow
&& m_nObjectState
== embed::EmbedStates::ACTIVE
)
849 m_nObjectState
= embed::EmbedStates::RUNNING
;
851 StateChangeNotification_Impl( sal_False
, nOldState
, m_nObjectState
);
854 if ( m_xClientSite
.is() )
858 m_xClientSite
->visibilityChanged( bShow
);
861 catch( const uno::Exception
& )
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()
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
= uno::Reference
< io::XStream
>();
902 MakeEventListenerNotification_Impl( OUString( "OnVisAreaChanged" ) );
908 void OleEmbeddedObject::OnClosed_Impl()
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( sal_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
);
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
);
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
= uno::Reference
< util::XCloseListener
>(
967 static_cast< ::cppu::OWeakObject
* >( new OClosePreventer
),
970 m_pOleComponent
->addCloseListener( m_xClosePreventer
);
975 void OleEmbeddedObject::CreateOleComponentAndLoad_Impl( OleComponent
* pOleComponent
)
977 if ( !m_pOleComponent
)
979 if ( !m_xObjectStream
.is() )
980 throw uno::RuntimeException();
982 CreateOleComponent_Impl( pOleComponent
);
984 // after the loading the object can appear as a link
985 // will be detected later by olecomponent
988 if ( m_aTempURL
.isEmpty() )
989 throw uno::RuntimeException(); // TODO
991 m_pOleComponent
->LoadEmbeddedObject( m_aTempURL
);
996 void OleEmbeddedObject::CreateOleComponentFromClipboard_Impl( OleComponent
* pOleComponent
)
998 if ( !m_pOleComponent
)
1000 if ( !m_xObjectStream
.is() )
1001 throw uno::RuntimeException();
1003 CreateOleComponent_Impl( pOleComponent
);
1005 // after the loading the object can appear as a link
1006 // will be detected later by olecomponent
1007 m_pOleComponent
->CreateObjectFromClipboard();
1012 uno::Reference
< io::XOutputStream
> OleEmbeddedObject::GetStreamForSaving()
1014 if ( !m_xObjectStream
.is() )
1015 throw uno::RuntimeException(); //TODO:
1017 uno::Reference
< io::XOutputStream
> xOutStream
= m_xObjectStream
->getOutputStream();
1018 if ( !xOutStream
.is() )
1019 throw io::IOException(); //TODO: access denied
1021 uno::Reference
< io::XTruncate
> xTruncate( xOutStream
, uno::UNO_QUERY
);
1022 if ( !xTruncate
.is() )
1023 throw uno::RuntimeException(); //TODO:
1025 xTruncate
->truncate();
1031 void OleEmbeddedObject::StoreObjectToStream( uno::Reference
< io::XOutputStream
> xOutStream
)
1032 throw ( uno::Exception
)
1034 // this method should be used only on windows
1035 if ( m_pOleComponent
)
1036 m_pOleComponent
->StoreOwnTmpIfNecessary();
1038 // now all the changes should be in temporary location
1039 if ( m_aTempURL
.isEmpty() )
1040 throw uno::RuntimeException();
1042 // open temporary file for reading
1043 uno::Reference
< ucb::XSimpleFileAccess3
> xTempAccess(
1044 ucb::SimpleFileAccess::create( comphelper::getComponentContext(m_xFactory
) ) );
1046 uno::Reference
< io::XInputStream
> xTempInStream
= xTempAccess
->openFileRead( m_aTempURL
);
1047 SAL_WARN_IF( !xTempInStream
.is(), "embeddedobj.ole", "The object's temporary file can not be reopened for reading!" );
1049 // TODO: use bStoreVisReplace
1051 if ( xTempInStream
.is() )
1053 // write all the contents to XOutStream
1054 uno::Reference
< io::XTruncate
> xTrunc( xOutStream
, uno::UNO_QUERY
);
1056 throw uno::RuntimeException(); //TODO:
1060 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream
, xOutStream
);
1063 throw io::IOException(); // TODO:
1065 // TODO: should the view replacement be in the stream ???
1066 // probably it must be specified on storing
1070 void OleEmbeddedObject::StoreToLocation_Impl(
1071 const uno::Reference
< embed::XStorage
>& xStorage
,
1072 const OUString
& sEntName
,
1073 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
,
1075 throw ( uno::Exception
)
1077 // TODO: use lObjArgs
1078 // TODO: exchange StoreVisualReplacement by SO file format version?
1080 if ( m_nObjectState
== -1 )
1082 // the object is still not loaded
1083 throw embed::WrongStateException( "Can't store object without persistence!",
1084 static_cast< ::cppu::OWeakObject
* >(this) );
1087 if ( m_bWaitSaveCompleted
)
1088 throw embed::WrongStateException(
1089 "The object waits for saveCompleted() call!",
1090 static_cast< ::cppu::OWeakObject
* >(this) );
1092 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStream
.is(), "The object has no valid persistence!\n" );
1094 bool bVisReplIsStored
= false;
1096 bool bTryOptimization
= false;
1097 bool bStoreVis
= m_bStoreVisRepl
;
1098 uno::Reference
< io::XStream
> xCachedVisualRepresentation
;
1099 for ( sal_Int32 nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
1101 if ( lObjArgs
[nInd
].Name
== "StoreVisualReplacement" )
1102 lObjArgs
[nInd
].Value
>>= bStoreVis
;
1103 else if ( lObjArgs
[nInd
].Name
== "VisualReplacement" )
1104 lObjArgs
[nInd
].Value
>>= xCachedVisualRepresentation
;
1105 else if ( lObjArgs
[nInd
].Name
== "CanTryOptimization" )
1106 lObjArgs
[nInd
].Value
>>= bTryOptimization
;
1109 // ignore visual representation provided from outside if it should not be stored
1111 xCachedVisualRepresentation
= uno::Reference
< io::XStream
>();
1113 if ( bStoreVis
&& !HasVisReplInStream() && !xCachedVisualRepresentation
.is() )
1114 throw io::IOException(); // TODO: there is no cached visual representation and nothing is provided from outside
1116 // if the representation is provided from outside it should be copied to a local stream
1117 bool bNeedLocalCache
= xCachedVisualRepresentation
.is();
1119 uno::Reference
< io::XStream
> xTargetStream
;
1121 bool bStoreLoaded
= false;
1122 if ( m_nObjectState
== embed::EmbedStates::LOADED
1124 // if the object was NOT modified after storing it can be just copied
1125 // as if it was in loaded state
1126 || ( m_pOleComponent
&& !m_pOleComponent
->IsDirty() )
1130 bool bOptimizedCopyingDone
= false;
1132 if ( bTryOptimization
&& bStoreVis
== HasVisReplInStream() )
1136 uno::Reference
< embed::XOptimizedStorage
> xSourceOptStor( m_xParentStorage
, uno::UNO_QUERY_THROW
);
1137 uno::Reference
< embed::XOptimizedStorage
> xTargetOptStor( xStorage
, uno::UNO_QUERY_THROW
);
1138 xSourceOptStor
->copyElementDirectlyTo( m_aEntryName
, xTargetOptStor
, sEntName
);
1139 bOptimizedCopyingDone
= true;
1141 catch( const uno::Exception
& )
1146 if ( !bOptimizedCopyingDone
)
1148 // if optimized copying fails a normal one should be tried
1149 m_xParentStorage
->copyElementTo( m_aEntryName
, xStorage
, sEntName
);
1152 // the locally retrieved representation is always preferable
1153 // since the object is in loaded state the representation is unchanged
1154 if ( m_xCachedVisualRepresentation
.is() )
1156 xCachedVisualRepresentation
= m_xCachedVisualRepresentation
;
1157 bNeedLocalCache
= false;
1160 bVisReplIsStored
= HasVisReplInStream();
1161 bStoreLoaded
= true;
1164 else if ( m_pOleComponent
)
1167 xStorage
->openStreamElement( sEntName
, embed::ElementModes::READWRITE
);
1168 if ( !xTargetStream
.is() )
1169 throw io::IOException(); //TODO: access denied
1171 SetStreamMediaType_Impl( xTargetStream
, OUString( "application/vnd.sun.star.oleobject" ));
1172 uno::Reference
< io::XOutputStream
> xOutStream
= xTargetStream
->getOutputStream();
1173 if ( !xOutStream
.is() )
1174 throw io::IOException(); //TODO: access denied
1176 StoreObjectToStream( xOutStream
);
1177 bVisReplIsStored
= sal_True
;
1181 // no need to do it on StoreTo since in this case the replacement is in the stream
1182 // and there is no need to cache it even if it is thrown away because the object
1183 // is not changed by StoreTo action
1185 uno::Reference
< io::XStream
> xTmpCVRepresentation
=
1186 TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream
);
1188 // the locally retrieved representation is always preferable
1189 if ( xTmpCVRepresentation
.is() )
1191 xCachedVisualRepresentation
= xTmpCVRepresentation
;
1192 bNeedLocalCache
= sal_False
;
1199 throw io::IOException(); // TODO
1202 if ( !xTargetStream
.is() )
1205 xStorage
->openStreamElement( sEntName
, embed::ElementModes::READWRITE
);
1206 if ( !xTargetStream
.is() )
1207 throw io::IOException(); //TODO: access denied
1210 LetCommonStoragePassBeUsed_Impl( xTargetStream
);
1212 if ( bStoreVis
!= bVisReplIsStored
)
1216 if ( !xCachedVisualRepresentation
.is() )
1217 xCachedVisualRepresentation
= TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream
);
1219 SAL_WARN_IF( !xCachedVisualRepresentation
.is(), "embeddedobj.ole", "No representation is available!" );
1221 // the following copying will be done in case it is SaveAs anyway
1222 // if it is not SaveAs the seekable access is not required currently
1223 // TODO/LATER: may be required in future
1226 uno::Reference
< io::XSeekable
> xCachedSeek( xCachedVisualRepresentation
, uno::UNO_QUERY
);
1227 if ( !xCachedSeek
.is() )
1229 xCachedVisualRepresentation
1230 = GetNewFilledTempStream_Impl( xCachedVisualRepresentation
->getInputStream() );
1231 bNeedLocalCache
= false;
1235 InsertVisualCache_Impl( xTargetStream
, xCachedVisualRepresentation
);
1239 // the removed representation could be cached by this method
1240 if ( !xCachedVisualRepresentation
.is() )
1241 xCachedVisualRepresentation
= TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream
);
1243 RemoveVisualCache_Impl( xTargetStream
);
1249 m_bWaitSaveCompleted
= true;
1250 m_xNewObjectStream
= xTargetStream
;
1251 m_xNewParentStorage
= xStorage
;
1252 m_aNewEntryName
= sEntName
;
1253 m_bNewVisReplInStream
= bStoreVis
;
1254 m_bStoreLoaded
= bStoreLoaded
;
1256 if ( xCachedVisualRepresentation
.is() )
1258 if ( bNeedLocalCache
)
1259 m_xNewCachedVisRepl
= GetNewFilledTempStream_Impl( xCachedVisualRepresentation
->getInputStream() );
1261 m_xNewCachedVisRepl
= xCachedVisualRepresentation
;
1264 // TODO: register listeners for storages above, in case they are disposed
1265 // an exception will be thrown on saveCompleted( true )
1269 uno::Reference
< lang::XComponent
> xComp( xTargetStream
, uno::UNO_QUERY
);
1274 } catch( const uno::Exception
& )
1282 void SAL_CALL
OleEmbeddedObject::setPersistentEntry(
1283 const uno::Reference
< embed::XStorage
>& xStorage
,
1284 const OUString
& sEntName
,
1285 sal_Int32 nEntryConnectionMode
,
1286 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1287 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1288 throw ( lang::IllegalArgumentException
,
1289 embed::WrongStateException
,
1292 uno::RuntimeException
, std::exception
)
1294 // begin wrapping related part ====================
1295 uno::Reference
< embed::XEmbedPersist
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1296 if ( xWrappedObject
.is() )
1298 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1299 xWrappedObject
->setPersistentEntry( xStorage
, sEntName
, nEntryConnectionMode
, lArguments
, lObjArgs
);
1302 // end wrapping related part ====================
1304 // TODO: use lObjArgs
1306 // the type of the object must be already set
1307 // a kind of typedetection should be done in the factory;
1308 // the only exception is object initialized from a stream,
1309 // the class ID will be detected from the stream
1311 ::osl::MutexGuard
aGuard( m_aMutex
);
1313 throw lang::DisposedException(); // TODO
1315 if ( !xStorage
.is() )
1316 throw lang::IllegalArgumentException( "No parent storage is provided!",
1317 static_cast< ::cppu::OWeakObject
* >(this),
1320 if ( sEntName
.isEmpty() )
1321 throw lang::IllegalArgumentException( "Empty element name is provided!",
1322 static_cast< ::cppu::OWeakObject
* >(this),
1325 // May be LOADED should be forbidden here ???
1326 if ( ( m_nObjectState
!= -1 || nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
1327 && ( m_nObjectState
== -1 || nEntryConnectionMode
!= embed::EntryInitModes::NO_INIT
) )
1329 // if the object is not loaded
1330 // it can not get persistent representation without initialization
1332 // if the object is loaded
1333 // it can switch persistent representation only without initialization
1335 throw embed::WrongStateException(
1336 "Can't change persistent representation of activated object!",
1337 static_cast< ::cppu::OWeakObject
* >(this) );
1340 if ( m_bWaitSaveCompleted
)
1342 if ( nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
1343 saveCompleted( ( m_xParentStorage
!= xStorage
|| !m_aEntryName
.equals( sEntName
) ) );
1345 throw embed::WrongStateException(
1346 "The object waits for saveCompleted() call!",
1347 static_cast< ::cppu::OWeakObject
* >(this) );
1350 uno::Reference
< container::XNameAccess
> xNameAccess( xStorage
, uno::UNO_QUERY
);
1351 if ( !xNameAccess
.is() )
1352 throw uno::RuntimeException(); //TODO
1354 // detect entry existence
1355 bool bElExists
= xNameAccess
->hasByName( sEntName
);
1357 m_bReadOnly
= false;
1358 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
1359 if ( lArguments
[nInd
].Name
== "ReadOnly" )
1360 lArguments
[nInd
].Value
>>= m_bReadOnly
;
1363 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
1366 SwitchOwnPersistence( xStorage
, sEntName
);
1368 for ( sal_Int32 nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
1369 if ( lObjArgs
[nInd
].Name
== "StoreVisualReplacement" )
1370 lObjArgs
[nInd
].Value
>>= m_bStoreVisRepl
;
1373 if ( nEntryConnectionMode
== embed::EntryInitModes::DEFAULT_INIT
)
1375 if ( m_bFromClipboard
)
1377 // the object should be initialized from clipboard
1378 // inpossibility to initialize the object means error here
1379 CreateOleComponentFromClipboard_Impl( NULL
);
1380 m_aClassID
= m_pOleComponent
->GetCLSID(); // was not set during consruction
1381 m_pOleComponent
->RunObject();
1382 m_nObjectState
= embed::EmbedStates::RUNNING
;
1384 else if ( bElExists
)
1386 // load object from the stream
1387 // after the loading the object can appear as a link
1388 // will be detected by olecomponent
1391 CreateOleComponentAndLoad_Impl( NULL
);
1392 m_aClassID
= m_pOleComponent
->GetCLSID(); // was not set during consruction
1394 catch( const uno::Exception
& )
1396 // TODO/LATER: detect classID of the object if possible
1397 // means that the object inprocess server could not be successfully instantiated
1398 GetRidOfComponent();
1401 m_nObjectState
= embed::EmbedStates::LOADED
;
1405 // create a new object
1406 CreateOleComponent_Impl();
1407 m_pOleComponent
->CreateNewEmbeddedObject( m_aClassID
);
1408 m_pOleComponent
->RunObject();
1409 m_nObjectState
= embed::EmbedStates::RUNNING
;
1414 if ( ( nStorageMode
& embed::ElementModes::READWRITE
) != embed::ElementModes::READWRITE
)
1415 throw io::IOException();
1417 if ( nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
1419 // the document just already changed its stream to store to;
1420 // the links to OLE documents switch their persistence in the same way
1421 // as normal embedded objects
1423 else if ( nEntryConnectionMode
== embed::EntryInitModes::TRUNCATE_INIT
)
1425 // create a new object, that will be stored in specified stream
1426 CreateOleComponent_Impl();
1428 m_pOleComponent
->CreateNewEmbeddedObject( m_aClassID
);
1429 m_pOleComponent
->RunObject();
1430 m_nObjectState
= embed::EmbedStates::RUNNING
;
1432 else if ( nEntryConnectionMode
== embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT
)
1434 // use URL ( may be content or stream later ) from MediaDescriptor to initialize object
1436 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
1437 if ( lArguments
[nInd
].Name
== "URL" )
1438 lArguments
[nInd
].Value
>>= aURL
;
1440 if ( aURL
.isEmpty() )
1441 throw lang::IllegalArgumentException(
1442 "Empty URL is provided in the media descriptor!",
1443 static_cast< ::cppu::OWeakObject
* >(this),
1446 CreateOleComponent_Impl();
1448 // TODO: the m_bIsLink value must be set already
1450 m_pOleComponent
->CreateObjectFromFile( aURL
);
1452 m_pOleComponent
->CreateLinkFromFile( aURL
);
1454 m_pOleComponent
->RunObject();
1455 m_aClassID
= m_pOleComponent
->GetCLSID(); // was not set during consruction
1457 m_nObjectState
= embed::EmbedStates::RUNNING
;
1459 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1464 throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
1465 static_cast< ::cppu::OWeakObject
* >(this),
1469 // On unix the ole object can not do anything except storing itself somewere
1470 if ( nEntryConnectionMode
== embed::EntryInitModes::DEFAULT_INIT
&& bElExists
)
1472 // TODO/LATER: detect classID of the object
1473 // can be a real problem for the links
1475 m_nObjectState
= embed::EmbedStates::LOADED
;
1477 else if ( nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
1479 // do nothing, the object has already switched it's persistence
1482 throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
1483 static_cast< ::cppu::OWeakObject
* >(this),
1490 void SAL_CALL
OleEmbeddedObject::storeToEntry( const uno::Reference
< embed::XStorage
>& xStorage
,
1491 const OUString
& sEntName
,
1492 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1493 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1494 throw ( lang::IllegalArgumentException
,
1495 embed::WrongStateException
,
1498 uno::RuntimeException
, std::exception
)
1500 // begin wrapping related part ====================
1501 uno::Reference
< embed::XEmbedPersist
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1502 if ( xWrappedObject
.is() )
1504 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1505 xWrappedObject
->storeToEntry( xStorage
, sEntName
, lArguments
, lObjArgs
);
1508 // end wrapping related part ====================
1510 ::osl::MutexGuard
aGuard( m_aMutex
);
1512 throw lang::DisposedException(); // TODO
1514 VerbExecutionControllerGuard
aVerbGuard( m_aVerbExecutionController
);
1516 StoreToLocation_Impl( xStorage
, sEntName
, lObjArgs
, false );
1518 // TODO: should the listener notification be done?
1522 void SAL_CALL
OleEmbeddedObject::storeAsEntry( const uno::Reference
< embed::XStorage
>& xStorage
,
1523 const OUString
& sEntName
,
1524 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1525 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1526 throw ( lang::IllegalArgumentException
,
1527 embed::WrongStateException
,
1530 uno::RuntimeException
, std::exception
)
1532 // begin wrapping related part ====================
1533 uno::Reference
< embed::XEmbedPersist
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1534 if ( xWrappedObject
.is() )
1536 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1537 xWrappedObject
->storeAsEntry( xStorage
, sEntName
, lArguments
, lObjArgs
);
1540 // end wrapping related part ====================
1542 ::osl::MutexGuard
aGuard( m_aMutex
);
1544 throw lang::DisposedException(); // TODO
1546 VerbExecutionControllerGuard
aVerbGuard( m_aVerbExecutionController
);
1548 StoreToLocation_Impl( xStorage
, sEntName
, lObjArgs
, true );
1550 // TODO: should the listener notification be done here or in saveCompleted?
1554 void SAL_CALL
OleEmbeddedObject::saveCompleted( sal_Bool bUseNew
)
1555 throw ( embed::WrongStateException
,
1557 uno::RuntimeException
, std::exception
)
1559 // begin wrapping related part ====================
1560 uno::Reference
< embed::XEmbedPersist
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1561 if ( xWrappedObject
.is() )
1563 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1564 xWrappedObject
->saveCompleted( bUseNew
);
1567 // end wrapping related part ====================
1569 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1571 throw lang::DisposedException(); // TODO
1573 if ( m_nObjectState
== -1 )
1575 // the object is still not loaded
1576 throw embed::WrongStateException( "Can't store object without persistence!",
1577 static_cast< ::cppu::OWeakObject
* >(this) );
1580 // it is allowed to call saveCompleted( false ) for nonstored objects
1581 if ( !m_bWaitSaveCompleted
&& !bUseNew
)
1584 SAL_WARN_IF( !m_bWaitSaveCompleted
, "embeddedobj.ole", "Unexpected saveCompleted() call!\n" );
1585 if ( !m_bWaitSaveCompleted
)
1586 throw io::IOException(); // TODO: illegal call
1588 OSL_ENSURE( m_xNewObjectStream
.is() && m_xNewParentStorage
.is() , "Internal object information is broken!\n" );
1589 if ( !m_xNewObjectStream
.is() || !m_xNewParentStorage
.is() )
1590 throw uno::RuntimeException(); // TODO: broken internal information
1594 SwitchOwnPersistence( m_xNewParentStorage
, m_xNewObjectStream
, m_aNewEntryName
);
1595 m_bStoreVisRepl
= m_bNewVisReplInStream
;
1596 SetVisReplInStream( m_bNewVisReplInStream
);
1597 m_xCachedVisualRepresentation
= m_xNewCachedVisRepl
;
1601 // close remembered stream
1603 uno::Reference
< lang::XComponent
> xComponent( m_xNewObjectStream
, uno::UNO_QUERY
);
1604 SAL_WARN_IF( !xComponent
.is(), "embeddedobj.ole", "Wrong storage implementation!" );
1605 if ( xComponent
.is() )
1606 xComponent
->dispose();
1608 catch ( const uno::Exception
& )
1613 bool bStoreLoaded
= m_bStoreLoaded
;
1615 m_xNewObjectStream
= uno::Reference
< io::XStream
>();
1616 m_xNewParentStorage
= uno::Reference
< embed::XStorage
>();
1617 m_aNewEntryName
.clear();
1618 m_bWaitSaveCompleted
= false;
1619 m_bNewVisReplInStream
= false;
1620 m_xNewCachedVisRepl
= uno::Reference
< io::XStream
>();
1621 m_bStoreLoaded
= false;
1623 if ( bUseNew
&& m_pOleComponent
&& m_nUpdateMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
&& !bStoreLoaded
1624 && m_nObjectState
!= embed::EmbedStates::LOADED
)
1626 // the object replacement image should be updated, so the cached size as well
1627 m_bHasCachedSize
= false;
1630 // the call will cache the size in case of success
1631 // probably it might need to be done earlier, while the object is in active state
1632 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
1634 catch( const uno::Exception
& )
1641 MakeEventListenerNotification_Impl( OUString( "OnSaveAsDone" ));
1643 // the object can be changed only on windows
1644 // the notification should be done only if the object is not in loaded state
1645 if ( m_pOleComponent
&& m_nUpdateMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
&& !bStoreLoaded
)
1647 MakeEventListenerNotification_Impl( OUString( "OnVisAreaChanged" ));
1653 sal_Bool SAL_CALL
OleEmbeddedObject::hasEntry()
1654 throw ( embed::WrongStateException
,
1655 uno::RuntimeException
, std::exception
)
1657 // begin wrapping related part ====================
1658 uno::Reference
< embed::XEmbedPersist
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1659 if ( xWrappedObject
.is() )
1661 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1662 return xWrappedObject
->hasEntry();
1664 // end wrapping related part ====================
1666 ::osl::MutexGuard
aGuard( m_aMutex
);
1668 throw lang::DisposedException(); // TODO
1670 if ( m_bWaitSaveCompleted
)
1671 throw embed::WrongStateException(
1672 "The object waits for saveCompleted() call!",
1673 static_cast< ::cppu::OWeakObject
* >(this) );
1675 if ( m_xObjectStream
.is() )
1682 OUString SAL_CALL
OleEmbeddedObject::getEntryName()
1683 throw ( embed::WrongStateException
,
1684 uno::RuntimeException
, std::exception
)
1686 // begin wrapping related part ====================
1687 uno::Reference
< embed::XEmbedPersist
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1688 if ( xWrappedObject
.is() )
1690 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1691 return xWrappedObject
->getEntryName();
1693 // end wrapping related part ====================
1695 ::osl::MutexGuard
aGuard( m_aMutex
);
1697 throw lang::DisposedException(); // TODO
1699 if ( m_nObjectState
== -1 )
1701 // the object is still not loaded
1702 throw embed::WrongStateException( "The object persistence is not initialized!",
1703 static_cast< ::cppu::OWeakObject
* >(this) );
1706 if ( m_bWaitSaveCompleted
)
1707 throw embed::WrongStateException(
1708 "The object waits for saveCompleted() call!",
1709 static_cast< ::cppu::OWeakObject
* >(this) );
1711 return m_aEntryName
;
1716 void SAL_CALL
OleEmbeddedObject::storeOwn()
1717 throw ( embed::WrongStateException
,
1720 uno::RuntimeException
, std::exception
)
1722 // begin wrapping related part ====================
1723 uno::Reference
< embed::XEmbedPersist
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1724 if ( xWrappedObject
.is() )
1726 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1727 xWrappedObject
->storeOwn();
1730 // end wrapping related part ====================
1732 // during switching from Activated to Running and from Running to Loaded states the object will
1733 // ask container to store the object, the container has to make decision
1736 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1738 throw lang::DisposedException(); // TODO
1740 VerbExecutionControllerGuard
aVerbGuard( m_aVerbExecutionController
);
1742 if ( m_nObjectState
== -1 )
1744 // the object is still not loaded
1745 throw embed::WrongStateException( "Can't store object without persistence!",
1746 static_cast< ::cppu::OWeakObject
* >(this) );
1749 if ( m_bWaitSaveCompleted
)
1750 throw embed::WrongStateException(
1751 "The object waits for saveCompleted() call!",
1752 static_cast< ::cppu::OWeakObject
* >(this) );
1755 throw io::IOException(); // TODO: access denied
1757 LetCommonStoragePassBeUsed_Impl( m_xObjectStream
);
1759 bool bStoreLoaded
= true;
1762 if ( m_nObjectState
!= embed::EmbedStates::LOADED
&& m_pOleComponent
&& m_pOleComponent
->IsDirty() )
1764 bStoreLoaded
= sal_False
;
1766 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStream
.is(), "The object has no valid persistence!\n" );
1768 if ( !m_xObjectStream
.is() )
1769 throw io::IOException(); //TODO: access denied
1771 SetStreamMediaType_Impl( m_xObjectStream
, OUString( "application/vnd.sun.star.oleobject" ));
1772 uno::Reference
< io::XOutputStream
> xOutStream
= m_xObjectStream
->getOutputStream();
1773 if ( !xOutStream
.is() )
1774 throw io::IOException(); //TODO: access denied
1776 // TODO: does this work for links too?
1777 StoreObjectToStream( GetStreamForSaving() );
1779 // the replacement is changed probably, and it must be in the object stream
1780 if ( !m_pOleComponent
->IsWorkaroundActive() )
1781 m_xCachedVisualRepresentation
= uno::Reference
< io::XStream
>();
1782 SetVisReplInStream( sal_True
);
1786 if ( m_bStoreVisRepl
!= HasVisReplInStream() )
1788 if ( m_bStoreVisRepl
)
1790 // the m_xCachedVisualRepresentation must be set or it should be already stored
1791 if ( m_xCachedVisualRepresentation
.is() )
1792 InsertVisualCache_Impl( m_xObjectStream
, m_xCachedVisualRepresentation
);
1795 m_xCachedVisualRepresentation
= TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream
);
1796 SAL_WARN_IF( !m_xCachedVisualRepresentation
.is(), "embeddedobj.ole", "No representation is available!" );
1801 if ( !m_xCachedVisualRepresentation
.is() )
1802 m_xCachedVisualRepresentation
= TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream
);
1803 RemoveVisualCache_Impl( m_xObjectStream
);
1806 SetVisReplInStream( m_bStoreVisRepl
);
1809 if ( m_pOleComponent
&& m_nUpdateMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
&& !bStoreLoaded
)
1811 // the object replacement image should be updated, so the cached size as well
1812 m_bHasCachedSize
= false;
1815 // the call will cache the size in case of success
1816 // probably it might need to be done earlier, while the object is in active state
1817 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
1819 catch( const uno::Exception
& )
1825 MakeEventListenerNotification_Impl( OUString( "OnSaveDone" ));
1827 // the object can be changed only on Windows
1828 // the notification should be done only if the object is not in loaded state
1829 if ( m_pOleComponent
&& m_nUpdateMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
&& !bStoreLoaded
)
1830 MakeEventListenerNotification_Impl( OUString( "OnVisAreaChanged" ));
1834 sal_Bool SAL_CALL
OleEmbeddedObject::isReadonly()
1835 throw ( embed::WrongStateException
,
1836 uno::RuntimeException
, std::exception
)
1838 // begin wrapping related part ====================
1839 uno::Reference
< embed::XEmbedPersist
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1840 if ( xWrappedObject
.is() )
1842 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1843 return xWrappedObject
->isReadonly();
1845 // end wrapping related part ====================
1847 ::osl::MutexGuard
aGuard( m_aMutex
);
1849 throw lang::DisposedException(); // TODO
1851 if ( m_nObjectState
== -1 )
1853 // the object is still not loaded
1854 throw embed::WrongStateException( "The object persistence is not initialized!",
1855 static_cast< ::cppu::OWeakObject
* >(this) );
1858 if ( m_bWaitSaveCompleted
)
1859 throw embed::WrongStateException(
1860 "The object waits for saveCompleted() call!",
1861 static_cast< ::cppu::OWeakObject
* >(this) );
1867 void SAL_CALL
OleEmbeddedObject::reload(
1868 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1869 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1870 throw ( lang::IllegalArgumentException
,
1871 embed::WrongStateException
,
1874 uno::RuntimeException
, std::exception
)
1876 // begin wrapping related part ====================
1877 uno::Reference
< embed::XEmbedPersist
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1878 if ( xWrappedObject
.is() )
1880 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1881 xWrappedObject
->reload( lArguments
, lObjArgs
);
1884 // end wrapping related part ====================
1886 // TODO: use lObjArgs
1888 ::osl::MutexGuard
aGuard( m_aMutex
);
1890 throw lang::DisposedException(); // TODO
1892 if ( m_nObjectState
== -1 )
1894 // the object is still not loaded
1895 throw embed::WrongStateException( "The object persistence is not initialized!",
1896 static_cast< ::cppu::OWeakObject
* >(this) );
1899 if ( m_bWaitSaveCompleted
)
1900 throw embed::WrongStateException(
1901 "The object waits for saveCompleted() call!",
1902 static_cast< ::cppu::OWeakObject
* >(this) );
1905 // throw away current document
1906 // load new document from current storage
1907 // use meaningfull part of lArguments
1911 void SAL_CALL
OleEmbeddedObject::breakLink( const uno::Reference
< embed::XStorage
>& xStorage
,
1912 const OUString
& sEntName
)
1913 throw ( lang::IllegalArgumentException
,
1914 embed::WrongStateException
,
1917 uno::RuntimeException
, std::exception
)
1919 // begin wrapping related part ====================
1920 uno::Reference
< embed::XLinkageSupport
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
1921 if ( xWrappedObject
.is() )
1923 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1924 xWrappedObject
->breakLink( xStorage
, sEntName
);
1927 // end wrapping related part ====================
1929 ::osl::MutexGuard
aGuard( m_aMutex
);
1931 throw lang::DisposedException(); // TODO
1933 if ( !xStorage
.is() )
1934 throw lang::IllegalArgumentException( "No parent storage is provided!",
1935 static_cast< ::cppu::OWeakObject
* >(this),
1938 if ( sEntName
.isEmpty() )
1939 throw lang::IllegalArgumentException( "Empty element name is provided!",
1940 static_cast< ::cppu::OWeakObject
* >(this),
1943 // TODO: The object must be at least in Running state;
1944 if ( !m_bIsLink
|| m_nObjectState
== -1 || !m_pOleComponent
)
1946 // it must be a linked initialized object
1947 throw embed::WrongStateException(
1948 "The object is not a valid linked object!",
1949 static_cast< ::cppu::OWeakObject
* >(this) );
1953 throw io::IOException(); // TODO: Access denied
1955 if ( m_bWaitSaveCompleted
)
1956 throw embed::WrongStateException(
1957 "The object waits for saveCompleted() call!",
1958 static_cast< ::cppu::OWeakObject
* >(this) );
1962 if ( m_pOleComponent
)
1964 // TODO: create an object based on the link
1966 // disconnect the old temporary URL
1967 OUString aOldTempURL
= m_aTempURL
;
1970 OleComponent
* pNewOleComponent
= new OleComponent( m_xFactory
, this );
1972 pNewOleComponent
->InitEmbeddedCopyOfLink( m_pOleComponent
);
1974 catch ( const uno::Exception
& )
1976 delete pNewOleComponent
;
1977 if ( !m_aTempURL
.isEmpty() )
1978 KillFile_Impl( m_aTempURL
, m_xFactory
);
1979 m_aTempURL
= aOldTempURL
;
1984 GetRidOfComponent();
1986 catch( const uno::Exception
& )
1988 delete pNewOleComponent
;
1989 if ( !m_aTempURL
.isEmpty() )
1990 KillFile_Impl( m_aTempURL
, m_xFactory
);
1991 m_aTempURL
= aOldTempURL
;
1995 KillFile_Impl( aOldTempURL
, m_xFactory
);
1997 CreateOleComponent_Impl( pNewOleComponent
);
1999 if ( m_xParentStorage
!= xStorage
|| !m_aEntryName
.equals( sEntName
) )
2000 SwitchOwnPersistence( xStorage
, sEntName
);
2002 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
2004 // TODO: should we activate the new object if the link was activated?
2006 sal_Int32 nTargetState
= m_nObjectState
;
2007 m_nObjectState
= embed::EmbedStates::LOADED
;
2009 if ( m_nObjectState
== embed::EmbedStates::RUNNING
)
2010 m_pOleComponent
->RunObject(); // the object already was in running state, the server must be installed
2011 else // m_nObjectState == embed::EmbedStates::ACTIVE
2013 m_pOleComponent
->RunObject(); // the object already was in running state, the server must be installed
2014 m_pOleComponent
->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN
);
2017 m_nObjectState
= nTargetState
;
2020 m_bIsLink
= sal_False
;
2026 throw io::IOException(); //TODO:
2031 sal_Bool SAL_CALL
OleEmbeddedObject::isLink()
2032 throw ( embed::WrongStateException
,
2033 uno::RuntimeException
, std::exception
)
2035 // begin wrapping related part ====================
2036 uno::Reference
< embed::XLinkageSupport
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
2037 if ( xWrappedObject
.is() )
2039 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
2040 return xWrappedObject
->isLink();
2042 // end wrapping related part ====================
2044 ::osl::MutexGuard
aGuard( m_aMutex
);
2046 throw lang::DisposedException(); // TODO
2052 OUString SAL_CALL
OleEmbeddedObject::getLinkURL()
2053 throw ( embed::WrongStateException
,
2055 uno::RuntimeException
, std::exception
)
2057 // begin wrapping related part ====================
2058 uno::Reference
< embed::XLinkageSupport
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
2059 if ( xWrappedObject
.is() )
2061 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
2062 return xWrappedObject
->getLinkURL();
2064 // end wrapping related part ====================
2066 ::osl::MutexGuard
aGuard( m_aMutex
);
2068 throw lang::DisposedException(); // TODO
2070 if ( m_bWaitSaveCompleted
)
2071 throw embed::WrongStateException(
2072 "The object waits for saveCompleted() call!",
2073 static_cast< ::cppu::OWeakObject
* >(this) );
2076 throw embed::WrongStateException(
2077 "The object is not a link object!",
2078 static_cast< ::cppu::OWeakObject
* >(this) );
2080 // TODO: probably the link URL can be retrieved from OLE
2085 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */