Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / embeddedobj / source / msole / oleembed.cxx
blobb0c8abc0f88ad4a6c136f57646d35ebae646e3c9
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/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 <olecomponent.hxx>
55 #include "ownview.hxx"
57 using namespace ::com::sun::star;
59 #ifdef WNT
60 //----------------------------------------------
61 void OleEmbeddedObject::SwitchComponentToRunningState_Impl()
63 if ( m_pOleComponent )
65 try
67 m_pOleComponent->RunObject();
69 catch( const embed::UnreachableStateException& )
71 GetRidOfComponent();
72 throw;
74 catch( const embed::WrongStateException& )
76 GetRidOfComponent();
77 throw;
80 else
82 throw embed::UnreachableStateException();
86 //----------------------------------------------
87 uno::Sequence< sal_Int32 > OleEmbeddedObject::GetReachableStatesList_Impl(
88 const uno::Sequence< embed::VerbDescriptor >& aVerbList )
90 uno::Sequence< sal_Int32 > aStates(2);
91 aStates[0] = embed::EmbedStates::LOADED;
92 aStates[1] = embed::EmbedStates::RUNNING;
93 for ( sal_Int32 nInd = 0; nInd < aVerbList.getLength(); nInd++ )
94 if ( aVerbList[nInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_OPEN )
96 aStates.realloc(3);
97 aStates[2] = embed::EmbedStates::ACTIVE;
100 return aStates;
103 //----------------------------------------------
104 uno::Sequence< sal_Int32 > OleEmbeddedObject::GetIntermediateVerbsSequence_Impl( sal_Int32 nNewState )
106 SAL_WARN_IF( m_nObjectState == embed::EmbedStates::LOADED, "embeddedobj.ole", "Loaded object is switched to running state without verbs using!" );
108 // actually there will be only one verb
109 if ( m_nObjectState == embed::EmbedStates::RUNNING && nNewState == embed::EmbedStates::ACTIVE )
111 uno::Sequence< sal_Int32 > aVerbs( 1 );
112 aVerbs[0] = embed::EmbedVerbs::MS_OLEVERB_OPEN;
115 return uno::Sequence< sal_Int32 >();
117 #endif
118 //----------------------------------------------
119 void OleEmbeddedObject::MoveListeners()
121 if ( m_pInterfaceContainer )
123 // move state change listeners
125 ::cppu::OInterfaceContainerHelper* pStateChangeContainer =
126 m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< embed::XStateChangeListener >*) NULL ) );
127 if ( pStateChangeContainer != NULL )
129 uno::Reference< embed::XStateChangeBroadcaster > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
130 if ( xWrappedObject.is() )
132 ::cppu::OInterfaceIteratorHelper pIterator( *pStateChangeContainer );
133 while ( pIterator.hasMoreElements() )
137 xWrappedObject->addStateChangeListener( (embed::XStateChangeListener*)pIterator.next() );
139 catch( const uno::RuntimeException& )
141 pIterator.remove();
148 // move event listeners
150 ::cppu::OInterfaceContainerHelper* pEventContainer =
151 m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< document::XEventListener >*) NULL ) );
152 if ( pEventContainer != NULL )
154 uno::Reference< document::XEventBroadcaster > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
155 if ( xWrappedObject.is() )
157 ::cppu::OInterfaceIteratorHelper pIterator( *pEventContainer );
158 while ( pIterator.hasMoreElements() )
162 xWrappedObject->addEventListener( (document::XEventListener*)pIterator.next() );
164 catch( const uno::RuntimeException& )
166 pIterator.remove();
173 // move close listeners
175 ::cppu::OInterfaceContainerHelper* pCloseContainer =
176 m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XCloseListener >*) NULL ) );
177 if ( pCloseContainer != NULL )
179 uno::Reference< util::XCloseBroadcaster > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
180 if ( xWrappedObject.is() )
182 ::cppu::OInterfaceIteratorHelper pIterator( *pCloseContainer );
183 while ( pIterator.hasMoreElements() )
187 xWrappedObject->addCloseListener( (util::XCloseListener*)pIterator.next() );
189 catch( const uno::RuntimeException& )
191 pIterator.remove();
198 delete m_pInterfaceContainer;
199 m_pInterfaceContainer = NULL;
203 //----------------------------------------------
204 uno::Reference< embed::XStorage > OleEmbeddedObject::CreateTemporarySubstorage( OUString& o_aStorageName )
206 uno::Reference< embed::XStorage > xResult;
208 for ( sal_Int32 nInd = 0; nInd < 32000 && !xResult.is(); nInd++ )
210 OUString aName = OUString::number( nInd ) + "TMPSTOR" + m_aEntryName;
211 if ( !m_xParentStorage->hasByName( aName ) )
213 xResult = m_xParentStorage->openStorageElement( aName, embed::ElementModes::READWRITE );
214 o_aStorageName = aName;
218 if ( !xResult.is() )
220 o_aStorageName = OUString();
221 throw uno::RuntimeException();
224 return xResult;
227 //----------------------------------------------
228 OUString OleEmbeddedObject::MoveToTemporarySubstream()
230 OUString aResult;
231 for ( sal_Int32 nInd = 0; nInd < 32000 && aResult.isEmpty(); nInd++ )
233 OUString aName = OUString::number( nInd ) + "TMPSTREAM" + m_aEntryName;
234 if ( !m_xParentStorage->hasByName( aName ) )
236 m_xParentStorage->renameElement( m_aEntryName, aName );
237 aResult = aName;
241 if ( aResult.isEmpty() )
242 throw uno::RuntimeException();
244 return aResult;
247 //----------------------------------------------
248 sal_Bool OleEmbeddedObject::TryToConvertToOOo()
250 sal_Bool bResult = sal_False;
252 OUString aStorageName;
253 OUString aTmpStreamName;
254 sal_Int32 nStep = 0;
256 if ( m_pOleComponent || m_bReadOnly )
257 return sal_False;
261 changeState( embed::EmbedStates::LOADED );
263 // the stream must be seekable
264 uno::Reference< io::XSeekable > xSeekable( m_xObjectStream, uno::UNO_QUERY_THROW );
265 xSeekable->seek( 0 );
266 OUString aFilterName = OwnView_Impl::GetFilterNameFromExtentionAndInStream( m_xFactory, OUString(), m_xObjectStream->getInputStream() );
268 // use the solution only for OOXML format currently
269 if ( !aFilterName.isEmpty()
270 && ( aFilterName == "Calc MS Excel 2007 XML" || aFilterName == "Impress MS PowerPoint 2007 XML" || aFilterName == "MS Word 2007 XML" ) )
272 uno::Reference< container::XNameAccess > xFilterFactory(
273 m_xFactory->createInstance("com.sun.star.document.FilterFactory"),
274 uno::UNO_QUERY_THROW );
276 OUString aDocServiceName;
277 uno::Any aFilterAnyData = xFilterFactory->getByName( aFilterName );
278 uno::Sequence< beans::PropertyValue > aFilterData;
279 if ( aFilterAnyData >>= aFilterData )
281 for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ )
282 if ( aFilterData[nInd].Name == "DocumentService" )
283 aFilterData[nInd].Value >>= aDocServiceName;
286 if ( !aDocServiceName.isEmpty() )
288 // create the model
289 uno::Sequence< uno::Any > aArguments(1);
290 aArguments[0] <<= beans::NamedValue( OUString( "EmbeddedObject" ), uno::makeAny( (sal_Bool)sal_True ));
292 uno::Reference< util::XCloseable > xDocument( m_xFactory->createInstanceWithArguments( aDocServiceName, aArguments ), uno::UNO_QUERY_THROW );
293 uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY_THROW );
294 uno::Reference< document::XStorageBasedDocument > xStorDoc( xDocument, uno::UNO_QUERY_THROW );
296 // let the model behave as embedded one
297 uno::Reference< frame::XModel > xModel( xDocument, uno::UNO_QUERY_THROW );
298 uno::Sequence< beans::PropertyValue > aSeq( 1 );
299 aSeq[0].Name = "SetEmbedded";
300 aSeq[0].Value <<= sal_True;
301 xModel->attachResource( OUString(), aSeq );
303 // load the model from the stream
304 uno::Sequence< beans::PropertyValue > aArgs( 5 );
305 aArgs[0].Name = "HierarchicalDocumentName";
306 aArgs[0].Value <<= m_aEntryName;
307 aArgs[1].Name = "ReadOnly";
308 aArgs[1].Value <<= sal_True;
309 aArgs[2].Name = "FilterName";
310 aArgs[2].Value <<= aFilterName;
311 aArgs[3].Name = "URL";
312 aArgs[3].Value <<= OUString( "private:stream" );
313 aArgs[4].Name = "InputStream";
314 aArgs[4].Value <<= m_xObjectStream->getInputStream();
316 xSeekable->seek( 0 );
317 xLoadable->load( aArgs );
319 // the model is successfully loaded, create a new storage and store the model to the storage
320 uno::Reference< embed::XStorage > xTmpStorage = CreateTemporarySubstorage( aStorageName );
321 xStorDoc->storeToStorage( xTmpStorage, uno::Sequence< beans::PropertyValue >() );
322 xDocument->close( sal_True );
323 uno::Reference< beans::XPropertySet > xStorProps( xTmpStorage, uno::UNO_QUERY_THROW );
324 OUString aMediaType;
325 xStorProps->getPropertyValue("MediaType") >>= aMediaType;
326 xTmpStorage->dispose();
328 // look for the related embedded object factory
329 ::comphelper::MimeConfigurationHelper aConfigHelper( comphelper::getComponentContext(m_xFactory) );
330 OUString aEmbedFactory;
331 if ( !aMediaType.isEmpty() )
332 aEmbedFactory = aConfigHelper.GetFactoryNameByMediaType( aMediaType );
334 if ( aEmbedFactory.isEmpty() )
335 throw uno::RuntimeException();
337 uno::Reference< uno::XInterface > xFact = m_xFactory->createInstance( aEmbedFactory );
339 uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( xFact, uno::UNO_QUERY_THROW );
341 // now the object should be adjusted to become the wrapper
342 nStep = 1;
343 uno::Reference< lang::XComponent > xComp( m_xObjectStream, uno::UNO_QUERY_THROW );
344 xComp->dispose();
345 m_xObjectStream = uno::Reference< io::XStream >();
346 m_nObjectState = -1;
348 nStep = 2;
349 aTmpStreamName = MoveToTemporarySubstream();
351 nStep = 3;
352 m_xParentStorage->renameElement( aStorageName, m_aEntryName );
354 nStep = 4;
355 m_xWrappedObject.set( xEmbCreator->createInstanceInitFromEntry( m_xParentStorage, m_aEntryName, uno::Sequence< beans::PropertyValue >(), uno::Sequence< beans::PropertyValue >() ), uno::UNO_QUERY_THROW );
357 bResult = sal_True; // the change is no more revertable
360 m_xParentStorage->removeElement( aTmpStreamName );
362 catch( const uno::Exception& )
364 // the success of the removing is not so important
369 catch( const uno::Exception& )
371 // repair the object if necessary
372 switch( nStep )
374 case 4:
375 case 3:
376 if ( !aTmpStreamName.isEmpty() && aTmpStreamName != m_aEntryName )
379 if ( m_xParentStorage->hasByName( m_aEntryName ) )
380 m_xParentStorage->removeElement( m_aEntryName );
381 m_xParentStorage->renameElement( aTmpStreamName, m_aEntryName );
383 catch ( const uno::Exception& )
385 try {
386 close( sal_True );
387 } catch( const uno::Exception& ) {}
389 m_xParentStorage->dispose(); // ??? the storage has information loss, it should be closed without commiting!
390 throw uno::RuntimeException(); // the repairing is not possible
392 case 2:
395 m_xObjectStream = m_xParentStorage->openStreamElement( m_aEntryName, m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE );
396 m_nObjectState = embed::EmbedStates::LOADED;
398 catch( const uno::Exception& )
400 try {
401 close( sal_True );
402 } catch( const uno::Exception& ) {}
404 throw uno::RuntimeException(); // the repairing is not possible
406 // no break as designed!
408 case 1:
409 case 0:
410 if ( !aStorageName.isEmpty() )
411 try {
412 m_xParentStorage->removeElement( aStorageName );
413 } catch( const uno::Exception& ) { SAL_WARN( "embeddedobj.ole", "Can not remove temporary storage!" ); }
414 break;
418 if ( bResult )
420 // the conversion was done successfully, now the additional initializations should happen
422 MoveListeners();
423 m_xWrappedObject->setClientSite( m_xClientSite );
424 if ( m_xParent.is() )
426 uno::Reference< container::XChild > xChild( m_xWrappedObject, uno::UNO_QUERY );
427 if ( xChild.is() )
428 xChild->setParent( m_xParent );
433 return bResult;
436 //----------------------------------------------
437 void SAL_CALL OleEmbeddedObject::changeState( sal_Int32 nNewState )
438 throw ( embed::UnreachableStateException,
439 embed::WrongStateException,
440 uno::Exception,
441 uno::RuntimeException )
443 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::changeState" );
445 // begin wrapping related part ====================
446 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
447 if ( xWrappedObject.is() )
449 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
450 xWrappedObject->changeState( nNewState );
451 return;
453 // end wrapping related part ====================
455 ::osl::ResettableMutexGuard aGuard( m_aMutex );
457 if ( m_bDisposed )
458 throw lang::DisposedException(); // TODO
460 if ( m_nObjectState == -1 )
461 throw embed::WrongStateException( OUString( "The object has no persistence!\n" ),
462 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
464 // in case the object is already in requested state
465 if ( m_nObjectState == nNewState )
466 return;
468 #ifdef WNT
469 if ( m_pOleComponent )
471 if ( m_nTargetState != -1 )
473 // means that the object is currently trying to reach the target state
474 throw embed::StateChangeInProgressException( OUString(),
475 uno::Reference< uno::XInterface >(),
476 m_nTargetState );
479 TargetStateControl_Impl aControl( m_nTargetState, nNewState );
481 // TODO: additional verbs can be a problem, since nobody knows how the object
482 // will behave after activation
484 sal_Int32 nOldState = m_nObjectState;
485 aGuard.clear();
486 StateChangeNotification_Impl( sal_True, nOldState, nNewState );
487 aGuard.reset();
491 if ( nNewState == embed::EmbedStates::LOADED )
493 // This means just closing of the current object
494 // If component can not be closed the object stays in loaded state
495 // and it holds reference to "incomplete" component
496 // If the object is switched to running state later
497 // the component will become "complete"
499 // the loaded state must be set before, because of notifications!
500 m_nObjectState = nNewState;
503 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
504 m_pOleComponent->CloseObject();
507 aGuard.clear();
508 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
509 aGuard.reset();
511 else if ( nNewState == embed::EmbedStates::RUNNING || nNewState == embed::EmbedStates::ACTIVE )
513 if ( m_nObjectState == embed::EmbedStates::LOADED )
515 // if the target object is in loaded state and a different state is specified
516 // as a new one the object first must be switched to running state.
518 // the component can exist already in nonrunning state
519 // it can be created during loading to detect type of object
520 CreateOleComponentAndLoad_Impl( m_pOleComponent );
522 SwitchComponentToRunningState_Impl();
523 m_nObjectState = embed::EmbedStates::RUNNING;
524 aGuard.clear();
525 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
526 aGuard.reset();
528 if ( m_pOleComponent && m_bHasSizeToSet )
530 aGuard.clear();
531 try {
532 m_pOleComponent->SetExtent( m_aSizeToSet, m_nAspectToSet );
533 m_bHasSizeToSet = sal_False;
535 catch( const uno::Exception& ) {}
536 aGuard.reset();
539 if ( m_nObjectState == nNewState )
540 return;
543 // so now the object is either switched from Active to Running state or vise versa
544 // the notification about object state change will be done asynchronously
545 if ( m_nObjectState == embed::EmbedStates::RUNNING && nNewState == embed::EmbedStates::ACTIVE )
547 // execute OPEN verb, if object does not reach active state it is an object's problem
548 aGuard.clear();
549 m_pOleComponent->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN );
550 aGuard.reset();
552 // some objects do not allow to set the size even in running state
553 if ( m_pOleComponent && m_bHasSizeToSet )
555 aGuard.clear();
556 try {
557 m_pOleComponent->SetExtent( m_aSizeToSet, m_nAspectToSet );
558 m_bHasSizeToSet = sal_False;
560 catch( uno::Exception& ) {}
561 aGuard.reset();
564 m_nObjectState = nNewState;
566 else if ( m_nObjectState == embed::EmbedStates::ACTIVE && nNewState == embed::EmbedStates::RUNNING )
568 aGuard.clear();
569 m_pOleComponent->CloseObject();
570 m_pOleComponent->RunObject(); // Should not fail, the object already was active
571 aGuard.reset();
572 m_nObjectState = nNewState;
574 else
576 throw embed::UnreachableStateException();
579 else
580 throw embed::UnreachableStateException();
582 catch( uno::Exception& )
584 aGuard.clear();
585 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
586 throw;
589 else
590 #endif
592 throw embed::UnreachableStateException();
596 //----------------------------------------------
597 uno::Sequence< sal_Int32 > SAL_CALL OleEmbeddedObject::getReachableStates()
598 throw ( embed::WrongStateException,
599 uno::RuntimeException )
601 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::getReachableStates" );
603 // begin wrapping related part ====================
604 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
605 if ( xWrappedObject.is() )
607 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
608 return xWrappedObject->getReachableStates();
610 // end wrapping related part ====================
612 ::osl::MutexGuard aGuard( m_aMutex );
613 if ( m_bDisposed )
614 throw lang::DisposedException(); // TODO
616 if ( m_nObjectState == -1 )
617 throw embed::WrongStateException( OUString( "The object has no persistence!\n" ),
618 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
620 #ifdef WNT
621 if ( m_pOleComponent )
623 if ( m_nObjectState == embed::EmbedStates::LOADED )
625 // the list of supported verbs can be retrieved only when object is in running state
626 throw embed::NeedsRunningStateException(); // TODO:
629 // the list of states can only be guessed based on standard verbs,
630 // since there is no way to detect what additional verbs do
631 return GetReachableStatesList_Impl( m_pOleComponent->GetVerbList() );
633 else
634 #endif
636 return uno::Sequence< sal_Int32 >();
640 //----------------------------------------------
641 sal_Int32 SAL_CALL OleEmbeddedObject::getCurrentState()
642 throw ( embed::WrongStateException,
643 uno::RuntimeException )
645 // begin wrapping related part ====================
646 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
647 if ( xWrappedObject.is() )
649 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
650 return xWrappedObject->getCurrentState();
652 // end wrapping related part ====================
654 ::osl::MutexGuard aGuard( m_aMutex );
655 if ( m_bDisposed )
656 throw lang::DisposedException(); // TODO
658 if ( m_nObjectState == -1 )
659 throw embed::WrongStateException( OUString( "The object has no persistence!\n" ),
660 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
662 // TODO: Shouldn't we ask object? ( I guess no )
663 return m_nObjectState;
666 namespace
668 bool lcl_CopyStream(uno::Reference<io::XInputStream> xIn, uno::Reference<io::XOutputStream> xOut)
670 const sal_Int32 nChunkSize = 4096;
671 uno::Sequence< sal_Int8 > aData(nChunkSize);
672 sal_Int32 nTotalRead = 0;
673 sal_Int32 nRead;
676 nRead = xIn->readBytes(aData, nChunkSize);
677 nTotalRead += nRead;
678 xOut->writeBytes(aData);
679 } while (nRead == nChunkSize);
680 return nTotalRead != 0;
683 //Dump the objects content to a tempfile, just the "CONTENTS" stream if
684 //there is one for non-compound documents, otherwise the whole content.
685 //On success a file is returned which must be removed by the caller
686 OUString lcl_ExtractObject(::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory,
687 ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > xObjectStream)
689 OUString sUrl;
691 // the solution is only active for Unix systems
692 #ifndef WNT
693 uno::Reference <beans::XPropertySet> xNativeTempFile(
694 io::TempFile::create(comphelper::getComponentContext(xFactory)),
695 uno::UNO_QUERY_THROW);
696 uno::Reference < io::XStream > xStream(xNativeTempFile, uno::UNO_QUERY_THROW);
698 uno::Sequence< uno::Any > aArgs( 2 );
699 aArgs[0] <<= xObjectStream;
700 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
701 uno::Reference< container::XNameContainer > xNameContainer(
702 xFactory->createInstanceWithArguments(
703 OUString("com.sun.star.embed.OLESimpleStorage"),
704 aArgs ), uno::UNO_QUERY_THROW );
706 uno::Reference< io::XStream > xCONTENTS;
709 xNameContainer->getByName("CONTENTS") >>= xCONTENTS;
711 catch (container::NoSuchElementException const&)
713 // ignore
716 sal_Bool bCopied = xCONTENTS.is() && lcl_CopyStream(xCONTENTS->getInputStream(), xStream->getOutputStream());
718 uno::Reference< io::XSeekable > xSeekableStor(xObjectStream, uno::UNO_QUERY);
719 if (xSeekableStor.is())
720 xSeekableStor->seek(0);
722 if (!bCopied)
723 bCopied = lcl_CopyStream(xObjectStream->getInputStream(), xStream->getOutputStream());
725 if (bCopied)
727 xNativeTempFile->setPropertyValue("RemoveFile",
728 uno::makeAny(sal_False));
729 uno::Any aUrl = xNativeTempFile->getPropertyValue("Uri");
730 aUrl >>= sUrl;
732 xNativeTempFile = uno::Reference<beans::XPropertySet>();
734 uno::Reference < ucb::XSimpleFileAccess3 > xSimpleFileAccess(
735 ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory) ) );
737 xSimpleFileAccess->setReadOnly(sUrl, sal_True);
739 else
741 xNativeTempFile->setPropertyValue("RemoveFile",
742 uno::makeAny(sal_True));
744 #else
745 (void) xFactory;
746 (void) xObjectStream;
747 #endif
748 return sUrl;
752 //----------------------------------------------
753 void SAL_CALL OleEmbeddedObject::doVerb( sal_Int32 nVerbID )
754 throw ( lang::IllegalArgumentException,
755 embed::WrongStateException,
756 embed::UnreachableStateException,
757 uno::Exception,
758 uno::RuntimeException )
760 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::doVerb" );
762 // begin wrapping related part ====================
763 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
764 if ( xWrappedObject.is() )
766 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
767 xWrappedObject->doVerb( nVerbID );
768 return;
770 // end wrapping related part ====================
772 ::osl::ResettableMutexGuard aGuard( m_aMutex );
773 if ( m_bDisposed )
774 throw lang::DisposedException(); // TODO
776 if ( m_nObjectState == -1 )
777 throw embed::WrongStateException( OUString( "The object has no persistence!\n" ),
778 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
780 #ifdef WNT
781 if ( m_pOleComponent )
783 sal_Int32 nOldState = m_nObjectState;
785 // TODO/LATER detect target state here and do a notification
786 // StateChangeNotification_Impl( sal_True, nOldState, nNewState );
787 if ( m_nObjectState == embed::EmbedStates::LOADED )
789 // if the target object is in loaded state
790 // it must be switched to running state to execute verb
791 aGuard.clear();
792 changeState( embed::EmbedStates::RUNNING );
793 aGuard.reset();
796 try {
797 if ( !m_pOleComponent )
798 throw uno::RuntimeException();
800 // ==== the STAMPIT related solution =============================
801 m_aVerbExecutionController.StartControlExecution();
802 // ===============================================================
804 m_pOleComponent->ExecuteVerb( nVerbID );
806 // ==== the STAMPIT related solution =============================
807 sal_Bool bModifiedOnExecution = m_aVerbExecutionController.EndControlExecution_WasModified();
809 // this workaround is implemented for STAMPIT object
810 // if object was modified during verb execution it is saved here
811 if ( bModifiedOnExecution && m_pOleComponent->IsDirty() )
812 SaveObject_Impl();
813 // ===============================================================
815 catch( uno::Exception& )
817 // ==== the STAMPIT related solution =============================
818 m_aVerbExecutionController.EndControlExecution_WasModified();
819 // ===============================================================
821 aGuard.clear();
822 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
823 throw;
827 else
828 #endif
830 if ( nVerbID == -9 )
832 // the workaround verb to show the object in case no server is available
834 // if it is possible, the object will be converted to OOo format
835 if ( !m_bTriedConversion )
837 m_bTriedConversion = sal_True;
838 if ( TryToConvertToOOo() )
840 changeState( embed::EmbedStates::UI_ACTIVE );
841 return;
845 if ( !m_pOwnView && m_xObjectStream.is() )
847 try {
848 uno::Reference< io::XSeekable > xSeekable( m_xObjectStream, uno::UNO_QUERY );
849 if ( xSeekable.is() )
850 xSeekable->seek( 0 );
852 m_pOwnView = new OwnView_Impl( m_xFactory, m_xObjectStream->getInputStream() );
853 m_pOwnView->acquire();
855 catch( uno::RuntimeException& )
857 throw;
859 catch (uno::Exception const& e)
861 SAL_WARN("embeddedobj.ole", "OleEmbeddedObject::doVerb: "
862 "-9 fallback path: exception caught: " << e.Message);
866 if ( !m_pOwnView || !m_pOwnView->Open() )
868 //Make a RO copy and see if the OS can find something to at
869 //least display the content for us
870 if (m_aTempDumpURL.isEmpty())
871 m_aTempDumpURL = lcl_ExtractObject(m_xFactory, m_xObjectStream);
873 if (!m_aTempDumpURL.isEmpty())
875 uno::Reference< ::com::sun::star::system::XSystemShellExecute > xSystemShellExecute(
876 ::com::sun::star::system::SystemShellExecute::create(comphelper::getComponentContext(m_xFactory)) );
877 xSystemShellExecute->execute(m_aTempDumpURL, OUString(), ::com::sun::star::system::SystemShellExecuteFlags::URIS_ONLY);
879 else
880 throw embed::UnreachableStateException();
883 else
886 throw embed::UnreachableStateException();
891 //----------------------------------------------
892 uno::Sequence< embed::VerbDescriptor > SAL_CALL OleEmbeddedObject::getSupportedVerbs()
893 throw ( embed::WrongStateException,
894 uno::RuntimeException )
896 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::getSupportedVerb" );
898 // begin wrapping related part ====================
899 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
900 if ( xWrappedObject.is() )
902 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
903 return xWrappedObject->getSupportedVerbs();
905 // end wrapping related part ====================
907 ::osl::MutexGuard aGuard( m_aMutex );
908 if ( m_bDisposed )
909 throw lang::DisposedException(); // TODO
911 if ( m_nObjectState == -1 )
912 throw embed::WrongStateException( OUString( "The object has no persistence!\n" ),
913 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
914 #ifdef WNT
915 if ( m_pOleComponent )
917 // registry could be used in this case
918 // if ( m_nObjectState == embed::EmbedStates::LOADED )
919 // {
920 // // the list of supported verbs can be retrieved only when object is in running state
921 // throw embed::NeedsRunningStateException(); // TODO:
922 // }
924 return m_pOleComponent->GetVerbList();
926 else
927 #endif
929 return uno::Sequence< embed::VerbDescriptor >();
933 //----------------------------------------------
934 void SAL_CALL OleEmbeddedObject::setClientSite(
935 const uno::Reference< embed::XEmbeddedClient >& xClient )
936 throw ( embed::WrongStateException,
937 uno::RuntimeException )
939 // begin wrapping related part ====================
940 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
941 if ( xWrappedObject.is() )
943 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
944 xWrappedObject->setClientSite( xClient );
945 return;
947 // end wrapping related part ====================
949 ::osl::MutexGuard aGuard( m_aMutex );
950 if ( m_bDisposed )
951 throw lang::DisposedException(); // TODO
953 if ( m_xClientSite != xClient)
955 if ( m_nObjectState != embed::EmbedStates::LOADED && m_nObjectState != embed::EmbedStates::RUNNING )
956 throw embed::WrongStateException(
957 OUString( "The client site can not be set currently!\n" ),
958 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
960 m_xClientSite = xClient;
964 //----------------------------------------------
965 uno::Reference< embed::XEmbeddedClient > SAL_CALL OleEmbeddedObject::getClientSite()
966 throw ( embed::WrongStateException,
967 uno::RuntimeException )
969 // begin wrapping related part ====================
970 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
971 if ( xWrappedObject.is() )
973 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
974 return xWrappedObject->getClientSite();
976 // end wrapping related part ====================
978 ::osl::MutexGuard aGuard( m_aMutex );
979 if ( m_bDisposed )
980 throw lang::DisposedException(); // TODO
982 if ( m_nObjectState == -1 )
983 throw embed::WrongStateException( OUString( "The object has no persistence!\n" ),
984 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
986 return m_xClientSite;
989 //----------------------------------------------
990 void SAL_CALL OleEmbeddedObject::update()
991 throw ( embed::WrongStateException,
992 uno::Exception,
993 uno::RuntimeException )
995 // begin wrapping related part ====================
996 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
997 if ( xWrappedObject.is() )
999 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1000 xWrappedObject->update();
1001 return;
1003 // end wrapping related part ====================
1005 ::osl::MutexGuard aGuard( m_aMutex );
1006 if ( m_bDisposed )
1007 throw lang::DisposedException(); // TODO
1009 if ( m_nObjectState == -1 )
1010 throw embed::WrongStateException( OUString( "The object has no persistence!\n" ),
1011 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1013 if ( m_nUpdateMode == embed::EmbedUpdateModes::EXPLICIT_UPDATE )
1015 // TODO: update view representation
1017 else
1019 // the object must be up to date
1020 SAL_WARN_IF( m_nUpdateMode != embed::EmbedUpdateModes::ALWAYS_UPDATE, "embeddedobj.ole", "Unknown update mode!" );
1024 //----------------------------------------------
1025 void SAL_CALL OleEmbeddedObject::setUpdateMode( sal_Int32 nMode )
1026 throw ( embed::WrongStateException,
1027 uno::RuntimeException )
1029 // begin wrapping related part ====================
1030 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
1031 if ( xWrappedObject.is() )
1033 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1034 xWrappedObject->setUpdateMode( nMode );
1035 return;
1037 // end wrapping related part ====================
1039 ::osl::MutexGuard aGuard( m_aMutex );
1040 if ( m_bDisposed )
1041 throw lang::DisposedException(); // TODO
1043 if ( m_nObjectState == -1 )
1044 throw embed::WrongStateException( OUString( "The object has no persistence!\n" ),
1045 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1047 OSL_ENSURE( nMode == embed::EmbedUpdateModes::ALWAYS_UPDATE
1048 || nMode == embed::EmbedUpdateModes::EXPLICIT_UPDATE,
1049 "Unknown update mode!\n" );
1050 m_nUpdateMode = nMode;
1053 //----------------------------------------------
1054 sal_Int64 SAL_CALL OleEmbeddedObject::getStatus( sal_Int64
1055 nAspect
1057 throw ( embed::WrongStateException,
1058 uno::RuntimeException )
1060 // begin wrapping related part ====================
1061 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
1062 if ( xWrappedObject.is() )
1064 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1065 return xWrappedObject->getStatus( nAspect );
1067 // end wrapping related part ====================
1069 ::osl::MutexGuard aGuard( m_aMutex );
1070 if ( m_bDisposed )
1071 throw lang::DisposedException(); // TODO
1073 if ( m_nObjectState == -1 )
1074 throw embed::WrongStateException( OUString( "The object must be in running state!\n" ),
1075 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1077 sal_Int64 nResult = 0;
1079 #ifdef WNT
1080 if ( m_bGotStatus && m_nStatusAspect == nAspect )
1081 nResult = m_nStatus;
1082 else if ( m_pOleComponent )
1085 m_nStatus = m_pOleComponent->GetMiscStatus( nAspect );
1086 m_nStatusAspect = nAspect;
1087 m_bGotStatus = sal_True;
1088 nResult = m_nStatus;
1090 #endif
1092 // this implementation needs size to be provided after object loading/creating to work in optimal way
1093 return ( nResult | embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD );
1096 //----------------------------------------------
1097 void SAL_CALL OleEmbeddedObject::setContainerName( const OUString& sName )
1098 throw ( uno::RuntimeException )
1100 // begin wrapping related part ====================
1101 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
1102 if ( xWrappedObject.is() )
1104 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1105 xWrappedObject->setContainerName( sName );
1106 return;
1108 // end wrapping related part ====================
1110 ::osl::MutexGuard aGuard( m_aMutex );
1111 if ( m_bDisposed )
1112 throw lang::DisposedException(); // TODO
1114 m_aContainerName = sName;
1118 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */