1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <oleembobj.hxx>
30 #include <com/sun/star/embed/EmbedStates.hpp>
31 #include <com/sun/star/embed/EmbedVerbs.hpp>
32 #include <com/sun/star/embed/EntryInitModes.hpp>
33 #include <com/sun/star/embed/XStorage.hpp>
34 #include <com/sun/star/embed/ElementModes.hpp>
35 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
36 #include <com/sun/star/embed/Aspects.hpp>
37 #include <com/sun/star/embed/NeedsRunningStateException.hpp>
38 #include <com/sun/star/embed/StateChangeInProgressException.hpp>
39 #include <com/sun/star/embed/EmbedMisc.hpp>
40 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
41 #include <com/sun/star/io/XSeekable.hpp>
42 #include <com/sun/star/lang/DisposedException.hpp>
43 #include <com/sun/star/beans/NamedValue.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/frame/XLoadable.hpp>
46 #include <com/sun/star/document/XStorageBasedDocument.hpp>
47 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
48 #include <com/sun/star/container/XNameAccess.hpp>
49 #include <com/sun/star/container/XNameContainer.hpp>
50 #include <com/sun/star/system/XSystemShellExecute.hpp>
51 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
53 #include <rtl/logfile.hxx>
54 #include <cppuhelper/interfacecontainer.h>
55 #include <comphelper/mimeconfighelper.hxx>
56 #include <comphelper/storagehelper.hxx>
59 #include <targetstatecontrol.hxx>
61 #include <olecomponent.hxx>
63 #include "ownview.hxx"
65 using namespace ::com::sun::star
;
68 //----------------------------------------------
69 void OleEmbeddedObject::SwitchComponentToRunningState_Impl()
71 if ( m_pOleComponent
)
75 m_pOleComponent
->RunObject();
77 catch( const embed::UnreachableStateException
& )
82 catch( const embed::WrongStateException
& )
90 throw embed::UnreachableStateException();
94 //----------------------------------------------
95 uno::Sequence
< sal_Int32
> OleEmbeddedObject::GetReachableStatesList_Impl(
96 const uno::Sequence
< embed::VerbDescriptor
>& aVerbList
)
98 uno::Sequence
< sal_Int32
> aStates(2);
99 aStates
[0] = embed::EmbedStates::LOADED
;
100 aStates
[1] = embed::EmbedStates::RUNNING
;
101 for ( sal_Int32 nInd
= 0; nInd
< aVerbList
.getLength(); nInd
++ )
102 if ( aVerbList
[nInd
].VerbID
== embed::EmbedVerbs::MS_OLEVERB_OPEN
)
105 aStates
[2] = embed::EmbedStates::ACTIVE
;
111 //----------------------------------------------
112 uno::Sequence
< sal_Int32
> OleEmbeddedObject::GetIntermediateVerbsSequence_Impl( sal_Int32 nNewState
)
114 OSL_ENSURE( m_nObjectState
!= embed::EmbedStates::LOADED
, "Loaded object is switched to running state without verbs using!" );
116 // actually there will be only one verb
117 if ( m_nObjectState
== embed::EmbedStates::RUNNING
&& nNewState
== embed::EmbedStates::ACTIVE
)
119 uno::Sequence
< sal_Int32
> aVerbs( 1 );
120 aVerbs
[0] = embed::EmbedVerbs::MS_OLEVERB_OPEN
;
123 return uno::Sequence
< sal_Int32
>();
126 //----------------------------------------------
127 void OleEmbeddedObject::MoveListeners()
129 if ( m_pInterfaceContainer
)
131 // move state change listeners
133 ::cppu::OInterfaceContainerHelper
* pStateChangeContainer
=
134 m_pInterfaceContainer
->getContainer( ::getCppuType( ( const uno::Reference
< embed::XStateChangeListener
>*) NULL
) );
135 if ( pStateChangeContainer
!= NULL
)
137 uno::Reference
< embed::XStateChangeBroadcaster
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
138 if ( xWrappedObject
.is() )
140 ::cppu::OInterfaceIteratorHelper
pIterator( *pStateChangeContainer
);
141 while ( pIterator
.hasMoreElements() )
145 xWrappedObject
->addStateChangeListener( (embed::XStateChangeListener
*)pIterator
.next() );
147 catch( const uno::RuntimeException
& )
156 // move event listeners
158 ::cppu::OInterfaceContainerHelper
* pEventContainer
=
159 m_pInterfaceContainer
->getContainer( ::getCppuType( ( const uno::Reference
< document::XEventListener
>*) NULL
) );
160 if ( pEventContainer
!= NULL
)
162 uno::Reference
< document::XEventBroadcaster
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
163 if ( xWrappedObject
.is() )
165 ::cppu::OInterfaceIteratorHelper
pIterator( *pEventContainer
);
166 while ( pIterator
.hasMoreElements() )
170 xWrappedObject
->addEventListener( (document::XEventListener
*)pIterator
.next() );
172 catch( const uno::RuntimeException
& )
181 // move close listeners
183 ::cppu::OInterfaceContainerHelper
* pCloseContainer
=
184 m_pInterfaceContainer
->getContainer( ::getCppuType( ( const uno::Reference
< util::XCloseListener
>*) NULL
) );
185 if ( pCloseContainer
!= NULL
)
187 uno::Reference
< util::XCloseBroadcaster
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
188 if ( xWrappedObject
.is() )
190 ::cppu::OInterfaceIteratorHelper
pIterator( *pCloseContainer
);
191 while ( pIterator
.hasMoreElements() )
195 xWrappedObject
->addCloseListener( (util::XCloseListener
*)pIterator
.next() );
197 catch( const uno::RuntimeException
& )
206 delete m_pInterfaceContainer
;
207 m_pInterfaceContainer
= NULL
;
211 //----------------------------------------------
212 uno::Reference
< embed::XStorage
> OleEmbeddedObject::CreateTemporarySubstorage( ::rtl::OUString
& o_aStorageName
)
214 uno::Reference
< embed::XStorage
> xResult
;
216 for ( sal_Int32 nInd
= 0; nInd
< 32000 && !xResult
.is(); nInd
++ )
218 ::rtl::OUString aName
= ::rtl::OUString::valueOf( nInd
);
219 aName
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TMPSTOR" ) );
220 aName
+= m_aEntryName
;
221 if ( !m_xParentStorage
->hasByName( aName
) )
223 xResult
= m_xParentStorage
->openStorageElement( aName
, embed::ElementModes::READWRITE
);
224 o_aStorageName
= aName
;
230 o_aStorageName
= ::rtl::OUString();
231 throw uno::RuntimeException();
237 //----------------------------------------------
238 ::rtl::OUString
OleEmbeddedObject::MoveToTemporarySubstream()
240 ::rtl::OUString aResult
;
241 for ( sal_Int32 nInd
= 0; nInd
< 32000 && aResult
.isEmpty(); nInd
++ )
243 ::rtl::OUString aName
= ::rtl::OUString::valueOf( nInd
);
244 aName
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TMPSTREAM" ) );
245 aName
+= m_aEntryName
;
246 if ( !m_xParentStorage
->hasByName( aName
) )
248 m_xParentStorage
->renameElement( m_aEntryName
, aName
);
253 if ( aResult
.isEmpty() )
254 throw uno::RuntimeException();
259 //----------------------------------------------
260 sal_Bool
OleEmbeddedObject::TryToConvertToOOo()
262 sal_Bool bResult
= sal_False
;
264 ::rtl::OUString aStorageName
;
265 ::rtl::OUString aTmpStreamName
;
268 if ( m_pOleComponent
|| m_bReadOnly
)
273 changeState( embed::EmbedStates::LOADED
);
275 // the stream must be seekable
276 uno::Reference
< io::XSeekable
> xSeekable( m_xObjectStream
, uno::UNO_QUERY_THROW
);
277 xSeekable
->seek( 0 );
278 ::rtl::OUString aFilterName
= OwnView_Impl::GetFilterNameFromExtentionAndInStream( m_xFactory
, ::rtl::OUString(), m_xObjectStream
->getInputStream() );
280 // use the solution only for OOXML format currently
281 if ( !aFilterName
.isEmpty()
282 && ( aFilterName
== "Calc MS Excel 2007 XML" || aFilterName
== "Impress MS PowerPoint 2007 XML" || aFilterName
== "MS Word 2007 XML" ) )
284 uno::Reference
< container::XNameAccess
> xFilterFactory(
285 m_xFactory
->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.FilterFactory" ) )),
286 uno::UNO_QUERY_THROW
);
288 ::rtl::OUString aDocServiceName
;
289 uno::Any aFilterAnyData
= xFilterFactory
->getByName( aFilterName
);
290 uno::Sequence
< beans::PropertyValue
> aFilterData
;
291 if ( aFilterAnyData
>>= aFilterData
)
293 for ( sal_Int32 nInd
= 0; nInd
< aFilterData
.getLength(); nInd
++ )
294 if ( aFilterData
[nInd
].Name
== "DocumentService" )
295 aFilterData
[nInd
].Value
>>= aDocServiceName
;
298 if ( !aDocServiceName
.isEmpty() )
301 uno::Sequence
< uno::Any
> aArguments(1);
302 aArguments
[0] <<= beans::NamedValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EmbeddedObject" ) ), uno::makeAny( (sal_Bool
)sal_True
));
304 uno::Reference
< util::XCloseable
> xDocument( m_xFactory
->createInstanceWithArguments( aDocServiceName
, aArguments
), uno::UNO_QUERY_THROW
);
305 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY_THROW
);
306 uno::Reference
< document::XStorageBasedDocument
> xStorDoc( xDocument
, uno::UNO_QUERY_THROW
);
308 // let the model behave as embedded one
309 uno::Reference
< frame::XModel
> xModel( xDocument
, uno::UNO_QUERY_THROW
);
310 uno::Sequence
< beans::PropertyValue
> aSeq( 1 );
311 aSeq
[0].Name
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "SetEmbedded" ));
312 aSeq
[0].Value
<<= sal_True
;
313 xModel
->attachResource( ::rtl::OUString(), aSeq
);
315 // load the model from the stream
316 uno::Sequence
< beans::PropertyValue
> aArgs( 5 );
317 aArgs
[0].Name
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "HierarchicalDocumentName" ));
318 aArgs
[0].Value
<<= m_aEntryName
;
319 aArgs
[1].Name
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ReadOnly" ));
320 aArgs
[1].Value
<<= sal_True
;
321 aArgs
[2].Name
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FilterName" ));
322 aArgs
[2].Value
<<= aFilterName
;
323 aArgs
[3].Name
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "URL" ));
324 aArgs
[3].Value
<<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "private:stream" ));
325 aArgs
[4].Name
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "InputStream" ));
326 aArgs
[4].Value
<<= m_xObjectStream
->getInputStream();
328 xSeekable
->seek( 0 );
329 xLoadable
->load( aArgs
);
331 // the model is successfuly loaded, create a new storage and store the model to the storage
332 uno::Reference
< embed::XStorage
> xTmpStorage
= CreateTemporarySubstorage( aStorageName
);
333 xStorDoc
->storeToStorage( xTmpStorage
, uno::Sequence
< beans::PropertyValue
>() );
334 xDocument
->close( sal_True
);
335 uno::Reference
< beans::XPropertySet
> xStorProps( xTmpStorage
, uno::UNO_QUERY_THROW
);
336 ::rtl::OUString aMediaType
;
337 xStorProps
->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "MediaType" )) ) >>= aMediaType
;
338 xTmpStorage
->dispose();
340 // look for the related embedded object factory
341 ::comphelper::MimeConfigurationHelper
aConfigHelper( m_xFactory
);
342 ::rtl::OUString aEmbedFactory
;
343 if ( !aMediaType
.isEmpty() )
344 aEmbedFactory
= aConfigHelper
.GetFactoryNameByMediaType( aMediaType
);
346 if ( aEmbedFactory
.isEmpty() )
347 throw uno::RuntimeException();
349 uno::Reference
< uno::XInterface
> xFact
= m_xFactory
->createInstance( aEmbedFactory
);
351 uno::Reference
< embed::XEmbedObjectCreator
> xEmbCreator( xFact
, uno::UNO_QUERY_THROW
);
353 // now the object should be adjusted to become the wrapper
355 uno::Reference
< lang::XComponent
> xComp( m_xObjectStream
, uno::UNO_QUERY_THROW
);
357 m_xObjectStream
= uno::Reference
< io::XStream
>();
361 aTmpStreamName
= MoveToTemporarySubstream();
364 m_xParentStorage
->renameElement( aStorageName
, m_aEntryName
);
367 m_xWrappedObject
.set( xEmbCreator
->createInstanceInitFromEntry( m_xParentStorage
, m_aEntryName
, uno::Sequence
< beans::PropertyValue
>(), uno::Sequence
< beans::PropertyValue
>() ), uno::UNO_QUERY_THROW
);
369 bResult
= sal_True
; // the change is no more revertable
372 m_xParentStorage
->removeElement( aTmpStreamName
);
374 catch( const uno::Exception
& )
376 // the success of the removing is not so important
381 catch( const uno::Exception
& )
383 // repair the object if necessary
388 if ( !aTmpStreamName
.isEmpty() && aTmpStreamName
!= m_aEntryName
)
391 if ( m_xParentStorage
->hasByName( m_aEntryName
) )
392 m_xParentStorage
->removeElement( m_aEntryName
);
393 m_xParentStorage
->renameElement( aTmpStreamName
, m_aEntryName
);
395 catch ( const uno::Exception
& )
399 } catch( const uno::Exception
& ) {}
401 m_xParentStorage
->dispose(); // ??? the storage has information loss, it should be closed without commiting!
402 throw uno::RuntimeException(); // the repairing is not possible
407 m_xObjectStream
= m_xParentStorage
->openStreamElement( m_aEntryName
, m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
);
408 m_nObjectState
= embed::EmbedStates::LOADED
;
410 catch( const uno::Exception
& )
414 } catch( const uno::Exception
& ) {}
416 throw uno::RuntimeException(); // the repairing is not possible
418 // no break as designed!
422 if ( !aStorageName
.isEmpty() )
424 m_xParentStorage
->removeElement( aStorageName
);
425 } catch( const uno::Exception
& ) { OSL_FAIL( "Can not remove temporary storage!" ); }
432 // the conversion was done successfuly, now the additional initializations should happen
435 m_xWrappedObject
->setClientSite( m_xClientSite
);
436 if ( m_xParent
.is() )
438 uno::Reference
< container::XChild
> xChild( m_xWrappedObject
, uno::UNO_QUERY
);
440 xChild
->setParent( m_xParent
);
448 //----------------------------------------------
449 void SAL_CALL
OleEmbeddedObject::changeState( sal_Int32 nNewState
)
450 throw ( embed::UnreachableStateException
,
451 embed::WrongStateException
,
453 uno::RuntimeException
)
455 RTL_LOGFILE_CONTEXT( aLog
, "embeddedobj (mv76033) OleEmbeddedObject::changeState" );
457 // begin wrapping related part ====================
458 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
459 if ( xWrappedObject
.is() )
461 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
462 xWrappedObject
->changeState( nNewState
);
465 // end wrapping related part ====================
467 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
470 throw lang::DisposedException(); // TODO
472 if ( m_nObjectState
== -1 )
473 throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object has no persistence!\n" )),
474 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
476 // in case the object is already in requested state
477 if ( m_nObjectState
== nNewState
)
481 if ( m_pOleComponent
)
483 if ( m_nTargetState
!= -1 )
485 // means that the object is currently trying to reach the target state
486 throw embed::StateChangeInProgressException( ::rtl::OUString(),
487 uno::Reference
< uno::XInterface
>(),
491 TargetStateControl_Impl
aControl( m_nTargetState
, nNewState
);
493 // TODO: additional verbs can be a problem, since nobody knows how the object
494 // will behave after activation
496 sal_Int32 nOldState
= m_nObjectState
;
498 StateChangeNotification_Impl( sal_True
, nOldState
, nNewState
);
503 if ( nNewState
== embed::EmbedStates::LOADED
)
505 // This means just closing of the current object
506 // If component can not be closed the object stays in loaded state
507 // and it holds reference to "incomplete" component
508 // If the object is switched to running state later
509 // the component will become "complete"
511 // the loaded state must be set before, because of notifications!
512 m_nObjectState
= nNewState
;
515 VerbExecutionControllerGuard
aVerbGuard( m_aVerbExecutionController
);
516 m_pOleComponent
->CloseObject();
520 StateChangeNotification_Impl( sal_False
, nOldState
, m_nObjectState
);
523 else if ( nNewState
== embed::EmbedStates::RUNNING
|| nNewState
== embed::EmbedStates::ACTIVE
)
525 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
527 // if the target object is in loaded state and a different state is specified
528 // as a new one the object first must be switched to running state.
530 // the component can exist already in nonrunning state
531 // it can be created during loading to detect type of object
532 CreateOleComponentAndLoad_Impl( m_pOleComponent
);
534 SwitchComponentToRunningState_Impl();
535 m_nObjectState
= embed::EmbedStates::RUNNING
;
537 StateChangeNotification_Impl( sal_False
, nOldState
, m_nObjectState
);
540 if ( m_pOleComponent
&& m_bHasSizeToSet
)
544 m_pOleComponent
->SetExtent( m_aSizeToSet
, m_nAspectToSet
);
545 m_bHasSizeToSet
= sal_False
;
547 catch( const uno::Exception
& ) {}
551 if ( m_nObjectState
== nNewState
)
555 // so now the object is either switched from Active to Running state or vise versa
556 // the notification about object state change will be done asynchronously
557 if ( m_nObjectState
== embed::EmbedStates::RUNNING
&& nNewState
== embed::EmbedStates::ACTIVE
)
559 // execute OPEN verb, if object does not reach active state it is an object's problem
561 m_pOleComponent
->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN
);
564 // some objects do not allow to set the size even in running state
565 if ( m_pOleComponent
&& m_bHasSizeToSet
)
569 m_pOleComponent
->SetExtent( m_aSizeToSet
, m_nAspectToSet
);
570 m_bHasSizeToSet
= sal_False
;
572 catch( uno::Exception
& ) {}
576 m_nObjectState
= nNewState
;
578 else if ( m_nObjectState
== embed::EmbedStates::ACTIVE
&& nNewState
== embed::EmbedStates::RUNNING
)
581 m_pOleComponent
->CloseObject();
582 m_pOleComponent
->RunObject(); // Should not fail, the object already was active
584 m_nObjectState
= nNewState
;
588 throw embed::UnreachableStateException();
592 throw embed::UnreachableStateException();
594 catch( uno::Exception
& )
597 StateChangeNotification_Impl( sal_False
, nOldState
, m_nObjectState
);
604 throw embed::UnreachableStateException();
608 //----------------------------------------------
609 uno::Sequence
< sal_Int32
> SAL_CALL
OleEmbeddedObject::getReachableStates()
610 throw ( embed::WrongStateException
,
611 uno::RuntimeException
)
613 RTL_LOGFILE_CONTEXT( aLog
, "embeddedobj (mv76033) OleEmbeddedObject::getReachableStates" );
615 // begin wrapping related part ====================
616 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
617 if ( xWrappedObject
.is() )
619 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
620 return xWrappedObject
->getReachableStates();
622 // end wrapping related part ====================
624 ::osl::MutexGuard
aGuard( m_aMutex
);
626 throw lang::DisposedException(); // TODO
628 if ( m_nObjectState
== -1 )
629 throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object has no persistence!\n" )),
630 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
633 if ( m_pOleComponent
)
635 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
637 // the list of supported verbs can be retrieved only when object is in running state
638 throw embed::NeedsRunningStateException(); // TODO:
641 // the list of states can only be guessed based on standard verbs,
642 // since there is no way to detect what additional verbs do
643 return GetReachableStatesList_Impl( m_pOleComponent
->GetVerbList() );
648 return uno::Sequence
< sal_Int32
>();
652 //----------------------------------------------
653 sal_Int32 SAL_CALL
OleEmbeddedObject::getCurrentState()
654 throw ( embed::WrongStateException
,
655 uno::RuntimeException
)
657 // begin wrapping related part ====================
658 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
659 if ( xWrappedObject
.is() )
661 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
662 return xWrappedObject
->getCurrentState();
664 // end wrapping related part ====================
666 ::osl::MutexGuard
aGuard( m_aMutex
);
668 throw lang::DisposedException(); // TODO
670 if ( m_nObjectState
== -1 )
671 throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object has no persistence!\n" )),
672 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
674 // TODO: Shouldn't we ask object? ( I guess no )
675 return m_nObjectState
;
680 bool lcl_CopyStream(uno::Reference
<io::XInputStream
> xIn
, uno::Reference
<io::XOutputStream
> xOut
)
682 const sal_Int32 nChunkSize
= 4096;
683 uno::Sequence
< sal_Int8
> aData(nChunkSize
);
684 sal_Int32 nTotalRead
= 0;
688 nRead
= xIn
->readBytes(aData
, nChunkSize
);
690 xOut
->writeBytes(aData
);
691 } while (nRead
== nChunkSize
);
692 return nTotalRead
!= 0;
695 //Dump the objects content to a tempfile, just the "CONTENTS" stream if
696 //there is one for non-compound documents, otherwise the whole content.
697 //On success a file is returned which must be removed by the caller
698 rtl::OUString
lcl_ExtractObject(::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> xFactory
,
699 ::com::sun::star::uno::Reference
< ::com::sun::star::io::XStream
> xObjectStream
)
703 // the solution is only active for Unix systems
705 uno::Reference
<beans::XPropertySet
> xNativeTempFile(
706 xFactory
->createInstance(
707 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.TempFile"))), uno::UNO_QUERY_THROW
);
708 uno::Reference
< io::XStream
> xStream(xNativeTempFile
, uno::UNO_QUERY_THROW
);
710 uno::Sequence
< uno::Any
> aArgs( 2 );
711 aArgs
[0] <<= xObjectStream
;
712 aArgs
[1] <<= (sal_Bool
)sal_True
; // do not create copy
713 uno::Reference
< container::XNameContainer
> xNameContainer(
714 xFactory
->createInstanceWithArguments(
715 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.OLESimpleStorage")),
716 aArgs
), uno::UNO_QUERY_THROW
);
718 uno::Reference
< io::XStream
> xCONTENTS
;
719 xNameContainer
->getByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CONTENTS"))) >>= xCONTENTS
;
721 sal_Bool bCopied
= xCONTENTS
.is() && lcl_CopyStream(xCONTENTS
->getInputStream(), xStream
->getOutputStream());
723 uno::Reference
< io::XSeekable
> xSeekableStor(xObjectStream
, uno::UNO_QUERY
);
724 if (xSeekableStor
.is())
725 xSeekableStor
->seek(0);
728 bCopied
= lcl_CopyStream(xObjectStream
->getInputStream(), xStream
->getOutputStream());
732 xNativeTempFile
->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RemoveFile")),
733 uno::makeAny(sal_False
));
734 uno::Any aUrl
= xNativeTempFile
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Uri")));
737 xNativeTempFile
= uno::Reference
<beans::XPropertySet
>();
739 uno::Reference
<ucb::XSimpleFileAccess
> xSimpleFileAccess(
740 xFactory
->createInstance(
741 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SimpleFileAccess"))),
742 uno::UNO_QUERY_THROW
);
744 xSimpleFileAccess
->setReadOnly(sUrl
, sal_True
);
748 xNativeTempFile
->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RemoveFile")),
749 uno::makeAny(sal_True
));
753 (void) xObjectStream
;
759 //----------------------------------------------
760 void SAL_CALL
OleEmbeddedObject::doVerb( sal_Int32 nVerbID
)
761 throw ( lang::IllegalArgumentException
,
762 embed::WrongStateException
,
763 embed::UnreachableStateException
,
765 uno::RuntimeException
)
767 RTL_LOGFILE_CONTEXT( aLog
, "embeddedobj (mv76033) OleEmbeddedObject::doVerb" );
769 // begin wrapping related part ====================
770 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
771 if ( xWrappedObject
.is() )
773 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
774 xWrappedObject
->doVerb( nVerbID
);
777 // end wrapping related part ====================
779 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
781 throw lang::DisposedException(); // TODO
783 if ( m_nObjectState
== -1 )
784 throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object has no persistence!\n" )),
785 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
788 if ( m_pOleComponent
)
790 sal_Int32 nOldState
= m_nObjectState
;
792 // TODO/LATER detect target state here and do a notification
793 // StateChangeNotification_Impl( sal_True, nOldState, nNewState );
794 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
796 // if the target object is in loaded state
797 // it must be switched to running state to execute verb
799 changeState( embed::EmbedStates::RUNNING
);
804 if ( !m_pOleComponent
)
805 throw uno::RuntimeException();
807 // ==== the STAMPIT related solution =============================
808 m_aVerbExecutionController
.StartControlExecution();
809 // ===============================================================
811 m_pOleComponent
->ExecuteVerb( nVerbID
);
813 // ==== the STAMPIT related solution =============================
814 sal_Bool bModifiedOnExecution
= m_aVerbExecutionController
.EndControlExecution_WasModified();
816 // this workaround is implemented for STAMPIT object
817 // if object was modified during verb execution it is saved here
818 if ( bModifiedOnExecution
&& m_pOleComponent
->IsDirty() )
820 // ===============================================================
822 catch( uno::Exception
& )
824 // ==== the STAMPIT related solution =============================
825 m_aVerbExecutionController
.EndControlExecution_WasModified();
826 // ===============================================================
829 StateChangeNotification_Impl( sal_False
, nOldState
, m_nObjectState
);
839 // the workaround verb to show the object in case no server is available
841 // if it is possible, the object will be converted to OOo format
842 if ( !m_bTriedConversion
)
844 m_bTriedConversion
= sal_True
;
845 if ( TryToConvertToOOo() )
847 changeState( embed::EmbedStates::UI_ACTIVE
);
852 if ( !m_pOwnView
&& m_xObjectStream
.is() )
855 uno::Reference
< io::XSeekable
> xSeekable( m_xObjectStream
, uno::UNO_QUERY
);
856 if ( xSeekable
.is() )
857 xSeekable
->seek( 0 );
859 m_pOwnView
= new OwnView_Impl( m_xFactory
, m_xObjectStream
->getInputStream() );
860 m_pOwnView
->acquire();
862 catch( uno::RuntimeException
& )
866 catch( uno::Exception
& )
871 if ( !m_pOwnView
|| !m_pOwnView
->Open() )
873 //Make a RO copy and see if the OS can find something to at
874 //least display the content for us
875 if (m_aTempDumpURL
.isEmpty())
876 m_aTempDumpURL
= lcl_ExtractObject(m_xFactory
, m_xObjectStream
);
878 if (!m_aTempDumpURL
.isEmpty())
880 uno::Reference
< ::com::sun::star::system::XSystemShellExecute
> xSystemShellExecute( m_xFactory
->createInstance(
881 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.system.SystemShellExecute"))),
882 uno::UNO_QUERY_THROW
);
883 xSystemShellExecute
->execute(m_aTempDumpURL
, ::rtl::OUString(), ::com::sun::star::system::SystemShellExecuteFlags::URIS_ONLY
);
886 throw embed::UnreachableStateException();
892 throw embed::UnreachableStateException();
897 //----------------------------------------------
898 uno::Sequence
< embed::VerbDescriptor
> SAL_CALL
OleEmbeddedObject::getSupportedVerbs()
899 throw ( embed::WrongStateException
,
900 uno::RuntimeException
)
902 RTL_LOGFILE_CONTEXT( aLog
, "embeddedobj (mv76033) OleEmbeddedObject::getSupportedVerb" );
904 // begin wrapping related part ====================
905 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
906 if ( xWrappedObject
.is() )
908 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
909 return xWrappedObject
->getSupportedVerbs();
911 // end wrapping related part ====================
913 ::osl::MutexGuard
aGuard( m_aMutex
);
915 throw lang::DisposedException(); // TODO
917 if ( m_nObjectState
== -1 )
918 throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object has no persistence!\n" )),
919 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
921 if ( m_pOleComponent
)
923 // registry could be used in this case
924 // if ( m_nObjectState == embed::EmbedStates::LOADED )
926 // // the list of supported verbs can be retrieved only when object is in running state
927 // throw embed::NeedsRunningStateException(); // TODO:
930 return m_pOleComponent
->GetVerbList();
935 return uno::Sequence
< embed::VerbDescriptor
>();
939 //----------------------------------------------
940 void SAL_CALL
OleEmbeddedObject::setClientSite(
941 const uno::Reference
< embed::XEmbeddedClient
>& xClient
)
942 throw ( embed::WrongStateException
,
943 uno::RuntimeException
)
945 // begin wrapping related part ====================
946 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
947 if ( xWrappedObject
.is() )
949 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
950 xWrappedObject
->setClientSite( xClient
);
953 // end wrapping related part ====================
955 ::osl::MutexGuard
aGuard( m_aMutex
);
957 throw lang::DisposedException(); // TODO
959 if ( m_xClientSite
!= xClient
)
961 if ( m_nObjectState
!= embed::EmbedStates::LOADED
&& m_nObjectState
!= embed::EmbedStates::RUNNING
)
962 throw embed::WrongStateException(
963 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The client site can not be set currently!\n" )),
964 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
966 m_xClientSite
= xClient
;
970 //----------------------------------------------
971 uno::Reference
< embed::XEmbeddedClient
> SAL_CALL
OleEmbeddedObject::getClientSite()
972 throw ( embed::WrongStateException
,
973 uno::RuntimeException
)
975 // begin wrapping related part ====================
976 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
977 if ( xWrappedObject
.is() )
979 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
980 return xWrappedObject
->getClientSite();
982 // end wrapping related part ====================
984 ::osl::MutexGuard
aGuard( m_aMutex
);
986 throw lang::DisposedException(); // TODO
988 if ( m_nObjectState
== -1 )
989 throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object has no persistence!\n" )),
990 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
992 return m_xClientSite
;
995 //----------------------------------------------
996 void SAL_CALL
OleEmbeddedObject::update()
997 throw ( embed::WrongStateException
,
999 uno::RuntimeException
)
1001 // begin wrapping related part ====================
1002 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1003 if ( xWrappedObject
.is() )
1005 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1006 xWrappedObject
->update();
1009 // end wrapping related part ====================
1011 ::osl::MutexGuard
aGuard( m_aMutex
);
1013 throw lang::DisposedException(); // TODO
1015 if ( m_nObjectState
== -1 )
1016 throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object has no persistence!\n" )),
1017 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1019 if ( m_nUpdateMode
== embed::EmbedUpdateModes::EXPLICIT_UPDATE
)
1021 // TODO: update view representation
1025 // the object must be up to date
1026 OSL_ENSURE( m_nUpdateMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
, "Unknown update mode!\n" );
1030 //----------------------------------------------
1031 void SAL_CALL
OleEmbeddedObject::setUpdateMode( sal_Int32 nMode
)
1032 throw ( embed::WrongStateException
,
1033 uno::RuntimeException
)
1035 // begin wrapping related part ====================
1036 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1037 if ( xWrappedObject
.is() )
1039 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1040 xWrappedObject
->setUpdateMode( nMode
);
1043 // end wrapping related part ====================
1045 ::osl::MutexGuard
aGuard( m_aMutex
);
1047 throw lang::DisposedException(); // TODO
1049 if ( m_nObjectState
== -1 )
1050 throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object has no persistence!\n" )),
1051 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1053 OSL_ENSURE( nMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
1054 || nMode
== embed::EmbedUpdateModes::EXPLICIT_UPDATE
,
1055 "Unknown update mode!\n" );
1056 m_nUpdateMode
= nMode
;
1059 //----------------------------------------------
1060 sal_Int64 SAL_CALL
OleEmbeddedObject::getStatus( sal_Int64
1063 throw ( embed::WrongStateException
,
1064 uno::RuntimeException
)
1066 // begin wrapping related part ====================
1067 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1068 if ( xWrappedObject
.is() )
1070 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1071 return xWrappedObject
->getStatus( nAspect
);
1073 // end wrapping related part ====================
1075 ::osl::MutexGuard
aGuard( m_aMutex
);
1077 throw lang::DisposedException(); // TODO
1079 if ( m_nObjectState
== -1 )
1080 throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object must be in running state!\n" )),
1081 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1083 sal_Int64 nResult
= 0;
1086 if ( m_bGotStatus
&& m_nStatusAspect
== nAspect
)
1087 nResult
= m_nStatus
;
1088 else if ( m_pOleComponent
)
1091 m_nStatus
= m_pOleComponent
->GetMiscStatus( nAspect
);
1092 m_nStatusAspect
= nAspect
;
1093 m_bGotStatus
= sal_True
;
1094 nResult
= m_nStatus
;
1098 // this implementation needs size to be provided after object loading/creating to work in optimal way
1099 return ( nResult
| embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD
);
1102 //----------------------------------------------
1103 void SAL_CALL
OleEmbeddedObject::setContainerName( const ::rtl::OUString
& sName
)
1104 throw ( uno::RuntimeException
)
1106 // begin wrapping related part ====================
1107 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1108 if ( xWrappedObject
.is() )
1110 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1111 xWrappedObject
->setContainerName( sName
);
1114 // end wrapping related part ====================
1116 ::osl::MutexGuard
aGuard( m_aMutex
);
1118 throw lang::DisposedException(); // TODO
1120 m_aContainerName
= sName
;
1124 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */