Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / embeddedobj / source / msole / olepersist.cxx
blob528d0fc5bdfa8b1fe1bf6531a07d6b4a3e1175fd
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 <com/sun/star/embed/EmbedStates.hpp>
22 #include <com/sun/star/embed/EmbedVerbs.hpp>
23 #include <com/sun/star/embed/EntryInitModes.hpp>
24 #include <com/sun/star/embed/XStorage.hpp>
25 #include <com/sun/star/embed/XTransactedObject.hpp>
26 #include <com/sun/star/embed/ElementModes.hpp>
27 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
28 #include <com/sun/star/embed/Aspects.hpp>
29 #include <com/sun/star/embed/XOptimizedStorage.hpp>
30 #include <com/sun/star/lang/XComponent.hpp>
31 #include <com/sun/star/lang/DisposedException.hpp>
32 #include <com/sun/star/container/XNameAccess.hpp>
33 #include <com/sun/star/container/XNameContainer.hpp>
34 #include <com/sun/star/io/TempFile.hpp>
35 #include <com/sun/star/io/XSeekable.hpp>
36 #include <com/sun/star/io/XTruncate.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
40 #include <comphelper/processfactory.hxx>
41 #include <comphelper/storagehelper.hxx>
42 #include <comphelper/mimeconfighelper.hxx>
43 #include <comphelper/classids.hxx>
44 #include <osl/thread.hxx>
46 #include <olecomponent.hxx>
47 #include <closepreventer.hxx>
49 using namespace ::com::sun::star;
50 using namespace ::comphelper;
52 //-------------------------------------------------------------------------
53 sal_Bool KillFile_Impl( const OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
55 if ( !xFactory.is() )
56 return sal_False;
58 sal_Bool bRet = sal_False;
60 try
62 uno::Reference < ucb::XSimpleFileAccess3 > xAccess(
63 ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory) ) );
65 xAccess->kill( aURL );
66 bRet = sal_True;
68 catch( const uno::Exception& )
72 return bRet;
75 //----------------------------------------------
76 OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
78 SAL_WARN_IF( !xFactory.is(), "embeddedobj.ole", "No factory is provided!" );
80 OUString aResult;
82 uno::Reference < beans::XPropertySet > xTempFile(
83 io::TempFile::create(comphelper::getComponentContext(xFactory)),
84 uno::UNO_QUERY_THROW );
86 try {
87 xTempFile->setPropertyValue("RemoveFile", uno::makeAny( sal_False ) );
88 uno::Any aUrl = xTempFile->getPropertyValue("Uri");
89 aUrl >>= aResult;
91 catch ( const uno::Exception& )
95 if ( aResult.isEmpty() )
96 throw uno::RuntimeException(); // TODO: can not create tempfile
98 return aResult;
101 //-----------------------------------------------
102 OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream,
103 const uno::Reference< lang::XMultiServiceFactory >& xFactory )
104 throw ( io::IOException,
105 uno::RuntimeException )
107 OSL_ENSURE( xInStream.is() && xFactory.is(), "Wrong parameters are provided!\n" );
109 OUString aResult = GetNewTempFileURL_Impl( xFactory );
111 if ( !aResult.isEmpty() )
113 try {
114 uno::Reference < ucb::XSimpleFileAccess3 > xTempAccess(
115 ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory) ) );
117 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aResult );
118 if ( xTempOutStream.is() )
120 // copy stream contents to the file
121 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
122 xTempOutStream->closeOutput();
123 xTempOutStream = uno::Reference< io::XOutputStream >();
125 else
126 throw io::IOException(); // TODO:
128 catch( const packages::WrongPasswordException& )
130 KillFile_Impl( aResult, xFactory );
131 throw io::IOException(); //TODO:
133 catch( const io::IOException& )
135 KillFile_Impl( aResult, xFactory );
136 throw;
138 catch( const uno::RuntimeException& )
140 KillFile_Impl( aResult, xFactory );
141 throw;
143 catch( const uno::Exception& )
145 KillFile_Impl( aResult, xFactory );
146 aResult = OUString();
150 return aResult;
152 #ifdef WNT
153 OUString GetNewFilledTempFile_Impl( const uno::Reference< embed::XOptimizedStorage >& xParentStorage, const OUString& aEntryName, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
154 throw( io::IOException, uno::RuntimeException )
156 OUString aResult;
160 uno::Reference < beans::XPropertySet > xTempFile(
161 io::TempFile::create(comphelper::getComponentContext(xFactory)),
162 uno::UNO_QUERY );
163 uno::Reference < io::XStream > xTempStream( xTempFile, uno::UNO_QUERY_THROW );
165 xParentStorage->copyStreamElementData( aEntryName, xTempStream );
167 xTempFile->setPropertyValue("RemoveFile", uno::makeAny( sal_False ) );
168 uno::Any aUrl = xTempFile->getPropertyValue("Uri");
169 aUrl >>= aResult;
171 catch( const uno::RuntimeException& )
173 throw;
175 catch( const uno::Exception& )
179 if ( aResult.isEmpty() )
180 throw io::IOException();
182 return aResult;
185 //------------------------------------------------------
186 void SetStreamMediaType_Impl( const uno::Reference< io::XStream >& xStream, const OUString& aMediaType )
188 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY );
189 if ( !xPropSet.is() )
190 throw uno::RuntimeException(); // TODO: all the storage streams must support XPropertySet
192 xPropSet->setPropertyValue("MediaType", uno::makeAny( aMediaType ) );
194 #endif
195 //------------------------------------------------------
196 void LetCommonStoragePassBeUsed_Impl( const uno::Reference< io::XStream >& xStream )
198 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY );
199 if ( !xPropSet.is() )
200 throw uno::RuntimeException(); // Only StorageStreams must be provided here, they must implement the interface
202 xPropSet->setPropertyValue("UseCommonStoragePasswordEncryption",
203 uno::makeAny( (sal_Bool)sal_True ) );
205 #ifdef WNT
206 //------------------------------------------------------
207 void VerbExecutionController::StartControlExecution()
209 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
211 // the class is used to detect STAMPIT object, that can never be active
212 if ( !m_bVerbExecutionInProgress && !m_bWasEverActive )
214 m_bVerbExecutionInProgress = sal_True;
215 m_nVerbExecutionThreadIdentifier = osl::Thread::getCurrentIdentifier();
216 m_bChangedOnVerbExecution = sal_False;
220 //------------------------------------------------------
221 sal_Bool VerbExecutionController::EndControlExecution_WasModified()
223 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
225 sal_Bool bResult = sal_False;
226 if ( m_bVerbExecutionInProgress && m_nVerbExecutionThreadIdentifier == osl::Thread::getCurrentIdentifier() )
228 bResult = m_bChangedOnVerbExecution;
229 m_bVerbExecutionInProgress = sal_False;
232 return bResult;
235 //------------------------------------------------------
236 void VerbExecutionController::ModificationNotificationIsDone()
238 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
240 if ( m_bVerbExecutionInProgress && osl::Thread::getCurrentIdentifier() == m_nVerbExecutionThreadIdentifier )
241 m_bChangedOnVerbExecution = sal_True;
243 #endif
244 //-----------------------------------------------
245 void VerbExecutionController::LockNotification()
247 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
248 if ( m_nNotificationLock < SAL_MAX_INT32 )
249 m_nNotificationLock++;
252 //-----------------------------------------------
253 void VerbExecutionController::UnlockNotification()
255 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
256 if ( m_nNotificationLock > 0 )
257 m_nNotificationLock--;
260 //-----------------------------------------------
261 uno::Reference< io::XStream > OleEmbeddedObject::GetNewFilledTempStream_Impl( const uno::Reference< io::XInputStream >& xInStream )
262 throw( io::IOException )
264 SAL_WARN_IF( !xInStream.is(), "embeddedobj.ole", "Wrong parameter is provided!" );
266 uno::Reference < io::XStream > xTempFile(
267 io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
268 uno::UNO_QUERY_THROW );
270 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream();
271 if ( xTempOutStream.is() )
273 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
274 xTempOutStream->flush();
276 else
277 throw io::IOException(); // TODO:
279 return xTempFile;
282 //------------------------------------------------------
283 uno::Reference< io::XStream > OleEmbeddedObject::TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream )
284 throw ( uno::Exception )
286 // TODO/LATER: Actually this should be done by a centralized component ( may be a graphical filter )
287 if ( !m_xFactory.is() )
288 throw uno::RuntimeException();
290 uno::Reference< io::XInputStream > xInStream = xStream->getInputStream();
291 if ( !xInStream.is() )
292 throw uno::RuntimeException();
294 uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW );
295 xSeek->seek( 0 );
297 uno::Sequence< sal_Int8 > aData( 8 );
298 sal_Int32 nRead = xInStream->readBytes( aData, 8 );
299 xSeek->seek( 0 );
301 if ( ( nRead >= 2 && aData[0] == 'B' && aData[1] == 'M' )
302 || ( nRead >= 4 && aData[0] == 1 && aData[1] == 0 && aData[2] == 9 && aData[3] == 0 ) )
304 // it should be a bitmap or a Metafile
305 return xStream;
309 sal_uInt32 nHeaderOffset = 0;
310 if ( ( nRead >= 8 && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1 )
311 && ( aData[4] == 2 || aData[4] == 3 || aData[4] == 14 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 )
313 nHeaderOffset = 40;
314 xSeek->seek( 8 );
316 // TargetDevice might be used in future, currently the cache has specified NULL
317 uno::Sequence< sal_Int8 > aHeadData( 4 );
318 nRead = xInStream->readBytes( aHeadData, 4 );
319 sal_uInt32 nLen = 0;
320 if ( nRead == 4 && aHeadData.getLength() == 4 )
321 nLen = ( ( ( (sal_uInt32)aHeadData[3] * 0x100 + (sal_uInt32)aHeadData[2] ) * 0x100 ) + (sal_uInt32)aHeadData[1] ) * 0x100 + (sal_uInt32)aHeadData[0];
322 if ( nLen > 4 )
324 xInStream->skipBytes( nLen - 4 );
325 nHeaderOffset += nLen - 4;
329 else if ( nRead > 4 )
331 // check whether the first bytes represent the size
332 sal_uInt32 nSize = 0;
333 for ( sal_Int32 nInd = 3; nInd >= 0; nInd-- )
334 nSize = ( nSize << 8 ) + (sal_uInt8)aData[nInd];
336 if ( nSize == xSeek->getLength() - 4 )
337 nHeaderOffset = 4;
340 if ( nHeaderOffset )
342 // this is either a bitmap or a metafile clipboard format, retrieve the pure stream
343 uno::Reference < io::XStream > xResult(
344 io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
345 uno::UNO_QUERY_THROW );
346 uno::Reference < io::XSeekable > xResultSeek( xResult, uno::UNO_QUERY_THROW );
347 uno::Reference < io::XOutputStream > xResultOut = xResult->getOutputStream();
348 uno::Reference < io::XInputStream > xResultIn = xResult->getInputStream();
349 if ( !xResultOut.is() || !xResultIn.is() )
350 throw uno::RuntimeException();
352 xSeek->seek( nHeaderOffset ); // header size for these formats
353 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xResultOut );
354 xResultOut->closeOutput();
355 xResultSeek->seek( 0 );
356 xSeek->seek( 0 );
358 return xResult;
361 return uno::Reference< io::XStream >();
364 //------------------------------------------------------
365 void OleEmbeddedObject::InsertVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream,
366 const uno::Reference< io::XStream >& xCachedVisualRepresentation )
367 throw ( uno::Exception )
369 OSL_ENSURE( xTargetStream.is() && xCachedVisualRepresentation.is(), "Invalid argumants!\n" );
371 if ( !xTargetStream.is() || !xCachedVisualRepresentation.is() )
372 throw uno::RuntimeException();
374 uno::Sequence< uno::Any > aArgs( 2 );
375 aArgs[0] <<= xTargetStream;
376 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
378 uno::Reference< container::XNameContainer > xNameContainer(
379 m_xFactory->createInstanceWithArguments(
380 OUString( "com.sun.star.embed.OLESimpleStorage" ),
381 aArgs ),
382 uno::UNO_QUERY );
384 if ( !xNameContainer.is() )
385 throw uno::RuntimeException();
387 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY_THROW );
388 if ( xCachedSeek.is() )
389 xCachedSeek->seek( 0 );
391 uno::Reference < io::XStream > xTempFile(
392 io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
393 uno::UNO_QUERY_THROW );
395 uno::Reference< io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW );
396 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream();
397 if ( xTempOutStream.is() )
399 // the OlePres stream must have additional header
400 // TODO/LATER: might need to be extended in future ( actually makes sence only for SO7 format )
401 uno::Reference< io::XInputStream > xInCacheStream = xCachedVisualRepresentation->getInputStream();
402 if ( !xInCacheStream.is() )
403 throw uno::RuntimeException();
405 // write 0xFFFFFFFF at the beginning
406 uno::Sequence< sal_Int8 > aData( 4 );
407 *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF;
409 xTempOutStream->writeBytes( aData );
411 // write clipboard format
412 uno::Sequence< sal_Int8 > aSigData( 2 );
413 xInCacheStream->readBytes( aSigData, 2 );
414 if ( aSigData.getLength() < 2 )
415 throw io::IOException();
417 if ( aSigData[0] == 'B' && aSigData[1] == 'M' )
419 // it's a bitmap
420 aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0;
422 else
424 // treat it as a metafile
425 aData[0] = 0x03; aData[1] = 0; aData[2] = 0; aData[3] = 0;
427 xTempOutStream->writeBytes( aData );
429 // write job related information
430 aData[0] = 0x04; aData[1] = 0; aData[2] = 0; aData[3] = 0;
431 xTempOutStream->writeBytes( aData );
433 // write aspect
434 aData[0] = 0x01; aData[1] = 0; aData[2] = 0; aData[3] = 0;
435 xTempOutStream->writeBytes( aData );
437 // write l-index
438 *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF;
439 xTempOutStream->writeBytes( aData );
441 // write adv. flags
442 aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0;
443 xTempOutStream->writeBytes( aData );
445 // write compression
446 *( (sal_uInt32*)aData.getArray() ) = 0x0;
447 xTempOutStream->writeBytes( aData );
449 // get the size
450 awt::Size aSize = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
451 sal_Int32 nIndex = 0;
453 // write width
454 for ( nIndex = 0; nIndex < 4; nIndex++ )
456 aData[nIndex] = (sal_Int8)( aSize.Width % 0x100 );
457 aSize.Width /= 0x100;
459 xTempOutStream->writeBytes( aData );
461 // write height
462 for ( nIndex = 0; nIndex < 4; nIndex++ )
464 aData[nIndex] = (sal_Int8)( aSize.Height % 0x100 );
465 aSize.Height /= 0x100;
467 xTempOutStream->writeBytes( aData );
469 // write garbage, it will be overwritten by the size
470 xTempOutStream->writeBytes( aData );
472 // write first bytes that was used to detect the type
473 xTempOutStream->writeBytes( aSigData );
475 // write the rest of the stream
476 ::comphelper::OStorageHelper::CopyInputToOutput( xInCacheStream, xTempOutStream );
478 // write the size of the stream
479 sal_Int64 nLength = xTempSeek->getLength() - 40;
480 if ( nLength < 0 || nLength >= 0xFFFFFFFF )
482 SAL_WARN( "embeddedobj.ole", "Length is not acceptable!" );
483 return;
485 for ( sal_Int32 nInd = 0; nInd < 4; nInd++ )
487 aData[nInd] = (sal_Int8)( ( (sal_uInt64) nLength ) % 0x100 );
488 nLength /= 0x100;
490 xTempSeek->seek( 36 );
491 xTempOutStream->writeBytes( aData );
493 xTempOutStream->flush();
495 xTempSeek->seek( 0 );
496 if ( xCachedSeek.is() )
497 xCachedSeek->seek( 0 );
499 else
500 throw io::IOException(); // TODO:
502 // insert the result file as replacement image
503 OUString aCacheName = "\002OlePres000";
504 if ( xNameContainer->hasByName( aCacheName ) )
505 xNameContainer->replaceByName( aCacheName, uno::makeAny( xTempFile ) );
506 else
507 xNameContainer->insertByName( aCacheName, uno::makeAny( xTempFile ) );
509 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY );
510 if ( !xTransacted.is() )
511 throw uno::RuntimeException();
513 xTransacted->commit();
516 //------------------------------------------------------
517 void OleEmbeddedObject::RemoveVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream )
518 throw ( uno::Exception )
520 OSL_ENSURE( xTargetStream.is(), "Invalid argumant!\n" );
521 if ( !xTargetStream.is() )
522 throw uno::RuntimeException();
524 uno::Sequence< uno::Any > aArgs( 2 );
525 aArgs[0] <<= xTargetStream;
526 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
527 uno::Reference< container::XNameContainer > xNameContainer(
528 m_xFactory->createInstanceWithArguments(
529 OUString( "com.sun.star.embed.OLESimpleStorage" ),
530 aArgs ),
531 uno::UNO_QUERY );
533 if ( !xNameContainer.is() )
534 throw uno::RuntimeException();
536 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ )
538 OUString aStreamName = "\002OlePres00" + OUString::number( nInd );
539 if ( xNameContainer->hasByName( aStreamName ) )
540 xNameContainer->removeByName( aStreamName );
543 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY );
544 if ( !xTransacted.is() )
545 throw uno::RuntimeException();
547 xTransacted->commit();
550 //------------------------------------------------------
551 void OleEmbeddedObject::SetVisReplInStream( sal_Bool bExists )
553 m_bVisReplInitialized = sal_True;
554 m_bVisReplInStream = bExists;
557 //------------------------------------------------------
558 sal_Bool OleEmbeddedObject::HasVisReplInStream()
560 if ( !m_bVisReplInitialized )
562 if ( m_xCachedVisualRepresentation.is() )
563 SetVisReplInStream( sal_True );
564 else
566 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::HasVisualReplInStream, analizing" );
568 uno::Reference< io::XInputStream > xStream;
570 OSL_ENSURE( !m_pOleComponent || !m_aTempURL.isEmpty(), "The temporary file must exist if there is a component!\n" );
571 if ( !m_aTempURL.isEmpty() )
575 // open temporary file for reading
576 uno::Reference < ucb::XSimpleFileAccess3 > xTempAccess(
577 ucb::SimpleFileAccess::create( comphelper::getComponentContext(m_xFactory) ) );
579 xStream = xTempAccess->openFileRead( m_aTempURL );
581 catch( const uno::Exception& )
585 if ( !xStream.is() )
586 xStream = m_xObjectStream->getInputStream();
588 if ( xStream.is() )
590 sal_Bool bExists = sal_False;
592 uno::Sequence< uno::Any > aArgs( 2 );
593 aArgs[0] <<= xStream;
594 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
595 uno::Reference< container::XNameContainer > xNameContainer(
596 m_xFactory->createInstanceWithArguments(
597 OUString( "com.sun.star.embed.OLESimpleStorage" ),
598 aArgs ),
599 uno::UNO_QUERY );
601 if ( xNameContainer.is() )
603 for ( sal_uInt8 nInd = 0; nInd < 10 && !bExists; nInd++ )
605 OUString aStreamName = "\002OlePres00" + OUString::number( nInd );
608 bExists = xNameContainer->hasByName( aStreamName );
610 catch( const uno::Exception& )
615 SetVisReplInStream( bExists );
620 return m_bVisReplInStream;
623 //------------------------------------------------------
624 uno::Reference< io::XStream > OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation_Impl(
625 const uno::Reference< io::XStream >& xStream,
626 sal_Bool bAllowToRepair50 )
627 throw ()
629 uno::Reference< io::XStream > xResult;
631 if ( xStream.is() )
633 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation, retrieving" );
635 uno::Reference< container::XNameContainer > xNameContainer;
636 uno::Sequence< uno::Any > aArgs( 2 );
637 aArgs[0] <<= xStream;
638 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
641 xNameContainer = uno::Reference< container::XNameContainer >(
642 m_xFactory->createInstanceWithArguments(
643 OUString( "com.sun.star.embed.OLESimpleStorage" ),
644 aArgs ),
645 uno::UNO_QUERY );
647 catch( const uno::Exception& )
650 if ( xNameContainer.is() )
652 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ )
654 OUString aStreamName = "\002OlePres00" + OUString::number( nInd );
655 uno::Reference< io::XStream > xCachedCopyStream;
658 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() )
660 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream );
661 if ( xResult.is() )
662 break;
665 catch( const uno::Exception& )
668 if ( nInd == 0 )
670 // to be compatible with the old versions Ole10Native is checked after OlePress000
671 aStreamName = "\001Ole10Native";
674 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() )
676 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream );
677 if ( xResult.is() )
678 break;
681 catch( const uno::Exception& )
688 if ( bAllowToRepair50 && !xResult.is() )
690 OUString aOrigContName( "Ole-Object" );
691 if ( xNameContainer->hasByName( aOrigContName ) )
693 uno::Reference< embed::XClassifiedObject > xClassified( xNameContainer, uno::UNO_QUERY_THROW );
694 if ( MimeConfigurationHelper::ClassIDsEqual( xClassified->getClassID(), MimeConfigurationHelper::GetSequenceClassID( SO3_OUT_CLASSID ) ) )
696 // this is an OLE object wrongly stored in 5.0 format
697 // this object must be repaired since SO7 has done it
699 uno::Reference< io::XOutputStream > xOutputStream = xStream->getOutputStream();
700 uno::Reference< io::XTruncate > xTruncate( xOutputStream, uno::UNO_QUERY_THROW );
702 uno::Reference< io::XInputStream > xOrigInputStream;
703 if ( ( xNameContainer->getByName( aOrigContName ) >>= xOrigInputStream )
704 && xOrigInputStream.is() )
706 // the provided input stream must be based on temporary medium and must be independent
707 // from the stream the storage is based on
708 uno::Reference< io::XSeekable > xOrigSeekable( xOrigInputStream, uno::UNO_QUERY );
709 if ( xOrigSeekable.is() )
710 xOrigSeekable->seek( 0 );
712 uno::Reference< lang::XComponent > xNameContDisp( xNameContainer, uno::UNO_QUERY_THROW );
713 xNameContDisp->dispose(); // free the original stream
715 xTruncate->truncate();
716 ::comphelper::OStorageHelper::CopyInputToOutput( xOrigInputStream, xOutputStream );
717 xOutputStream->flush();
719 if ( xStream == m_xObjectStream )
721 if ( !m_aTempURL.isEmpty() )
723 // this is the own stream, so the temporary URL must be cleaned if it exists
724 KillFile_Impl( m_aTempURL, m_xFactory );
725 m_aTempURL = OUString();
728 #ifdef WNT
729 // retry to create the component after recovering
730 GetRidOfComponent();
734 CreateOleComponentAndLoad_Impl( NULL );
735 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction
737 catch( const uno::Exception& )
739 GetRidOfComponent();
741 #endif
744 xResult = TryToRetrieveCachedVisualRepresentation_Impl( xStream, sal_False );
750 catch( const uno::Exception& )
755 return xResult;
758 //------------------------------------------------------
759 void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
760 const uno::Reference< io::XStream >& xNewObjectStream,
761 const OUString& aNewName )
763 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
765 SAL_WARN_IF( xNewObjectStream != m_xObjectStream, "embeddedobj.ole", "The streams must be the same!" );
766 return;
769 try {
770 uno::Reference< lang::XComponent > xComponent( m_xObjectStream, uno::UNO_QUERY );
771 OSL_ENSURE( !m_xObjectStream.is() || xComponent.is(), "Wrong stream implementation!" );
772 if ( xComponent.is() )
773 xComponent->dispose();
775 catch ( const uno::Exception& )
779 m_xObjectStream = xNewObjectStream;
780 m_xParentStorage = xNewParentStorage;
781 m_aEntryName = aNewName;
784 //------------------------------------------------------
785 void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
786 const OUString& aNewName )
788 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
789 return;
791 sal_Int32 nStreamMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
793 uno::Reference< io::XStream > xNewOwnStream = xNewParentStorage->openStreamElement( aNewName, nStreamMode );
794 SAL_WARN_IF( !xNewOwnStream.is(), "embeddedobj.ole", "The method can not return empty reference!" );
796 SwitchOwnPersistence( xNewParentStorage, xNewOwnStream, aNewName );
799 #ifdef WNT
800 //----------------------------------------------
801 sal_Bool OleEmbeddedObject::SaveObject_Impl()
803 sal_Bool bResult = sal_False;
805 if ( m_xClientSite.is() )
809 m_xClientSite->saveObject();
810 bResult = sal_True;
812 catch( const uno::Exception& )
817 return bResult;
820 //----------------------------------------------
821 sal_Bool OleEmbeddedObject::OnShowWindow_Impl( sal_Bool bShow )
823 ::osl::ResettableMutexGuard aGuard( m_aMutex );
825 sal_Bool bResult = sal_False;
827 SAL_WARN_IF( m_nObjectState == -1, "embeddedobj.ole", "The object has no persistence!" );
828 SAL_WARN_IF( m_nObjectState == embed::EmbedStates::LOADED, "embeddedobj.ole", "The object get OnShowWindow in loaded state!" );
829 if ( m_nObjectState == -1 || m_nObjectState == embed::EmbedStates::LOADED )
830 return sal_False;
832 // the object is either activated or deactivated
833 sal_Int32 nOldState = m_nObjectState;
834 if ( bShow && m_nObjectState == embed::EmbedStates::RUNNING )
836 m_nObjectState = embed::EmbedStates::ACTIVE;
837 m_aVerbExecutionController.ObjectIsActive();
839 aGuard.clear();
840 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
842 else if ( !bShow && m_nObjectState == embed::EmbedStates::ACTIVE )
844 m_nObjectState = embed::EmbedStates::RUNNING;
845 aGuard.clear();
846 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
849 if ( m_xClientSite.is() )
853 m_xClientSite->visibilityChanged( bShow );
854 bResult = sal_True;
856 catch( const uno::Exception& )
861 return bResult;
864 //------------------------------------------------------
865 void OleEmbeddedObject::OnIconChanged_Impl()
867 // TODO/LATER: currently this notification seems to be impossible
868 // MakeEventListenerNotification_Impl( OUString( "OnIconChanged" ) );
871 //------------------------------------------------------
872 void OleEmbeddedObject::OnViewChanged_Impl()
874 if ( m_bDisposed )
875 throw lang::DisposedException();
877 // For performance reasons the notification currently is ignored, STAMPIT object is the exception,
878 // it can never be active and never call SaveObject, so it is the only way to detect that it is changed
880 // ==== the STAMPIT related solution =============================
881 // the following variable is used to detect whether the object was modified during verb execution
882 m_aVerbExecutionController.ModificationNotificationIsDone();
884 // The following things are controlled by VerbExecutionController:
885 // - if the verb execution is in progress and the view is changed the object will be stored
886 // after the execution, so there is no need to send the notification.
887 // - the STAMPIT object can never be active.
888 if ( m_aVerbExecutionController.CanDoNotification()
889 && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE )
891 OSL_ENSURE( MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0x852ee1c9, 0x9058, 0x44ba, 0x8c,0x6c,0x0c,0x5f,0xc6,0x6b,0xdb,0x8d ) )
892 || MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0xcf1b4491, 0xbea3, 0x4c9f, 0xa7,0x0f,0x22,0x1b,0x1e,0xca,0xef,0x3e ) ),
893 "Expected to be triggered for STAMPIT only! Please contact developers!\n" );
895 // The view is changed while the object is in running state, save the new object
896 m_xCachedVisualRepresentation = uno::Reference< io::XStream >();
897 SaveObject_Impl();
898 MakeEventListenerNotification_Impl( OUString( "OnVisAreaChanged" ) );
900 // ===============================================================
903 //------------------------------------------------------
904 void OleEmbeddedObject::OnClosed_Impl()
906 if ( m_bDisposed )
907 throw lang::DisposedException();
909 if ( m_nObjectState != embed::EmbedStates::LOADED )
911 sal_Int32 nOldState = m_nObjectState;
912 m_nObjectState = embed::EmbedStates::LOADED;
913 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
917 //------------------------------------------------------
918 OUString OleEmbeddedObject::CreateTempURLEmpty_Impl()
920 SAL_WARN_IF( !m_aTempURL.isEmpty(), "embeddedobj.ole", "The object has already the temporary file!" );
921 m_aTempURL = GetNewTempFileURL_Impl( m_xFactory );
923 return m_aTempURL;
926 //------------------------------------------------------
927 OUString OleEmbeddedObject::GetTempURL_Impl()
929 if ( m_aTempURL.isEmpty() )
931 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::GetTempURL_Impl, tempfile creation" );
933 // if there is no temporary file, it will be created from the own entry
934 uno::Reference< embed::XOptimizedStorage > xOptParStorage( m_xParentStorage, uno::UNO_QUERY );
935 if ( xOptParStorage.is() )
937 m_aTempURL = GetNewFilledTempFile_Impl( xOptParStorage, m_aEntryName, m_xFactory );
939 else if ( m_xObjectStream.is() )
941 // load object from the stream
942 uno::Reference< io::XInputStream > xInStream = m_xObjectStream->getInputStream();
943 if ( !xInStream.is() )
944 throw io::IOException(); // TODO: access denied
946 m_aTempURL = GetNewFilledTempFile_Impl( xInStream, m_xFactory );
950 return m_aTempURL;
953 //------------------------------------------------------
954 void OleEmbeddedObject::CreateOleComponent_Impl( OleComponent* pOleComponent )
956 if ( !m_pOleComponent )
958 m_pOleComponent = pOleComponent ? pOleComponent : new OleComponent( m_xFactory, this );
959 m_pOleComponent->acquire(); // TODO: needs holder?
961 if ( !m_xClosePreventer.is() )
962 m_xClosePreventer = uno::Reference< util::XCloseListener >(
963 static_cast< ::cppu::OWeakObject* >( new OClosePreventer ),
964 uno::UNO_QUERY );
966 m_pOleComponent->addCloseListener( m_xClosePreventer );
970 //------------------------------------------------------
971 void OleEmbeddedObject::CreateOleComponentAndLoad_Impl( OleComponent* pOleComponent )
973 if ( !m_pOleComponent )
975 if ( !m_xObjectStream.is() )
976 throw uno::RuntimeException();
978 CreateOleComponent_Impl( pOleComponent );
980 // after the loading the object can appear as a link
981 // will be detected later by olecomponent
983 GetTempURL_Impl();
984 if ( m_aTempURL.isEmpty() )
985 throw uno::RuntimeException(); // TODO
987 m_pOleComponent->LoadEmbeddedObject( m_aTempURL );
991 //------------------------------------------------------
992 void OleEmbeddedObject::CreateOleComponentFromClipboard_Impl( OleComponent* pOleComponent )
994 if ( !m_pOleComponent )
996 if ( !m_xObjectStream.is() )
997 throw uno::RuntimeException();
999 CreateOleComponent_Impl( pOleComponent );
1001 // after the loading the object can appear as a link
1002 // will be detected later by olecomponent
1003 m_pOleComponent->CreateObjectFromClipboard();
1007 //------------------------------------------------------
1008 uno::Reference< io::XOutputStream > OleEmbeddedObject::GetStreamForSaving()
1010 if ( !m_xObjectStream.is() )
1011 throw uno::RuntimeException(); //TODO:
1013 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream();
1014 if ( !xOutStream.is() )
1015 throw io::IOException(); //TODO: access denied
1017 uno::Reference< io::XTruncate > xTruncate( xOutStream, uno::UNO_QUERY );
1018 if ( !xTruncate.is() )
1019 throw uno::RuntimeException(); //TODO:
1021 xTruncate->truncate();
1023 return xOutStream;
1026 //----------------------------------------------
1027 void OleEmbeddedObject::StoreObjectToStream( uno::Reference< io::XOutputStream > xOutStream )
1028 throw ( uno::Exception )
1030 // this method should be used only on windows
1031 if ( m_pOleComponent )
1032 m_pOleComponent->StoreOwnTmpIfNecessary();
1034 // now all the changes should be in temporary location
1035 if ( m_aTempURL.isEmpty() )
1036 throw uno::RuntimeException();
1038 // open temporary file for reading
1039 uno::Reference < ucb::XSimpleFileAccess3 > xTempAccess(
1040 ucb::SimpleFileAccess::create( comphelper::getComponentContext(m_xFactory) ) );
1042 uno::Reference< io::XInputStream > xTempInStream = xTempAccess->openFileRead( m_aTempURL );
1043 SAL_WARN_IF( !xTempInStream.is(), "embeddedobj.ole", "The object's temporary file can not be reopened for reading!" );
1045 // TODO: use bStoreVisReplace
1047 if ( xTempInStream.is() )
1049 // write all the contents to XOutStream
1050 uno::Reference< io::XTruncate > xTrunc( xOutStream, uno::UNO_QUERY );
1051 if ( !xTrunc.is() )
1052 throw uno::RuntimeException(); //TODO:
1054 xTrunc->truncate();
1056 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutStream );
1058 else
1059 throw io::IOException(); // TODO:
1061 // TODO: should the view replacement be in the stream ???
1062 // probably it must be specified on storing
1064 #endif
1065 //------------------------------------------------------
1066 void OleEmbeddedObject::StoreToLocation_Impl(
1067 const uno::Reference< embed::XStorage >& xStorage,
1068 const OUString& sEntName,
1069 const uno::Sequence< beans::PropertyValue >& lObjArgs,
1070 sal_Bool bSaveAs )
1071 throw ( uno::Exception )
1073 // TODO: use lObjArgs
1074 // TODO: exchange StoreVisualReplacement by SO file format version?
1076 if ( m_nObjectState == -1 )
1078 // the object is still not loaded
1079 throw embed::WrongStateException( OUString( "Can't store object without persistence!\n" ),
1080 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1083 if ( m_bWaitSaveCompleted )
1084 throw embed::WrongStateException(
1085 OUString( "The object waits for saveCompleted() call!\n" ),
1086 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1088 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" );
1090 sal_Bool bVisReplIsStored = sal_False;
1092 sal_Bool bTryOptimization = sal_False;
1093 sal_Bool bStoreVis = m_bStoreVisRepl;
1094 uno::Reference< io::XStream > xCachedVisualRepresentation;
1095 for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1097 if ( lObjArgs[nInd].Name == "StoreVisualReplacement" )
1098 lObjArgs[nInd].Value >>= bStoreVis;
1099 else if ( lObjArgs[nInd].Name == "VisualReplacement" )
1100 lObjArgs[nInd].Value >>= xCachedVisualRepresentation;
1101 else if ( lObjArgs[nInd].Name == "CanTryOptimization" )
1102 lObjArgs[nInd].Value >>= bTryOptimization;
1105 // ignore visual representation provided from outside if it should not be stored
1106 if ( !bStoreVis )
1107 xCachedVisualRepresentation = uno::Reference< io::XStream >();
1109 if ( bStoreVis && !HasVisReplInStream() && !xCachedVisualRepresentation.is() )
1110 throw io::IOException(); // TODO: there is no cached visual representation and nothing is provided from outside
1112 // if the representation is provided from outside it should be copied to a local stream
1113 sal_Bool bNeedLocalCache = xCachedVisualRepresentation.is();
1115 uno::Reference< io::XStream > xTargetStream;
1117 sal_Bool bStoreLoaded = sal_False;
1118 if ( m_nObjectState == embed::EmbedStates::LOADED
1119 #ifdef WNT
1120 // if the object was NOT modified after storing it can be just copied
1121 // as if it was in loaded state
1122 || ( m_pOleComponent && !m_pOleComponent->IsDirty() )
1123 #endif
1126 sal_Bool bOptimizedCopyingDone = sal_False;
1128 if ( bTryOptimization && bStoreVis == HasVisReplInStream() )
1132 uno::Reference< embed::XOptimizedStorage > xSourceOptStor( m_xParentStorage, uno::UNO_QUERY_THROW );
1133 uno::Reference< embed::XOptimizedStorage > xTargetOptStor( xStorage, uno::UNO_QUERY_THROW );
1134 xSourceOptStor->copyElementDirectlyTo( m_aEntryName, xTargetOptStor, sEntName );
1135 bOptimizedCopyingDone = sal_True;
1137 catch( const uno::Exception& )
1142 if ( !bOptimizedCopyingDone )
1144 // if optimized copying fails a normal one should be tried
1145 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
1148 // the locally retrieved representation is always preferable
1149 // since the object is in loaded state the representation is unchanged
1150 if ( m_xCachedVisualRepresentation.is() )
1152 xCachedVisualRepresentation = m_xCachedVisualRepresentation;
1153 bNeedLocalCache = sal_False;
1156 bVisReplIsStored = HasVisReplInStream();
1157 bStoreLoaded = sal_True;
1159 #ifdef WNT
1160 else if ( m_pOleComponent )
1162 xTargetStream =
1163 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE );
1164 if ( !xTargetStream.is() )
1165 throw io::IOException(); //TODO: access denied
1167 SetStreamMediaType_Impl( xTargetStream, OUString( "application/vnd.sun.star.oleobject" ));
1168 uno::Reference< io::XOutputStream > xOutStream = xTargetStream->getOutputStream();
1169 if ( !xOutStream.is() )
1170 throw io::IOException(); //TODO: access denied
1172 StoreObjectToStream( xOutStream );
1173 bVisReplIsStored = sal_True;
1175 if ( bSaveAs )
1177 // no need to do it on StoreTo since in this case the replacement is in the stream
1178 // and there is no need to cache it even if it is thrown away because the object
1179 // is not changed by StoreTo action
1181 uno::Reference< io::XStream > xTmpCVRepresentation =
1182 TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1184 // the locally retrieved representation is always preferable
1185 if ( xTmpCVRepresentation.is() )
1187 xCachedVisualRepresentation = xTmpCVRepresentation;
1188 bNeedLocalCache = sal_False;
1192 #endif
1193 else
1195 throw io::IOException(); // TODO
1198 if ( !xTargetStream.is() )
1200 xTargetStream =
1201 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE );
1202 if ( !xTargetStream.is() )
1203 throw io::IOException(); //TODO: access denied
1206 LetCommonStoragePassBeUsed_Impl( xTargetStream );
1208 if ( bStoreVis != bVisReplIsStored )
1210 if ( bStoreVis )
1212 if ( !xCachedVisualRepresentation.is() )
1213 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1215 SAL_WARN_IF( !xCachedVisualRepresentation.is(), "embeddedobj.ole", "No representation is available!" );
1217 // the following copying will be done in case it is SaveAs anyway
1218 // if it is not SaveAs the seekable access is not required currently
1219 // TODO/LATER: may be required in future
1220 if ( bSaveAs )
1222 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY );
1223 if ( !xCachedSeek.is() )
1225 xCachedVisualRepresentation
1226 = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() );
1227 bNeedLocalCache = sal_False;
1231 InsertVisualCache_Impl( xTargetStream, xCachedVisualRepresentation );
1233 else
1235 // the removed representation could be cached by this method
1236 if ( !xCachedVisualRepresentation.is() )
1237 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1239 RemoveVisualCache_Impl( xTargetStream );
1243 if ( bSaveAs )
1245 m_bWaitSaveCompleted = sal_True;
1246 m_xNewObjectStream = xTargetStream;
1247 m_xNewParentStorage = xStorage;
1248 m_aNewEntryName = sEntName;
1249 m_bNewVisReplInStream = bStoreVis;
1250 m_bStoreLoaded = bStoreLoaded;
1252 if ( xCachedVisualRepresentation.is() )
1254 if ( bNeedLocalCache )
1255 m_xNewCachedVisRepl = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() );
1256 else
1257 m_xNewCachedVisRepl = xCachedVisualRepresentation;
1260 // TODO: register listeners for storages above, in case they are disposed
1261 // an exception will be thrown on saveCompleted( true )
1263 else
1265 uno::Reference< lang::XComponent > xComp( xTargetStream, uno::UNO_QUERY );
1266 if ( xComp.is() )
1268 try {
1269 xComp->dispose();
1270 } catch( const uno::Exception& )
1277 //------------------------------------------------------
1278 void SAL_CALL OleEmbeddedObject::setPersistentEntry(
1279 const uno::Reference< embed::XStorage >& xStorage,
1280 const OUString& sEntName,
1281 sal_Int32 nEntryConnectionMode,
1282 const uno::Sequence< beans::PropertyValue >& lArguments,
1283 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1284 throw ( lang::IllegalArgumentException,
1285 embed::WrongStateException,
1286 io::IOException,
1287 uno::Exception,
1288 uno::RuntimeException )
1290 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::setPersistentEntry" );
1292 // begin wrapping related part ====================
1293 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1294 if ( xWrappedObject.is() )
1296 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1297 xWrappedObject->setPersistentEntry( xStorage, sEntName, nEntryConnectionMode, lArguments, lObjArgs );
1298 return;
1300 // end wrapping related part ====================
1302 // TODO: use lObjArgs
1304 // the type of the object must be already set
1305 // a kind of typedetection should be done in the factory;
1306 // the only exception is object initialized from a stream,
1307 // the class ID will be detected from the stream
1309 ::osl::MutexGuard aGuard( m_aMutex );
1310 if ( m_bDisposed )
1311 throw lang::DisposedException(); // TODO
1313 if ( !xStorage.is() )
1314 throw lang::IllegalArgumentException( OUString( "No parent storage is provided!\n" ),
1315 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1316 1 );
1318 if ( sEntName.isEmpty() )
1319 throw lang::IllegalArgumentException( OUString( "Empty element name is provided!\n" ),
1320 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1321 2 );
1323 // May be LOADED should be forbidden here ???
1324 if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1325 && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) )
1327 // if the object is not loaded
1328 // it can not get persistent representation without initialization
1330 // if the object is loaded
1331 // it can switch persistent representation only without initialization
1333 throw embed::WrongStateException(
1334 OUString( "Can't change persistent representation of activated object!\n" ),
1335 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1338 if ( m_bWaitSaveCompleted )
1340 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1341 saveCompleted( ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) );
1342 else
1343 throw embed::WrongStateException(
1344 OUString( "The object waits for saveCompleted() call!\n" ),
1345 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1348 uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
1349 if ( !xNameAccess.is() )
1350 throw uno::RuntimeException(); //TODO
1352 // detect entry existence
1353 sal_Bool bElExists = xNameAccess->hasByName( sEntName );
1355 m_bReadOnly = sal_False;
1356 for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1357 if ( lArguments[nInd].Name == "ReadOnly" )
1358 lArguments[nInd].Value >>= m_bReadOnly;
1360 #ifdef WNT
1361 sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
1362 #endif
1364 SwitchOwnPersistence( xStorage, sEntName );
1366 for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1367 if ( lObjArgs[nInd].Name == "StoreVisualReplacement" )
1368 lObjArgs[nInd].Value >>= m_bStoreVisRepl;
1370 #ifdef WNT
1371 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT )
1373 if ( m_bFromClipboard )
1375 // the object should be initialized from clipboard
1376 // inpossibility to initialize the object means error here
1377 CreateOleComponentFromClipboard_Impl( NULL );
1378 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction
1379 m_pOleComponent->RunObject();
1380 m_nObjectState = embed::EmbedStates::RUNNING;
1382 else if ( bElExists )
1384 // load object from the stream
1385 // after the loading the object can appear as a link
1386 // will be detected by olecomponent
1389 CreateOleComponentAndLoad_Impl( NULL );
1390 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction
1392 catch( const uno::Exception& )
1394 // TODO/LATER: detect classID of the object if possible
1395 // means that the object inprocess server could not be successfully instantiated
1396 GetRidOfComponent();
1399 m_nObjectState = embed::EmbedStates::LOADED;
1401 else
1403 // create a new object
1404 CreateOleComponent_Impl();
1405 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID );
1406 m_pOleComponent->RunObject();
1407 m_nObjectState = embed::EmbedStates::RUNNING;
1410 else
1412 if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE )
1413 throw io::IOException();
1415 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1417 // the document just already changed its stream to store to;
1418 // the links to OLE documents switch their persistence in the same way
1419 // as normal embedded objects
1421 else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT )
1423 // create a new object, that will be stored in specified stream
1424 CreateOleComponent_Impl();
1426 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID );
1427 m_pOleComponent->RunObject();
1428 m_nObjectState = embed::EmbedStates::RUNNING;
1430 else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT )
1432 // use URL ( may be content or stream later ) from MediaDescriptor to initialize object
1433 OUString aURL;
1434 for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1435 if ( lArguments[nInd].Name == "URL" )
1436 lArguments[nInd].Value >>= aURL;
1438 if ( aURL.isEmpty() )
1439 throw lang::IllegalArgumentException(
1440 OUString( "Empty URL is provided in the media descriptor!\n" ),
1441 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1442 4 );
1444 CreateOleComponent_Impl();
1446 // TODO: the m_bIsLink value must be set already
1447 if ( !m_bIsLink )
1448 m_pOleComponent->CreateObjectFromFile( aURL );
1449 else
1450 m_pOleComponent->CreateLinkFromFile( aURL );
1452 m_pOleComponent->RunObject();
1453 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction
1455 m_nObjectState = embed::EmbedStates::RUNNING;
1457 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1459 //TODO:
1461 else
1462 throw lang::IllegalArgumentException( OUString( "Wrong connection mode is provided!\n" ),
1463 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1464 3 );
1466 #else
1467 // On unix the ole object can not do anything except storing itself somewere
1468 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT && bElExists )
1470 // TODO/LATER: detect classID of the object
1471 // can be a real problem for the links
1473 m_nObjectState = embed::EmbedStates::LOADED;
1475 else if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1477 // do nothing, the object has already switched it's persistence
1479 else
1480 throw lang::IllegalArgumentException( OUString( "Wrong connection mode is provided!\n" ),
1481 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1482 3 );
1484 #endif
1487 //------------------------------------------------------
1488 void SAL_CALL OleEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage,
1489 const OUString& sEntName,
1490 const uno::Sequence< beans::PropertyValue >& lArguments,
1491 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1492 throw ( lang::IllegalArgumentException,
1493 embed::WrongStateException,
1494 io::IOException,
1495 uno::Exception,
1496 uno::RuntimeException )
1498 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::storeToEntry" );
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 );
1506 return;
1508 // end wrapping related part ====================
1510 ::osl::MutexGuard aGuard( m_aMutex );
1511 if ( m_bDisposed )
1512 throw lang::DisposedException(); // TODO
1514 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
1516 StoreToLocation_Impl( xStorage, sEntName, lObjArgs, sal_False );
1518 // TODO: should the listener notification be done?
1521 //------------------------------------------------------
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,
1528 io::IOException,
1529 uno::Exception,
1530 uno::RuntimeException )
1532 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::storeAsEntry" );
1534 // begin wrapping related part ====================
1535 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1536 if ( xWrappedObject.is() )
1538 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1539 xWrappedObject->storeAsEntry( xStorage, sEntName, lArguments, lObjArgs );
1540 return;
1542 // end wrapping related part ====================
1544 ::osl::MutexGuard aGuard( m_aMutex );
1545 if ( m_bDisposed )
1546 throw lang::DisposedException(); // TODO
1548 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
1550 StoreToLocation_Impl( xStorage, sEntName, lObjArgs, sal_True );
1552 // TODO: should the listener notification be done here or in saveCompleted?
1555 //------------------------------------------------------
1556 void SAL_CALL OleEmbeddedObject::saveCompleted( sal_Bool bUseNew )
1557 throw ( embed::WrongStateException,
1558 uno::Exception,
1559 uno::RuntimeException )
1561 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::saveCompleted" );
1563 // begin wrapping related part ====================
1564 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1565 if ( xWrappedObject.is() )
1567 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1568 xWrappedObject->saveCompleted( bUseNew );
1569 return;
1571 // end wrapping related part ====================
1573 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1574 if ( m_bDisposed )
1575 throw lang::DisposedException(); // TODO
1577 if ( m_nObjectState == -1 )
1579 // the object is still not loaded
1580 throw embed::WrongStateException( OUString( "Can't store object without persistence!\n" ),
1581 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1584 // it is allowed to call saveCompleted( false ) for nonstored objects
1585 if ( !m_bWaitSaveCompleted && !bUseNew )
1586 return;
1588 SAL_WARN_IF( !m_bWaitSaveCompleted, "embeddedobj.ole", "Unexpected saveCompleted() call!\n" );
1589 if ( !m_bWaitSaveCompleted )
1590 throw io::IOException(); // TODO: illegal call
1592 OSL_ENSURE( m_xNewObjectStream.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" );
1593 if ( !m_xNewObjectStream.is() || !m_xNewParentStorage.is() )
1594 throw uno::RuntimeException(); // TODO: broken internal information
1596 if ( bUseNew )
1598 SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStream, m_aNewEntryName );
1599 m_bStoreVisRepl = m_bNewVisReplInStream;
1600 SetVisReplInStream( m_bNewVisReplInStream );
1601 m_xCachedVisualRepresentation = m_xNewCachedVisRepl;
1603 else
1605 // close remembered stream
1606 try {
1607 uno::Reference< lang::XComponent > xComponent( m_xNewObjectStream, uno::UNO_QUERY );
1608 SAL_WARN_IF( !xComponent.is(), "embeddedobj.ole", "Wrong storage implementation!" );
1609 if ( xComponent.is() )
1610 xComponent->dispose();
1612 catch ( const uno::Exception& )
1617 sal_Bool bStoreLoaded = m_bStoreLoaded;
1619 m_xNewObjectStream = uno::Reference< io::XStream >();
1620 m_xNewParentStorage = uno::Reference< embed::XStorage >();
1621 m_aNewEntryName = OUString();
1622 m_bWaitSaveCompleted = sal_False;
1623 m_bNewVisReplInStream = sal_False;
1624 m_xNewCachedVisRepl = uno::Reference< io::XStream >();
1625 m_bStoreLoaded = sal_False;
1627 if ( bUseNew && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded
1628 && m_nObjectState != embed::EmbedStates::LOADED )
1630 // the object replacement image should be updated, so the cached size as well
1631 m_bHasCachedSize = sal_False;
1634 // the call will cache the size in case of success
1635 // probably it might need to be done earlier, while the object is in active state
1636 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1638 catch( const uno::Exception& )
1642 aGuard.clear();
1643 if ( bUseNew )
1645 MakeEventListenerNotification_Impl( OUString( "OnSaveAsDone" ));
1647 // the object can be changed only on windows
1648 // the notification should be done only if the object is not in loaded state
1649 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1651 MakeEventListenerNotification_Impl( OUString( "OnVisAreaChanged" ));
1656 //------------------------------------------------------
1657 sal_Bool SAL_CALL OleEmbeddedObject::hasEntry()
1658 throw ( embed::WrongStateException,
1659 uno::RuntimeException )
1661 // begin wrapping related part ====================
1662 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1663 if ( xWrappedObject.is() )
1665 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1666 return xWrappedObject->hasEntry();
1668 // end wrapping related part ====================
1670 ::osl::MutexGuard aGuard( m_aMutex );
1671 if ( m_bDisposed )
1672 throw lang::DisposedException(); // TODO
1674 if ( m_bWaitSaveCompleted )
1675 throw embed::WrongStateException(
1676 OUString( "The object waits for saveCompleted() call!\n" ),
1677 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1679 if ( m_xObjectStream.is() )
1680 return sal_True;
1682 return sal_False;
1685 //------------------------------------------------------
1686 OUString SAL_CALL OleEmbeddedObject::getEntryName()
1687 throw ( embed::WrongStateException,
1688 uno::RuntimeException )
1690 // begin wrapping related part ====================
1691 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1692 if ( xWrappedObject.is() )
1694 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1695 return xWrappedObject->getEntryName();
1697 // end wrapping related part ====================
1699 ::osl::MutexGuard aGuard( m_aMutex );
1700 if ( m_bDisposed )
1701 throw lang::DisposedException(); // TODO
1703 if ( m_nObjectState == -1 )
1705 // the object is still not loaded
1706 throw embed::WrongStateException( OUString( "The object persistence is not initialized!\n" ),
1707 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1710 if ( m_bWaitSaveCompleted )
1711 throw embed::WrongStateException(
1712 OUString( "The object waits for saveCompleted() call!\n" ),
1713 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1715 return m_aEntryName;
1719 //------------------------------------------------------
1720 void SAL_CALL OleEmbeddedObject::storeOwn()
1721 throw ( embed::WrongStateException,
1722 io::IOException,
1723 uno::Exception,
1724 uno::RuntimeException )
1726 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::storeOwn" );
1728 // begin wrapping related part ====================
1729 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1730 if ( xWrappedObject.is() )
1732 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1733 xWrappedObject->storeOwn();
1734 return;
1736 // end wrapping related part ====================
1738 // during switching from Activated to Running and from Running to Loaded states the object will
1739 // ask container to store the object, the container has to make decision
1740 // to do so or not
1742 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1743 if ( m_bDisposed )
1744 throw lang::DisposedException(); // TODO
1746 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
1748 if ( m_nObjectState == -1 )
1750 // the object is still not loaded
1751 throw embed::WrongStateException( OUString( "Can't store object without persistence!\n" ),
1752 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1755 if ( m_bWaitSaveCompleted )
1756 throw embed::WrongStateException(
1757 OUString( "The object waits for saveCompleted() call!\n" ),
1758 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1760 if ( m_bReadOnly )
1761 throw io::IOException(); // TODO: access denied
1763 LetCommonStoragePassBeUsed_Impl( m_xObjectStream );
1765 sal_Bool bStoreLoaded = sal_True;
1767 #ifdef WNT
1768 if ( m_nObjectState != embed::EmbedStates::LOADED && m_pOleComponent && m_pOleComponent->IsDirty() )
1770 bStoreLoaded = sal_False;
1772 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" );
1774 if ( !m_xObjectStream.is() )
1775 throw io::IOException(); //TODO: access denied
1777 SetStreamMediaType_Impl( m_xObjectStream, OUString( "application/vnd.sun.star.oleobject" ));
1778 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream();
1779 if ( !xOutStream.is() )
1780 throw io::IOException(); //TODO: access denied
1782 // TODO: does this work for links too?
1783 StoreObjectToStream( GetStreamForSaving() );
1785 // the replacement is changed probably, and it must be in the object stream
1786 if ( !m_pOleComponent->IsWorkaroundActive() )
1787 m_xCachedVisualRepresentation = uno::Reference< io::XStream >();
1788 SetVisReplInStream( sal_True );
1790 #endif
1792 if ( m_bStoreVisRepl != HasVisReplInStream() )
1794 if ( m_bStoreVisRepl )
1796 // the m_xCachedVisualRepresentation must be set or it should be already stored
1797 if ( m_xCachedVisualRepresentation.is() )
1798 InsertVisualCache_Impl( m_xObjectStream, m_xCachedVisualRepresentation );
1799 else
1801 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream );
1802 SAL_WARN_IF( !m_xCachedVisualRepresentation.is(), "embeddedobj.ole", "No representation is available!" );
1805 else
1807 if ( !m_xCachedVisualRepresentation.is() )
1808 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream );
1809 RemoveVisualCache_Impl( m_xObjectStream );
1812 SetVisReplInStream( m_bStoreVisRepl );
1815 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1817 // the object replacement image should be updated, so the cached size as well
1818 m_bHasCachedSize = sal_False;
1821 // the call will cache the size in case of success
1822 // probably it might need to be done earlier, while the object is in active state
1823 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1825 catch( const uno::Exception& )
1829 aGuard.clear();
1831 MakeEventListenerNotification_Impl( OUString( "OnSaveDone" ));
1833 // the object can be changed only on Windows
1834 // the notification should be done only if the object is not in loaded state
1835 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1836 MakeEventListenerNotification_Impl( OUString( "OnVisAreaChanged" ));
1839 //------------------------------------------------------
1840 sal_Bool SAL_CALL OleEmbeddedObject::isReadonly()
1841 throw ( embed::WrongStateException,
1842 uno::RuntimeException )
1844 // begin wrapping related part ====================
1845 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1846 if ( xWrappedObject.is() )
1848 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1849 return xWrappedObject->isReadonly();
1851 // end wrapping related part ====================
1853 ::osl::MutexGuard aGuard( m_aMutex );
1854 if ( m_bDisposed )
1855 throw lang::DisposedException(); // TODO
1857 if ( m_nObjectState == -1 )
1859 // the object is still not loaded
1860 throw embed::WrongStateException( OUString( "The object persistence is not initialized!\n" ),
1861 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1864 if ( m_bWaitSaveCompleted )
1865 throw embed::WrongStateException(
1866 OUString( "The object waits for saveCompleted() call!\n" ),
1867 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1869 return m_bReadOnly;
1872 //------------------------------------------------------
1873 void SAL_CALL OleEmbeddedObject::reload(
1874 const uno::Sequence< beans::PropertyValue >& lArguments,
1875 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1876 throw ( lang::IllegalArgumentException,
1877 embed::WrongStateException,
1878 io::IOException,
1879 uno::Exception,
1880 uno::RuntimeException )
1882 // begin wrapping related part ====================
1883 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1884 if ( xWrappedObject.is() )
1886 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1887 xWrappedObject->reload( lArguments, lObjArgs );
1888 return;
1890 // end wrapping related part ====================
1892 // TODO: use lObjArgs
1894 ::osl::MutexGuard aGuard( m_aMutex );
1895 if ( m_bDisposed )
1896 throw lang::DisposedException(); // TODO
1898 if ( m_nObjectState == -1 )
1900 // the object is still not loaded
1901 throw embed::WrongStateException( OUString( "The object persistence is not initialized!\n" ),
1902 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1905 if ( m_bWaitSaveCompleted )
1906 throw embed::WrongStateException(
1907 OUString( "The object waits for saveCompleted() call!\n" ),
1908 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1910 // TODO:
1911 // throw away current document
1912 // load new document from current storage
1913 // use meaningfull part of lArguments
1916 //------------------------------------------------------
1917 void SAL_CALL OleEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage,
1918 const OUString& sEntName )
1919 throw ( lang::IllegalArgumentException,
1920 embed::WrongStateException,
1921 io::IOException,
1922 uno::Exception,
1923 uno::RuntimeException )
1925 // begin wrapping related part ====================
1926 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1927 if ( xWrappedObject.is() )
1929 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1930 xWrappedObject->breakLink( xStorage, sEntName );
1931 return;
1933 // end wrapping related part ====================
1935 ::osl::MutexGuard aGuard( m_aMutex );
1936 if ( m_bDisposed )
1937 throw lang::DisposedException(); // TODO
1939 if ( !xStorage.is() )
1940 throw lang::IllegalArgumentException( OUString( "No parent storage is provided!\n" ),
1941 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1942 1 );
1944 if ( sEntName.isEmpty() )
1945 throw lang::IllegalArgumentException( OUString( "Empty element name is provided!\n" ),
1946 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1947 2 );
1949 // TODO: The object must be at least in Running state;
1950 if ( !m_bIsLink || m_nObjectState == -1 || !m_pOleComponent )
1952 // it must be a linked initialized object
1953 throw embed::WrongStateException(
1954 OUString( "The object is not a valid linked object!\n" ),
1955 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1958 if ( m_bReadOnly )
1959 throw io::IOException(); // TODO: Access denied
1961 if ( m_bWaitSaveCompleted )
1962 throw embed::WrongStateException(
1963 OUString( "The object waits for saveCompleted() call!\n" ),
1964 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1967 #ifdef WNT
1968 if ( m_pOleComponent )
1970 // TODO: create an object based on the link
1972 // disconnect the old temporary URL
1973 OUString aOldTempURL = m_aTempURL;
1974 m_aTempURL = OUString();
1976 OleComponent* pNewOleComponent = new OleComponent( m_xFactory, this );
1977 try {
1978 pNewOleComponent->InitEmbeddedCopyOfLink( m_pOleComponent );
1980 catch ( const uno::Exception& )
1982 delete pNewOleComponent;
1983 if ( !m_aTempURL.isEmpty() )
1984 KillFile_Impl( m_aTempURL, m_xFactory );
1985 m_aTempURL = aOldTempURL;
1986 throw;
1989 try {
1990 GetRidOfComponent();
1992 catch( const uno::Exception& )
1994 delete pNewOleComponent;
1995 if ( !m_aTempURL.isEmpty() )
1996 KillFile_Impl( m_aTempURL, m_xFactory );
1997 m_aTempURL = aOldTempURL;
1998 throw;
2001 KillFile_Impl( aOldTempURL, m_xFactory );
2003 CreateOleComponent_Impl( pNewOleComponent );
2005 if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) )
2006 SwitchOwnPersistence( xStorage, sEntName );
2008 if ( m_nObjectState != embed::EmbedStates::LOADED )
2010 // TODO: should we activate the new object if the link was activated?
2012 sal_Int32 nTargetState = m_nObjectState;
2013 m_nObjectState = embed::EmbedStates::LOADED;
2015 if ( m_nObjectState == embed::EmbedStates::RUNNING )
2016 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed
2017 else // m_nObjectState == embed::EmbedStates::ACTIVE
2019 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed
2020 m_pOleComponent->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN );
2023 m_nObjectState = nTargetState;
2026 m_bIsLink = sal_False;
2027 m_aLinkURL = OUString();
2029 else
2030 #endif
2032 throw io::IOException(); //TODO:
2036 //------------------------------------------------------
2037 sal_Bool SAL_CALL OleEmbeddedObject::isLink()
2038 throw ( embed::WrongStateException,
2039 uno::RuntimeException )
2041 // begin wrapping related part ====================
2042 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
2043 if ( xWrappedObject.is() )
2045 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
2046 return xWrappedObject->isLink();
2048 // end wrapping related part ====================
2050 ::osl::MutexGuard aGuard( m_aMutex );
2051 if ( m_bDisposed )
2052 throw lang::DisposedException(); // TODO
2054 return m_bIsLink;
2057 //------------------------------------------------------
2058 OUString SAL_CALL OleEmbeddedObject::getLinkURL()
2059 throw ( embed::WrongStateException,
2060 uno::Exception,
2061 uno::RuntimeException )
2063 // begin wrapping related part ====================
2064 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
2065 if ( xWrappedObject.is() )
2067 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
2068 return xWrappedObject->getLinkURL();
2070 // end wrapping related part ====================
2072 ::osl::MutexGuard aGuard( m_aMutex );
2073 if ( m_bDisposed )
2074 throw lang::DisposedException(); // TODO
2076 if ( m_bWaitSaveCompleted )
2077 throw embed::WrongStateException(
2078 OUString( "The object waits for saveCompleted() call!\n" ),
2079 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
2081 if ( !m_bIsLink )
2082 throw embed::WrongStateException(
2083 OUString( "The object is not a link object!\n" ),
2084 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
2086 // TODO: probably the link URL can be retrieved from OLE
2088 return m_aLinkURL;
2091 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */