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 <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/ElementModes.hpp>
26 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
27 #include <com/sun/star/embed/Aspects.hpp>
28 #include <com/sun/star/embed/NeedsRunningStateException.hpp>
29 #include <com/sun/star/embed/StateChangeInProgressException.hpp>
30 #include <com/sun/star/embed/EmbedMisc.hpp>
31 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
32 #include <com/sun/star/io/TempFile.hpp>
33 #include <com/sun/star/io/XSeekable.hpp>
34 #include <com/sun/star/lang/DisposedException.hpp>
35 #include <com/sun/star/beans/NamedValue.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/frame/XLoadable.hpp>
38 #include <com/sun/star/document/XStorageBasedDocument.hpp>
39 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
40 #include <com/sun/star/container/XNameAccess.hpp>
41 #include <com/sun/star/container/XNameContainer.hpp>
42 #include <com/sun/star/system/SystemShellExecute.hpp>
43 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
45 #include <cppuhelper/interfacecontainer.h>
46 #include <comphelper/processfactory.hxx>
47 #include <comphelper/mimeconfighelper.hxx>
48 #include <comphelper/storagehelper.hxx>
51 #include <targetstatecontrol.hxx>
53 #include "ownview.hxx"
56 #include <olecomponent.hxx>
59 using namespace ::com::sun::star
;
63 void OleEmbeddedObject::SwitchComponentToRunningState_Impl()
65 if ( m_pOleComponent
)
69 m_pOleComponent
->RunObject();
71 catch( const embed::UnreachableStateException
& )
76 catch( const embed::WrongStateException
& )
84 throw embed::UnreachableStateException();
89 uno::Sequence
< sal_Int32
> OleEmbeddedObject::GetReachableStatesList_Impl(
90 const uno::Sequence
< embed::VerbDescriptor
>& aVerbList
)
92 uno::Sequence
< sal_Int32
> aStates(2);
93 aStates
[0] = embed::EmbedStates::LOADED
;
94 aStates
[1] = embed::EmbedStates::RUNNING
;
95 for ( sal_Int32 nInd
= 0; nInd
< aVerbList
.getLength(); nInd
++ )
96 if ( aVerbList
[nInd
].VerbID
== embed::EmbedVerbs::MS_OLEVERB_OPEN
)
99 aStates
[2] = embed::EmbedStates::ACTIVE
;
106 uno::Sequence
< sal_Int32
> OleEmbeddedObject::GetIntermediateVerbsSequence_Impl( sal_Int32 nNewState
)
108 SAL_WARN_IF( m_nObjectState
== embed::EmbedStates::LOADED
, "embeddedobj.ole", "Loaded object is switched to running state without verbs using!" );
110 // actually there will be only one verb
111 if ( m_nObjectState
== embed::EmbedStates::RUNNING
&& nNewState
== embed::EmbedStates::ACTIVE
)
113 uno::Sequence
< sal_Int32
> aVerbs( 1 );
114 aVerbs
[0] = embed::EmbedVerbs::MS_OLEVERB_OPEN
;
117 return uno::Sequence
< sal_Int32
>();
121 void OleEmbeddedObject::MoveListeners()
123 if ( m_pInterfaceContainer
)
125 // move state change listeners
127 ::cppu::OInterfaceContainerHelper
* pStateChangeContainer
=
128 m_pInterfaceContainer
->getContainer( cppu::UnoType
<embed::XStateChangeListener
>::get());
129 if ( pStateChangeContainer
!= nullptr )
131 uno::Reference
< embed::XStateChangeBroadcaster
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
132 if ( xWrappedObject
.is() )
134 ::cppu::OInterfaceIteratorHelper
pIterator( *pStateChangeContainer
);
135 while ( pIterator
.hasMoreElements() )
139 xWrappedObject
->addStateChangeListener( static_cast<embed::XStateChangeListener
*>(pIterator
.next()) );
141 catch( const uno::RuntimeException
& )
150 // move event listeners
152 ::cppu::OInterfaceContainerHelper
* pEventContainer
=
153 m_pInterfaceContainer
->getContainer( cppu::UnoType
<document::XEventListener
>::get());
154 if ( pEventContainer
!= nullptr )
156 uno::Reference
< document::XEventBroadcaster
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
157 if ( xWrappedObject
.is() )
159 ::cppu::OInterfaceIteratorHelper
pIterator( *pEventContainer
);
160 while ( pIterator
.hasMoreElements() )
164 xWrappedObject
->addEventListener( static_cast<document::XEventListener
*>(pIterator
.next()) );
166 catch( const uno::RuntimeException
& )
175 // move close listeners
177 ::cppu::OInterfaceContainerHelper
* pCloseContainer
=
178 m_pInterfaceContainer
->getContainer( cppu::UnoType
<util::XCloseListener
>::get());
179 if ( pCloseContainer
!= nullptr )
181 uno::Reference
< util::XCloseBroadcaster
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
182 if ( xWrappedObject
.is() )
184 ::cppu::OInterfaceIteratorHelper
pIterator( *pCloseContainer
);
185 while ( pIterator
.hasMoreElements() )
189 xWrappedObject
->addCloseListener( static_cast<util::XCloseListener
*>(pIterator
.next()) );
191 catch( const uno::RuntimeException
& )
200 delete m_pInterfaceContainer
;
201 m_pInterfaceContainer
= nullptr;
206 uno::Reference
< embed::XStorage
> OleEmbeddedObject::CreateTemporarySubstorage( OUString
& o_aStorageName
)
208 uno::Reference
< embed::XStorage
> xResult
;
210 for ( sal_Int32 nInd
= 0; nInd
< 32000 && !xResult
.is(); nInd
++ )
212 OUString aName
= OUString::number( nInd
) + "TMPSTOR" + m_aEntryName
;
213 if ( !m_xParentStorage
->hasByName( aName
) )
215 xResult
= m_xParentStorage
->openStorageElement( aName
, embed::ElementModes::READWRITE
);
216 o_aStorageName
= aName
;
222 o_aStorageName
.clear();
223 throw uno::RuntimeException();
230 OUString
OleEmbeddedObject::MoveToTemporarySubstream()
233 for ( sal_Int32 nInd
= 0; nInd
< 32000 && aResult
.isEmpty(); nInd
++ )
235 OUString aName
= OUString::number( nInd
) + "TMPSTREAM" + m_aEntryName
;
236 if ( !m_xParentStorage
->hasByName( aName
) )
238 m_xParentStorage
->renameElement( m_aEntryName
, aName
);
243 if ( aResult
.isEmpty() )
244 throw uno::RuntimeException();
250 bool OleEmbeddedObject::TryToConvertToOOo( const uno::Reference
< io::XStream
>& xStream
)
252 bool bResult
= false;
254 OUString aStorageName
;
255 OUString aTmpStreamName
;
258 if ( m_pOleComponent
|| m_bReadOnly
)
263 changeState( embed::EmbedStates::LOADED
);
265 // the stream must be seekable
266 uno::Reference
< io::XSeekable
> xSeekable( xStream
, uno::UNO_QUERY_THROW
);
267 xSeekable
->seek( 0 );
268 m_aFilterName
= OwnView_Impl::GetFilterNameFromExtentionAndInStream( m_xFactory
, OUString(), xStream
->getInputStream() );
270 if ( !m_aFilterName
.isEmpty()
271 && ( m_aFilterName
== "Calc MS Excel 2007 XML" || m_aFilterName
== "Impress MS PowerPoint 2007 XML" || m_aFilterName
== "MS Word 2007 XML"
272 || m_aFilterName
== "MS Excel 97 Vorlage/Template" || m_aFilterName
== "MS Word 97 Vorlage" ) )
274 uno::Reference
< container::XNameAccess
> xFilterFactory(
275 m_xFactory
->createInstance("com.sun.star.document.FilterFactory"),
276 uno::UNO_QUERY_THROW
);
278 OUString aDocServiceName
;
279 uno::Any aFilterAnyData
= xFilterFactory
->getByName( m_aFilterName
);
280 uno::Sequence
< beans::PropertyValue
> aFilterData
;
281 if ( aFilterAnyData
>>= aFilterData
)
283 for ( sal_Int32 nInd
= 0; nInd
< aFilterData
.getLength(); nInd
++ )
284 if ( aFilterData
[nInd
].Name
== "DocumentService" )
285 aFilterData
[nInd
].Value
>>= aDocServiceName
;
288 if ( !aDocServiceName
.isEmpty() )
291 uno::Sequence
< uno::Any
> aArguments(1);
292 aArguments
[0] <<= beans::NamedValue( OUString( "EmbeddedObject" ), uno::makeAny( true ));
294 uno::Reference
< util::XCloseable
> xDocument( m_xFactory
->createInstanceWithArguments( aDocServiceName
, aArguments
), uno::UNO_QUERY_THROW
);
295 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY_THROW
);
296 uno::Reference
< document::XStorageBasedDocument
> xStorDoc( xDocument
, uno::UNO_QUERY_THROW
);
298 // let the model behave as embedded one
299 uno::Reference
< frame::XModel
> xModel( xDocument
, uno::UNO_QUERY_THROW
);
300 uno::Sequence
< beans::PropertyValue
> aSeq( 1 );
301 aSeq
[0].Name
= "SetEmbedded";
302 aSeq
[0].Value
<<= true;
303 xModel
->attachResource( OUString(), aSeq
);
305 // load the model from the stream
306 uno::Sequence
< beans::PropertyValue
> aArgs( 5 );
307 aArgs
[0].Name
= "HierarchicalDocumentName";
308 aArgs
[0].Value
<<= m_aEntryName
;
309 aArgs
[1].Name
= "ReadOnly";
310 aArgs
[1].Value
<<= true;
311 aArgs
[2].Name
= "FilterName";
312 aArgs
[2].Value
<<= m_aFilterName
;
313 aArgs
[3].Name
= "URL";
314 aArgs
[3].Value
<<= OUString( "private:stream" );
315 aArgs
[4].Name
= "InputStream";
316 aArgs
[4].Value
<<= xStream
->getInputStream();
318 xSeekable
->seek( 0 );
319 xLoadable
->load( aArgs
);
321 // the model is successfully loaded, create a new storage and store the model to the storage
322 uno::Reference
< embed::XStorage
> xTmpStorage
= CreateTemporarySubstorage( aStorageName
);
323 xStorDoc
->storeToStorage( xTmpStorage
, uno::Sequence
< beans::PropertyValue
>() );
324 xDocument
->close( true );
325 uno::Reference
< beans::XPropertySet
> xStorProps( xTmpStorage
, uno::UNO_QUERY_THROW
);
327 xStorProps
->getPropertyValue("MediaType") >>= aMediaType
;
328 xTmpStorage
->dispose();
330 // look for the related embedded object factory
331 ::comphelper::MimeConfigurationHelper
aConfigHelper( comphelper::getComponentContext(m_xFactory
) );
332 OUString aEmbedFactory
;
333 if ( !aMediaType
.isEmpty() )
334 aEmbedFactory
= aConfigHelper
.GetFactoryNameByMediaType( aMediaType
);
336 if ( aEmbedFactory
.isEmpty() )
337 throw uno::RuntimeException();
339 uno::Reference
< uno::XInterface
> xFact
= m_xFactory
->createInstance( aEmbedFactory
);
341 uno::Reference
< embed::XEmbedObjectCreator
> xEmbCreator( xFact
, uno::UNO_QUERY_THROW
);
343 // now the object should be adjusted to become the wrapper
345 uno::Reference
< lang::XComponent
> xComp( m_xObjectStream
, uno::UNO_QUERY_THROW
);
347 m_xObjectStream
.clear();
351 aTmpStreamName
= MoveToTemporarySubstream();
354 m_xParentStorage
->renameElement( aStorageName
, m_aEntryName
);
357 m_xWrappedObject
.set( xEmbCreator
->createInstanceInitFromEntry( m_xParentStorage
, m_aEntryName
, uno::Sequence
< beans::PropertyValue
>(), uno::Sequence
< beans::PropertyValue
>() ), uno::UNO_QUERY_THROW
);
359 // remember parent document name to show in the title bar
360 m_xWrappedObject
->setContainerName( m_aContainerName
);
362 bResult
= true; // the change is no more revertable
365 m_xParentStorage
->removeElement( aTmpStreamName
);
367 catch( const uno::Exception
& )
369 // the success of the removing is not so important
374 catch( const uno::Exception
& )
376 // repair the object if necessary
381 if ( !aTmpStreamName
.isEmpty() && aTmpStreamName
!= m_aEntryName
)
384 if ( m_xParentStorage
->hasByName( m_aEntryName
) )
385 m_xParentStorage
->removeElement( m_aEntryName
);
386 m_xParentStorage
->renameElement( aTmpStreamName
, m_aEntryName
);
388 catch ( const uno::Exception
& )
392 } catch( const uno::Exception
& ) {}
394 m_xParentStorage
->dispose(); // ??? the storage has information loss, it should be closed without committing!
395 throw uno::RuntimeException(); // the repairing is not possible
401 m_xObjectStream
= m_xParentStorage
->openStreamElement( m_aEntryName
, m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
);
402 m_nObjectState
= embed::EmbedStates::LOADED
;
404 catch( const uno::Exception
& )
408 } catch( const uno::Exception
& ) {}
410 throw uno::RuntimeException(); // the repairing is not possible
416 if ( !aStorageName
.isEmpty() )
418 m_xParentStorage
->removeElement( aStorageName
);
419 } catch( const uno::Exception
& ) { SAL_WARN( "embeddedobj.ole", "Can not remove temporary storage!" ); }
426 // the conversion was done successfully, now the additional initializations should happen
429 m_xWrappedObject
->setClientSite( m_xClientSite
);
430 if ( m_xParent
.is() )
432 uno::Reference
< container::XChild
> xChild( m_xWrappedObject
, uno::UNO_QUERY
);
434 xChild
->setParent( m_xParent
);
443 void SAL_CALL
OleEmbeddedObject::changeState( sal_Int32 nNewState
)
444 throw ( embed::UnreachableStateException
,
445 embed::WrongStateException
,
447 uno::RuntimeException
, std::exception
)
449 // begin wrapping related part ====================
450 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
451 if ( xWrappedObject
.is() )
453 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
454 xWrappedObject
->changeState( nNewState
);
457 // end wrapping related part ====================
459 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
462 throw lang::DisposedException(); // TODO
464 if ( m_nObjectState
== -1 )
465 throw embed::WrongStateException( "The object has no persistence!",
466 static_cast< ::cppu::OWeakObject
* >(this) );
468 // in case the object is already in requested state
469 if ( m_nObjectState
== nNewState
)
473 if ( m_pOleComponent
)
475 if ( m_nTargetState
!= -1 )
477 // means that the object is currently trying to reach the target state
478 throw embed::StateChangeInProgressException( OUString(),
479 uno::Reference
< uno::XInterface
>(),
483 TargetStateControl_Impl
aControl( m_nTargetState
, nNewState
);
485 // TODO: additional verbs can be a problem, since nobody knows how the object
486 // will behave after activation
488 sal_Int32 nOldState
= m_nObjectState
;
490 StateChangeNotification_Impl( true, nOldState
, nNewState
);
495 if ( nNewState
== embed::EmbedStates::LOADED
)
497 // This means just closing of the current object
498 // If component can not be closed the object stays in loaded state
499 // and it holds reference to "incomplete" component
500 // If the object is switched to running state later
501 // the component will become "complete"
503 // the loaded state must be set before, because of notifications!
504 m_nObjectState
= nNewState
;
507 VerbExecutionControllerGuard
aVerbGuard( m_aVerbExecutionController
);
508 m_pOleComponent
->CloseObject();
512 StateChangeNotification_Impl( false, nOldState
, m_nObjectState
);
515 else if ( nNewState
== embed::EmbedStates::RUNNING
|| nNewState
== embed::EmbedStates::ACTIVE
)
517 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
519 // if the target object is in loaded state and a different state is specified
520 // as a new one the object first must be switched to running state.
522 // the component can exist already in nonrunning state
523 // it can be created during loading to detect type of object
524 CreateOleComponentAndLoad_Impl( m_pOleComponent
);
526 SwitchComponentToRunningState_Impl();
527 m_nObjectState
= embed::EmbedStates::RUNNING
;
529 StateChangeNotification_Impl( false, nOldState
, m_nObjectState
);
532 if ( m_pOleComponent
&& m_bHasSizeToSet
)
536 m_pOleComponent
->SetExtent( m_aSizeToSet
, m_nAspectToSet
);
537 m_bHasSizeToSet
= false;
539 catch( const uno::Exception
& ) {}
543 if ( m_nObjectState
== nNewState
)
547 // so now the object is either switched from Active to Running state or vise versa
548 // the notification about object state change will be done asynchronously
549 if ( m_nObjectState
== embed::EmbedStates::RUNNING
&& nNewState
== embed::EmbedStates::ACTIVE
)
551 // execute OPEN verb, if object does not reach active state it is an object's problem
553 m_pOleComponent
->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN
);
556 // some objects do not allow to set the size even in running state
557 if ( m_pOleComponent
&& m_bHasSizeToSet
)
561 m_pOleComponent
->SetExtent( m_aSizeToSet
, m_nAspectToSet
);
562 m_bHasSizeToSet
= false;
564 catch( uno::Exception
& ) {}
568 m_nObjectState
= nNewState
;
570 else if ( m_nObjectState
== embed::EmbedStates::ACTIVE
&& nNewState
== embed::EmbedStates::RUNNING
)
573 m_pOleComponent
->CloseObject();
574 m_pOleComponent
->RunObject(); // Should not fail, the object already was active
576 m_nObjectState
= nNewState
;
580 throw embed::UnreachableStateException();
584 throw embed::UnreachableStateException();
586 catch( uno::Exception
& )
589 StateChangeNotification_Impl( false, nOldState
, m_nObjectState
);
596 throw embed::UnreachableStateException();
601 uno::Sequence
< sal_Int32
> SAL_CALL
OleEmbeddedObject::getReachableStates()
602 throw ( embed::WrongStateException
,
603 uno::RuntimeException
, std::exception
)
605 // begin wrapping related part ====================
606 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
607 if ( xWrappedObject
.is() )
609 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
610 return xWrappedObject
->getReachableStates();
612 // end wrapping related part ====================
614 ::osl::MutexGuard
aGuard( m_aMutex
);
616 throw lang::DisposedException(); // TODO
618 if ( m_nObjectState
== -1 )
619 throw embed::WrongStateException( "The object has no persistence!",
620 static_cast< ::cppu::OWeakObject
* >(this) );
623 if ( m_pOleComponent
)
625 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
627 // the list of supported verbs can be retrieved only when object is in running state
628 throw embed::NeedsRunningStateException(); // TODO:
631 // the list of states can only be guessed based on standard verbs,
632 // since there is no way to detect what additional verbs do
633 return GetReachableStatesList_Impl( m_pOleComponent
->GetVerbList() );
638 return uno::Sequence
< sal_Int32
>();
643 sal_Int32 SAL_CALL
OleEmbeddedObject::getCurrentState()
644 throw ( embed::WrongStateException
,
645 uno::RuntimeException
, std::exception
)
647 // begin wrapping related part ====================
648 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
649 if ( xWrappedObject
.is() )
651 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
652 return xWrappedObject
->getCurrentState();
654 // end wrapping related part ====================
656 ::osl::MutexGuard
aGuard( m_aMutex
);
658 throw lang::DisposedException(); // TODO
660 if ( m_nObjectState
== -1 )
661 throw embed::WrongStateException( "The object has no persistence!",
662 static_cast< ::cppu::OWeakObject
* >(this) );
664 // TODO: Shouldn't we ask object? ( I guess no )
665 return m_nObjectState
;
670 bool lcl_CopyStream(const uno::Reference
<io::XInputStream
>& xIn
, const uno::Reference
<io::XOutputStream
>& xOut
, sal_Int32 nMaxCopy
= SAL_MAX_INT32
)
675 const sal_Int32 nChunkSize
= 4096;
676 uno::Sequence
< sal_Int8
> aData(nChunkSize
);
677 sal_Int32 nTotalRead
= 0;
681 if (nTotalRead
+ aData
.getLength() > nMaxCopy
)
683 aData
.realloc(nMaxCopy
- nTotalRead
);
685 nRead
= xIn
->readBytes(aData
, aData
.getLength());
687 xOut
->writeBytes(aData
);
688 } while (nRead
== nChunkSize
&& nTotalRead
<= nMaxCopy
);
689 return nTotalRead
!= 0;
692 uno::Reference
< io::XStream
> lcl_GetExtractedStream( OUString
& rUrl
,
693 const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xFactory
,
694 const css::uno::Reference
< css::io::XStream
>& xObjectStream
)
696 uno::Reference
<beans::XPropertySet
> xNativeTempFile(
697 io::TempFile::create(comphelper::getComponentContext(xFactory
)),
698 uno::UNO_QUERY_THROW
);
699 uno::Reference
< io::XStream
> xStream(xNativeTempFile
, uno::UNO_QUERY_THROW
);
701 uno::Sequence
< uno::Any
> aArgs( 2 );
702 aArgs
[0] <<= xObjectStream
;
703 aArgs
[1] <<= true; // do not create copy
704 uno::Reference
< container::XNameContainer
> xNameContainer(
705 xFactory
->createInstanceWithArguments(
706 "com.sun.star.embed.OLESimpleStorage",
707 aArgs
), uno::UNO_QUERY_THROW
);
709 //various stream names that can contain the real document contents for
710 //this object in a straightforward direct way
711 static const OUStringLiteral aStreamNames
[] =
713 OUStringLiteral("CONTENTS"),
714 OUStringLiteral("Package"),
715 OUStringLiteral("EmbeddedOdf"),
716 OUStringLiteral("WordDocument"),
717 OUStringLiteral("Workbook"),
718 OUStringLiteral("PowerPoint Document")
721 bool bCopied
= false;
722 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aStreamNames
) && !bCopied
; ++i
)
724 uno::Reference
<io::XStream
> xEmbeddedFile
;
727 xNameContainer
->getByName(aStreamNames
[i
]) >>= xEmbeddedFile
;
729 catch (const container::NoSuchElementException
&)
733 bCopied
= xEmbeddedFile
.is() && lcl_CopyStream(xEmbeddedFile
->getInputStream(), xStream
->getOutputStream());
738 uno::Reference
< io::XStream
> xOle10Native
;
741 xNameContainer
->getByName("\1Ole10Native") >>= xOle10Native
;
743 catch (container::NoSuchElementException
const&)
747 if (xOle10Native
.is())
749 const uno::Reference
<io::XInputStream
> xIn
= xOle10Native
->getInputStream();
750 xIn
->skipBytes(4); //size of the entire stream minus 4 bytes
751 xIn
->skipBytes(2); //word that represent the directory type
752 uno::Sequence
< sal_Int8
> aData(1);
756 nRead
= xIn
->readBytes(aData
, 1);
757 } while (nRead
== 1 && aData
[0] != 0); // file name plus extension of the attachment null terminated
760 nRead
= xIn
->readBytes(aData
, 1);
761 } while (nRead
== 1 && aData
[0] != 0); // Fully Qualified File name with extension
762 xIn
->skipBytes(1); //single byte
763 xIn
->skipBytes(1); //single byte
764 xIn
->skipBytes(2); //Word that represent the directory type
765 xIn
->skipBytes(4); //len of string
768 nRead
= xIn
->readBytes(aData
, 1);
769 } while (nRead
== 1 && aData
[0] != 0); // Actual string representing the file path
770 uno::Sequence
< sal_Int8
> aLenData(4);
771 xIn
->readBytes(aLenData
, 4); //len of attachment
772 sal_uInt32 nLen
= static_cast<sal_uInt32
>(
773 (aLenData
[0] & 0xFF) |
774 ((aLenData
[1] & 0xFF) << 8) |
775 ((aLenData
[2] & 0xFF) << 16) |
776 ((aLenData
[3] & 0xFF) << 24));
778 bCopied
= lcl_CopyStream(xIn
, xStream
->getOutputStream(), nLen
);
782 uno::Reference
< io::XSeekable
> xSeekableStor(xObjectStream
, uno::UNO_QUERY
);
783 if (xSeekableStor
.is())
784 xSeekableStor
->seek(0);
787 bCopied
= lcl_CopyStream(xObjectStream
->getInputStream(), xStream
->getOutputStream());
791 xNativeTempFile
->setPropertyValue("RemoveFile",
792 uno::makeAny(false));
793 uno::Any aUrl
= xNativeTempFile
->getPropertyValue("Uri");
796 xNativeTempFile
.clear();
798 uno::Reference
< ucb::XSimpleFileAccess3
> xSimpleFileAccess(
799 ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory
) ) );
801 xSimpleFileAccess
->setReadOnly(rUrl
, true);
805 xNativeTempFile
->setPropertyValue("RemoveFile",
812 //Dump the objects content to a tempfile, just the "CONTENTS" stream if
813 //there is one for non-compound documents, otherwise the whole content.
814 //On success a file is returned which must be removed by the caller
815 OUString
lcl_ExtractObject(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xFactory
,
816 const css::uno::Reference
< css::io::XStream
>& xObjectStream
)
820 // the solution is only active for Unix systems
822 lcl_GetExtractedStream(sUrl
, xFactory
, xObjectStream
);
825 (void) xObjectStream
;
830 uno::Reference
< io::XStream
> lcl_ExtractObjectStream( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xFactory
,
831 const css::uno::Reference
< css::io::XStream
>& xObjectStream
)
834 return lcl_GetExtractedStream( sUrl
, xFactory
, xObjectStream
);
839 void SAL_CALL
OleEmbeddedObject::doVerb( sal_Int32 nVerbID
)
840 throw ( lang::IllegalArgumentException
,
841 embed::WrongStateException
,
842 embed::UnreachableStateException
,
844 uno::RuntimeException
, std::exception
)
846 // begin wrapping related part ====================
847 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
848 if ( xWrappedObject
.is() )
850 // open content in the window not in-place
851 nVerbID
= embed::EmbedVerbs::MS_OLEVERB_OPEN
;
853 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
854 xWrappedObject
->doVerb( nVerbID
);
857 // end wrapping related part ====================
859 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
861 throw lang::DisposedException(); // TODO
863 if ( m_nObjectState
== -1 )
864 throw embed::WrongStateException( "The object has no persistence!",
865 static_cast< ::cppu::OWeakObject
* >(this) );
868 if ( m_pOleComponent
)
870 sal_Int32 nOldState
= m_nObjectState
;
872 // TODO/LATER detect target state here and do a notification
873 // StateChangeNotification_Impl( sal_True, nOldState, nNewState );
874 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
876 // if the target object is in loaded state
877 // it must be switched to running state to execute verb
879 changeState( embed::EmbedStates::RUNNING
);
884 if ( !m_pOleComponent
)
885 throw uno::RuntimeException();
887 // ==== the STAMPIT related solution =============================
888 m_aVerbExecutionController
.StartControlExecution();
891 m_pOleComponent
->ExecuteVerb( nVerbID
);
892 m_pOleComponent
->SetHostName( OUString(), m_aContainerName
);
894 // ==== the STAMPIT related solution =============================
895 bool bModifiedOnExecution
= m_aVerbExecutionController
.EndControlExecution_WasModified();
897 // this workaround is implemented for STAMPIT object
898 // if object was modified during verb execution it is saved here
899 if ( bModifiedOnExecution
&& m_pOleComponent
->IsDirty() )
903 catch( uno::Exception
& )
905 // ==== the STAMPIT related solution =============================
906 m_aVerbExecutionController
.EndControlExecution_WasModified();
910 StateChangeNotification_Impl( false, nOldState
, m_nObjectState
);
920 // the workaround verb to show the object in case no server is available
922 // if it is possible, the object will be converted to OOo format
923 if ( !m_bTriedConversion
)
925 m_bTriedConversion
= true;
926 if ( TryToConvertToOOo( m_xObjectStream
) )
928 changeState( embed::EmbedStates::ACTIVE
);
933 if ( !m_pOwnView
&& m_xObjectStream
.is() && m_aFilterName
!= "Text" )
936 uno::Reference
< io::XSeekable
> xSeekable( m_xObjectStream
, uno::UNO_QUERY
);
937 if ( xSeekable
.is() )
938 xSeekable
->seek( 0 );
940 m_pOwnView
= new OwnView_Impl( m_xFactory
, m_xObjectStream
->getInputStream() );
941 m_pOwnView
->acquire();
943 catch( uno::RuntimeException
& )
947 catch (uno::Exception
const& e
)
949 SAL_WARN("embeddedobj.ole", "OleEmbeddedObject::doVerb: "
950 "-9 fallback path: exception caught: " << e
.Message
);
954 // it may be the OLE Storage, try to extract stream
955 if ( !m_pOwnView
&& m_xObjectStream
.is() && m_aFilterName
== "Text" )
957 uno::Reference
< io::XStream
> xStream
= lcl_ExtractObjectStream( m_xFactory
, m_xObjectStream
);
959 if ( TryToConvertToOOo( xStream
) )
961 changeState( embed::EmbedStates::ACTIVE
);
966 if (!m_pOwnView
|| !m_pOwnView
->Open())
968 //Make a RO copy and see if the OS can find something to at
969 //least display the content for us
970 if (m_aTempDumpURL
.isEmpty())
971 m_aTempDumpURL
= lcl_ExtractObject(m_xFactory
, m_xObjectStream
);
973 if (!m_aTempDumpURL
.isEmpty())
975 uno::Reference
< css::system::XSystemShellExecute
> xSystemShellExecute(
976 css::system::SystemShellExecute::create(comphelper::getComponentContext(m_xFactory
)) );
977 xSystemShellExecute
->execute(m_aTempDumpURL
, OUString(), css::system::SystemShellExecuteFlags::URIS_ONLY
);
980 throw embed::UnreachableStateException();
986 throw embed::UnreachableStateException();
992 uno::Sequence
< embed::VerbDescriptor
> SAL_CALL
OleEmbeddedObject::getSupportedVerbs()
993 throw ( embed::WrongStateException
,
994 uno::RuntimeException
, std::exception
)
996 // begin wrapping related part ====================
997 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
998 if ( xWrappedObject
.is() )
1000 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1001 return xWrappedObject
->getSupportedVerbs();
1003 // end wrapping related part ====================
1005 ::osl::MutexGuard
aGuard( m_aMutex
);
1007 throw lang::DisposedException(); // TODO
1009 if ( m_nObjectState
== -1 )
1010 throw embed::WrongStateException( "The object has no persistence!",
1011 static_cast< ::cppu::OWeakObject
* >(this) );
1013 if ( m_pOleComponent
)
1015 // registry could be used in this case
1016 // if ( m_nObjectState == embed::EmbedStates::LOADED )
1018 // // the list of supported verbs can be retrieved only when object is in running state
1019 // throw embed::NeedsRunningStateException(); // TODO:
1022 return m_pOleComponent
->GetVerbList();
1027 return uno::Sequence
< embed::VerbDescriptor
>();
1032 void SAL_CALL
OleEmbeddedObject::setClientSite(
1033 const uno::Reference
< embed::XEmbeddedClient
>& xClient
)
1034 throw ( embed::WrongStateException
,
1035 uno::RuntimeException
, std::exception
)
1037 // begin wrapping related part ====================
1038 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1039 if ( xWrappedObject
.is() )
1041 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1042 xWrappedObject
->setClientSite( xClient
);
1045 // end wrapping related part ====================
1047 ::osl::MutexGuard
aGuard( m_aMutex
);
1049 throw lang::DisposedException(); // TODO
1051 if ( m_xClientSite
!= xClient
)
1053 if ( m_nObjectState
!= embed::EmbedStates::LOADED
&& m_nObjectState
!= embed::EmbedStates::RUNNING
)
1054 throw embed::WrongStateException(
1055 "The client site can not be set currently!",
1056 static_cast< ::cppu::OWeakObject
* >(this) );
1058 m_xClientSite
= xClient
;
1063 uno::Reference
< embed::XEmbeddedClient
> SAL_CALL
OleEmbeddedObject::getClientSite()
1064 throw ( embed::WrongStateException
,
1065 uno::RuntimeException
, std::exception
)
1067 // begin wrapping related part ====================
1068 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1069 if ( xWrappedObject
.is() )
1071 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1072 return xWrappedObject
->getClientSite();
1074 // end wrapping related part ====================
1076 ::osl::MutexGuard
aGuard( m_aMutex
);
1078 throw lang::DisposedException(); // TODO
1080 if ( m_nObjectState
== -1 )
1081 throw embed::WrongStateException( "The object has no persistence!",
1082 static_cast< ::cppu::OWeakObject
* >(this) );
1084 return m_xClientSite
;
1088 void SAL_CALL
OleEmbeddedObject::update()
1089 throw ( embed::WrongStateException
,
1091 uno::RuntimeException
, std::exception
)
1093 // begin wrapping related part ====================
1094 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1095 if ( xWrappedObject
.is() )
1097 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1098 xWrappedObject
->update();
1101 // end wrapping related part ====================
1103 ::osl::MutexGuard
aGuard( m_aMutex
);
1105 throw lang::DisposedException(); // TODO
1107 if ( m_nObjectState
== -1 )
1108 throw embed::WrongStateException( "The object has no persistence!",
1109 static_cast< ::cppu::OWeakObject
* >(this) );
1111 if ( m_nUpdateMode
== embed::EmbedUpdateModes::EXPLICIT_UPDATE
)
1113 // TODO: update view representation
1117 // the object must be up to date
1118 SAL_WARN_IF( m_nUpdateMode
!= embed::EmbedUpdateModes::ALWAYS_UPDATE
, "embeddedobj.ole", "Unknown update mode!" );
1123 void SAL_CALL
OleEmbeddedObject::setUpdateMode( sal_Int32 nMode
)
1124 throw ( embed::WrongStateException
,
1125 uno::RuntimeException
, std::exception
)
1127 // begin wrapping related part ====================
1128 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1129 if ( xWrappedObject
.is() )
1131 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1132 xWrappedObject
->setUpdateMode( nMode
);
1135 // end wrapping related part ====================
1137 ::osl::MutexGuard
aGuard( m_aMutex
);
1139 throw lang::DisposedException(); // TODO
1141 if ( m_nObjectState
== -1 )
1142 throw embed::WrongStateException( "The object has no persistence!",
1143 static_cast< ::cppu::OWeakObject
* >(this) );
1145 OSL_ENSURE( nMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
1146 || nMode
== embed::EmbedUpdateModes::EXPLICIT_UPDATE
,
1147 "Unknown update mode!\n" );
1148 m_nUpdateMode
= nMode
;
1152 sal_Int64 SAL_CALL
OleEmbeddedObject::getStatus( sal_Int64
1155 throw ( embed::WrongStateException
,
1156 uno::RuntimeException
, std::exception
)
1158 // begin wrapping related part ====================
1159 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1160 if ( xWrappedObject
.is() )
1162 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1163 return xWrappedObject
->getStatus( nAspect
);
1165 // end wrapping related part ====================
1167 ::osl::MutexGuard
aGuard( m_aMutex
);
1169 throw lang::DisposedException(); // TODO
1171 if ( m_nObjectState
== -1 )
1172 throw embed::WrongStateException( "The object must be in running state!",
1173 static_cast< ::cppu::OWeakObject
* >(this) );
1175 sal_Int64 nResult
= 0;
1178 if ( m_bGotStatus
&& m_nStatusAspect
== nAspect
)
1179 nResult
= m_nStatus
;
1180 else if ( m_pOleComponent
)
1183 m_nStatus
= m_pOleComponent
->GetMiscStatus( nAspect
);
1184 m_nStatusAspect
= nAspect
;
1185 m_bGotStatus
= true;
1186 nResult
= m_nStatus
;
1190 // this implementation needs size to be provided after object loading/creating to work in optimal way
1191 return ( nResult
| embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD
);
1195 void SAL_CALL
OleEmbeddedObject::setContainerName( const OUString
& sName
)
1196 throw ( uno::RuntimeException
, std::exception
)
1198 // begin wrapping related part ====================
1199 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1200 if ( xWrappedObject
.is() )
1202 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1203 xWrappedObject
->setContainerName( sName
);
1206 // end wrapping related part ====================
1208 ::osl::MutexGuard
aGuard( m_aMutex
);
1210 throw lang::DisposedException(); // TODO
1212 m_aContainerName
= sName
;
1216 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */