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 <commonembobj.hxx>
21 #include <com/sun/star/embed/Aspects.hpp>
22 #include <com/sun/star/document/XStorageBasedDocument.hpp>
23 #include <com/sun/star/embed/EmbedStates.hpp>
24 #include <com/sun/star/embed/EntryInitModes.hpp>
25 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
26 #include <com/sun/star/embed/WrongStateException.hpp>
27 #include <com/sun/star/embed/XStorage.hpp>
28 #include <com/sun/star/embed/XOptimizedStorage.hpp>
29 #include <com/sun/star/embed/ElementModes.hpp>
30 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
31 #include <com/sun/star/embed/StorageFactory.hpp>
32 #include <com/sun/star/io/IOException.hpp>
33 #include <com/sun/star/io/TempFile.hpp>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/frame/XStorable.hpp>
36 #include <com/sun/star/frame/XLoadable.hpp>
37 #include <com/sun/star/frame/XModule.hpp>
38 #include <com/sun/star/lang/NoSupportException.hpp>
39 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
40 #include <com/sun/star/lang/DisposedException.hpp>
41 #include <com/sun/star/util/XModifiable.hpp>
43 #include <com/sun/star/container/XNameAccess.hpp>
44 #include <com/sun/star/container/XChild.hpp>
45 #include <com/sun/star/util/XCloseable.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/beans/IllegalTypeException.hpp>
48 #include <com/sun/star/chart2/XChartDocument.hpp>
50 #include <comphelper/fileformat.h>
51 #include <comphelper/storagehelper.hxx>
52 #include <comphelper/mimeconfighelper.hxx>
53 #include <comphelper/namedvaluecollection.hxx>
55 #include <tools/diagnose_ex.h>
56 #include <sal/log.hxx>
57 #include <unotools/configmgr.hxx>
58 #include "persistence.hxx"
60 using namespace ::com::sun::star
;
63 uno::Sequence
< beans::PropertyValue
> GetValuableArgs_Impl( const uno::Sequence
< beans::PropertyValue
>& aMedDescr
,
64 bool bCanUseDocumentBaseURL
)
66 uno::Sequence
< beans::PropertyValue
> aResult
;
67 sal_Int32 nResLen
= 0;
69 for ( sal_Int32 nInd
= 0; nInd
< aMedDescr
.getLength(); nInd
++ )
71 if ( aMedDescr
[nInd
].Name
== "ComponentData" || aMedDescr
[nInd
].Name
== "DocumentTitle"
72 || aMedDescr
[nInd
].Name
== "InteractionHandler" || aMedDescr
[nInd
].Name
== "JumpMark"
73 // || aMedDescr[nInd].Name == "Password" // makes no sense for embedded objects
74 || aMedDescr
[nInd
].Name
== "Preview" || aMedDescr
[nInd
].Name
== "ReadOnly"
75 || aMedDescr
[nInd
].Name
== "StartPresentation" || aMedDescr
[nInd
].Name
== "RepairPackage"
76 || aMedDescr
[nInd
].Name
== "StatusIndicator" || aMedDescr
[nInd
].Name
== "ViewData"
77 || aMedDescr
[nInd
].Name
== "ViewId" || aMedDescr
[nInd
].Name
== "MacroExecutionMode"
78 || aMedDescr
[nInd
].Name
== "UpdateDocMode"
79 || (aMedDescr
[nInd
].Name
== "DocumentBaseURL" && bCanUseDocumentBaseURL
) )
81 aResult
.realloc( ++nResLen
);
82 aResult
[nResLen
-1] = aMedDescr
[nInd
];
90 static uno::Sequence
< beans::PropertyValue
> addAsTemplate( const uno::Sequence
< beans::PropertyValue
>& aOrig
)
92 bool bAsTemplateSet
= false;
93 sal_Int32 nLength
= aOrig
.getLength();
94 uno::Sequence
< beans::PropertyValue
> aResult( nLength
);
96 for ( sal_Int32 nInd
= 0; nInd
< nLength
; nInd
++ )
98 aResult
[nInd
].Name
= aOrig
[nInd
].Name
;
99 if ( aResult
[nInd
].Name
== "AsTemplate" )
101 aResult
[nInd
].Value
<<= true;
102 bAsTemplateSet
= true;
105 aResult
[nInd
].Value
= aOrig
[nInd
].Value
;
108 if ( !bAsTemplateSet
)
110 aResult
.realloc( nLength
+ 1 );
111 aResult
[nLength
].Name
= "AsTemplate";
112 aResult
[nLength
].Value
<<= true;
119 static uno::Reference
< io::XInputStream
> createTempInpStreamFromStor(
120 const uno::Reference
< embed::XStorage
>& xStorage
,
121 const uno::Reference
< uno::XComponentContext
>& xContext
)
123 SAL_WARN_IF( !xStorage
.is(), "embeddedobj.common", "The storage can not be empty!" );
125 uno::Reference
< io::XInputStream
> xResult
;
127 uno::Reference
< io::XStream
> xTempStream( io::TempFile::create(xContext
), uno::UNO_QUERY_THROW
);
129 uno::Reference
< lang::XSingleServiceFactory
> xStorageFactory( embed::StorageFactory::create(xContext
) );
131 uno::Sequence
< uno::Any
> aArgs( 2 );
132 aArgs
[0] <<= xTempStream
;
133 aArgs
[1] <<= embed::ElementModes::READWRITE
;
134 uno::Reference
< embed::XStorage
> xTempStorage( xStorageFactory
->createInstanceWithArguments( aArgs
),
135 uno::UNO_QUERY_THROW
);
139 xStorage
->copyToStorage( xTempStorage
);
140 } catch( const uno::Exception
& )
142 css::uno::Any anyEx
= cppu::getCaughtException();
143 throw embed::StorageWrappedTargetException(
144 "Can't copy storage!",
145 uno::Reference
< uno::XInterface
>(),
150 if ( xTempStorage
.is() )
151 xTempStorage
->dispose();
153 catch ( const uno::Exception
& )
158 uno::Reference
< io::XOutputStream
> xTempOut
= xTempStream
->getOutputStream();
160 xTempOut
->closeOutput();
162 catch ( const uno::Exception
& )
166 xResult
= xTempStream
->getInputStream();
173 static void TransferMediaType( const uno::Reference
< embed::XStorage
>& i_rSource
, const uno::Reference
< embed::XStorage
>& i_rTarget
)
177 const uno::Reference
< beans::XPropertySet
> xSourceProps( i_rSource
, uno::UNO_QUERY_THROW
);
178 const uno::Reference
< beans::XPropertySet
> xTargetProps( i_rTarget
, uno::UNO_QUERY_THROW
);
179 const OUString
sMediaTypePropName( "MediaType" );
180 xTargetProps
->setPropertyValue( sMediaTypePropName
, xSourceProps
->getPropertyValue( sMediaTypePropName
) );
182 catch( const uno::Exception
& )
184 DBG_UNHANDLED_EXCEPTION("embeddedobj.common");
189 static uno::Reference
< util::XCloseable
> CreateDocument( const uno::Reference
< uno::XComponentContext
>& _rxContext
,
190 const OUString
& _rDocumentServiceName
, bool _bEmbeddedScriptSupport
, const bool i_bDocumentRecoverySupport
)
192 ::comphelper::NamedValueCollection aArguments
;
193 aArguments
.put( "EmbeddedObject", true );
194 aArguments
.put( "EmbeddedScriptSupport", _bEmbeddedScriptSupport
);
195 aArguments
.put( "DocumentRecoverySupport", i_bDocumentRecoverySupport
);
197 uno::Reference
< uno::XInterface
> xDocument
;
200 xDocument
= _rxContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
201 _rDocumentServiceName
, aArguments
.getWrappedPropertyValues(), _rxContext
);
203 catch( const uno::Exception
& )
205 // if an embedded object implementation does not support XInitialization,
206 // the default factory from cppuhelper will throw an
207 // IllegalArgumentException when we try to create the instance with arguments.
208 // Okay, so we fall back to creating the instance without any arguments.
209 OSL_FAIL("Consider implementing interface XInitialization to avoid duplicate construction");
210 xDocument
= _rxContext
->getServiceManager()->createInstanceWithContext( _rDocumentServiceName
, _rxContext
);
213 SAL_WARN_IF(!xDocument
.is(), "embeddedobj.common", "Service " << _rDocumentServiceName
<< " is not available?");
214 return uno::Reference
< util::XCloseable
>( xDocument
, uno::UNO_QUERY
);
218 static void SetDocToEmbedded( const uno::Reference
< frame::XModel
>& rDocument
, const OUString
& aModuleName
)
222 uno::Sequence
< beans::PropertyValue
> aSeq( 1 );
223 aSeq
[0].Name
= "SetEmbedded";
224 aSeq
[0].Value
<<= true;
225 rDocument
->attachResource( OUString(), aSeq
);
227 if ( !aModuleName
.isEmpty() )
231 uno::Reference
< frame::XModule
> xModule( rDocument
, uno::UNO_QUERY_THROW
);
232 xModule
->setIdentifier( aModuleName
);
234 catch( const uno::Exception
& )
241 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference
< embed::XStorage
>& xNewParentStorage
,
242 const uno::Reference
< embed::XStorage
>& xNewObjectStorage
,
243 const OUString
& aNewName
)
245 if ( xNewParentStorage
== m_xParentStorage
&& aNewName
== m_aEntryName
)
247 SAL_WARN_IF( xNewObjectStorage
!= m_xObjectStorage
, "embeddedobj.common", "The storage must be the same!" );
251 auto xOldObjectStorage
= m_xObjectStorage
;
252 m_xObjectStorage
= xNewObjectStorage
;
253 m_xParentStorage
= xNewParentStorage
;
254 m_aEntryName
= aNewName
;
256 // the linked document should not be switched
259 uno::Reference
< document::XStorageBasedDocument
> xDoc( m_xDocHolder
->GetComponent(), uno::UNO_QUERY
);
261 SwitchDocToStorage_Impl( xDoc
, m_xObjectStorage
);
265 if ( xOldObjectStorage
.is() )
266 xOldObjectStorage
->dispose();
268 catch ( const uno::Exception
& )
274 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference
< embed::XStorage
>& xNewParentStorage
,
275 const OUString
& aNewName
)
277 if ( xNewParentStorage
== m_xParentStorage
&& aNewName
== m_aEntryName
)
280 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
282 uno::Reference
< embed::XStorage
> xNewOwnStorage
= xNewParentStorage
->openStorageElement( aNewName
, nStorageMode
);
283 SAL_WARN_IF( !xNewOwnStorage
.is(), "embeddedobj.common", "The method can not return empty reference!" );
285 SwitchOwnPersistence( xNewParentStorage
, xNewOwnStorage
, aNewName
);
289 void OCommonEmbeddedObject::EmbedAndReparentDoc_Impl( const uno::Reference
< util::XCloseable
>& i_rxDocument
) const
291 SetDocToEmbedded( uno::Reference
< frame::XModel
>( i_rxDocument
, uno::UNO_QUERY
), m_aModuleName
);
295 uno::Reference
< container::XChild
> xChild( i_rxDocument
, uno::UNO_QUERY
);
297 xChild
->setParent( m_xParent
);
299 catch( const lang::NoSupportException
& )
301 SAL_WARN( "embeddedobj.common", "OCommonEmbeddedObject::EmbedAndReparentDoc: cannot set parent at document!" );
306 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::InitNewDocument_Impl()
308 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
309 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
311 uno::Reference
< frame::XModel
> xModel( xDocument
, uno::UNO_QUERY
);
312 uno::Reference
< frame::XLoadable
> xLoadable( xModel
, uno::UNO_QUERY_THROW
);
316 // set the document mode to embedded as the first action on document!!!
317 EmbedAndReparentDoc_Impl( xDocument
);
319 // if we have a storage to recover the document from, do not use initNew, but instead load from that storage
320 bool bInitNew
= true;
321 if ( m_xRecoveryStorage
.is() )
323 uno::Reference
< document::XStorageBasedDocument
> xDoc( xLoadable
, uno::UNO_QUERY
);
324 SAL_WARN_IF( !xDoc
.is(), "embeddedobj.common", "OCommonEmbeddedObject::InitNewDocument_Impl: cannot recover from a storage when the document is not storage based!" );
327 ::comphelper::NamedValueCollection aLoadArgs
;
328 FillDefaultLoadArgs_Impl( m_xRecoveryStorage
, aLoadArgs
);
330 xDoc
->loadFromStorage( m_xRecoveryStorage
, aLoadArgs
.getPropertyValues() );
331 SwitchDocToStorage_Impl( xDoc
, m_xObjectStorage
);
338 // init document as a new
339 xLoadable
->initNew();
341 xModel
->attachResource( xModel
->getURL(), m_aDocMediaDescriptor
);
343 catch( const uno::Exception
& )
345 if ( xDocument
.is() )
349 xDocument
->close( true );
351 catch( const uno::Exception
& )
363 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::LoadLink_Impl()
365 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
366 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
368 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY_THROW
);
371 uno::Sequence
< beans::PropertyValue
> aArgs( nLen
);
372 aArgs
[0].Name
= "URL";
373 aArgs
[0].Value
<<= m_aLinkURL
;
374 aArgs
[1].Name
= "FilterName";
375 aArgs
[1].Value
<<= m_aLinkFilterName
;
376 if ( m_bLinkHasPassword
)
378 aArgs
.realloc( ++nLen
);
379 aArgs
[nLen
-1].Name
= "Password";
380 aArgs
[nLen
-1].Value
<<= m_aLinkPassword
;
383 aArgs
.realloc( m_aDocMediaDescriptor
.getLength() + nLen
);
384 for ( sal_Int32 nInd
= 0; nInd
< m_aDocMediaDescriptor
.getLength(); nInd
++ )
386 aArgs
[nInd
+nLen
].Name
= m_aDocMediaDescriptor
[nInd
].Name
;
387 aArgs
[nInd
+nLen
].Value
= m_aDocMediaDescriptor
[nInd
].Value
;
392 // the document is not really an embedded one, it is a link
393 EmbedAndReparentDoc_Impl( xDocument
);
396 xLoadable
->load( aArgs
);
398 if ( !m_bLinkHasPassword
)
400 // check if there is a password to cache
401 uno::Reference
< frame::XModel
> xModel( xLoadable
, uno::UNO_QUERY_THROW
);
402 uno::Sequence
< beans::PropertyValue
> aProps
= xModel
->getArgs();
403 for ( sal_Int32 nInd
= 0; nInd
< aProps
.getLength(); nInd
++ )
404 if ( aProps
[nInd
].Name
== "Password" && ( aProps
[nInd
].Value
>>= m_aLinkPassword
) )
406 m_bLinkHasPassword
= true;
411 catch( const uno::Exception
& )
413 if ( xDocument
.is() )
417 xDocument
->close( true );
419 catch( const uno::Exception
& )
432 OUString
OCommonEmbeddedObject::GetFilterName( sal_Int32 nVersion
) const
434 OUString aFilterName
= GetPresetFilterName();
435 if ( aFilterName
.isEmpty() )
437 OUString sDocumentServiceName
= GetDocumentServiceName();
438 if (utl::ConfigManager::IsFuzzing() && nVersion
== SOFFICE_FILEFORMAT_CURRENT
&&
439 sDocumentServiceName
== "com.sun.star.chart2.ChartDocument")
444 ::comphelper::MimeConfigurationHelper
aHelper( m_xContext
);
445 aFilterName
= aHelper
.GetDefaultFilterFromServiceName(sDocumentServiceName
, nVersion
);
447 // If no filter is found, fall back to the FileFormatVersion=6200 filter, Base only has that.
448 if (aFilterName
.isEmpty() && nVersion
== SOFFICE_FILEFORMAT_CURRENT
)
449 aFilterName
= aHelper
.GetDefaultFilterFromServiceName(GetDocumentServiceName(), SOFFICE_FILEFORMAT_60
);
450 } catch( const uno::Exception
& )
458 void OCommonEmbeddedObject::FillDefaultLoadArgs_Impl( const uno::Reference
< embed::XStorage
>& i_rxStorage
,
459 ::comphelper::NamedValueCollection
& o_rLoadArgs
) const
461 o_rLoadArgs
.put( "DocumentBaseURL", GetBaseURL_Impl() );
462 o_rLoadArgs
.put( "HierarchicalDocumentName", m_aEntryName
);
463 o_rLoadArgs
.put( "ReadOnly", m_bReadOnly
);
465 OUString aFilterName
= GetFilterName( ::comphelper::OStorageHelper::GetXStorageFormat( i_rxStorage
) );
466 SAL_WARN_IF( aFilterName
.isEmpty(), "embeddedobj.common", "OCommonEmbeddedObject::FillDefaultLoadArgs_Impl: Wrong document service name!" );
467 if ( aFilterName
.isEmpty() )
468 throw io::IOException(); // TODO: error message/code
470 o_rLoadArgs
.put( "FilterName", aFilterName
);
474 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::LoadDocumentFromStorage_Impl()
476 ENSURE_OR_THROW( m_xObjectStorage
.is(), "no object storage" );
478 const uno::Reference
< embed::XStorage
> xSourceStorage( m_xRecoveryStorage
.is() ? m_xRecoveryStorage
: m_xObjectStorage
);
480 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
481 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
483 //#i103460# ODF: take the size given from the parent frame as default
484 uno::Reference
< chart2::XChartDocument
> xChart( xDocument
, uno::UNO_QUERY
);
487 uno::Reference
< embed::XVisualObject
> xChartVisualObject( xChart
, uno::UNO_QUERY
);
488 if( xChartVisualObject
.is() )
489 xChartVisualObject
->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT
, m_aDefaultSizeForChart_In_100TH_MM
);
492 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY
);
493 uno::Reference
< document::XStorageBasedDocument
> xDoc( xDocument
, uno::UNO_QUERY
);
494 if ( !xDoc
.is() && !xLoadable
.is() )
495 throw uno::RuntimeException();
497 ::comphelper::NamedValueCollection aLoadArgs
;
498 FillDefaultLoadArgs_Impl( xSourceStorage
, aLoadArgs
);
500 uno::Reference
< io::XInputStream
> xTempInpStream
;
503 xTempInpStream
= createTempInpStreamFromStor( xSourceStorage
, m_xContext
);
504 if ( !xTempInpStream
.is() )
505 throw uno::RuntimeException();
507 OUString aTempFileURL
;
510 // no need to let the file stay after the stream is removed since the embedded document
511 // can not be stored directly
512 uno::Reference
< beans::XPropertySet
> xTempStreamProps( xTempInpStream
, uno::UNO_QUERY_THROW
);
513 xTempStreamProps
->getPropertyValue("Uri") >>= aTempFileURL
;
515 catch( const uno::Exception
& )
519 SAL_WARN_IF( aTempFileURL
.isEmpty(), "embeddedobj.common", "Couldn't retrieve temporary file URL!" );
521 aLoadArgs
.put( "URL", aTempFileURL
);
522 aLoadArgs
.put( "InputStream", xTempInpStream
);
526 aLoadArgs
.merge( m_aDocMediaDescriptor
, true );
530 // set the document mode to embedded as the first step!!!
531 EmbedAndReparentDoc_Impl( xDocument
);
535 xDoc
->loadFromStorage( xSourceStorage
, aLoadArgs
.getPropertyValues() );
536 if ( xSourceStorage
!= m_xObjectStorage
)
537 SwitchDocToStorage_Impl( xDoc
, m_xObjectStorage
);
540 xLoadable
->load( aLoadArgs
.getPropertyValues() );
542 catch( const uno::Exception
& )
544 if ( xDocument
.is() )
548 xDocument
->close( true );
550 catch( const uno::Exception
& )
552 DBG_UNHANDLED_EXCEPTION("embeddedobj.common");
563 uno::Reference
< io::XInputStream
> OCommonEmbeddedObject::StoreDocumentToTempStream_Impl(
564 sal_Int32 nStorageFormat
,
565 const OUString
& aBaseURL
,
566 const OUString
& aHierarchName
)
568 uno::Reference
< io::XOutputStream
> xTempOut(
569 io::TempFile::create(m_xContext
),
570 uno::UNO_QUERY_THROW
);
571 uno::Reference
< io::XInputStream
> aResult( xTempOut
, uno::UNO_QUERY_THROW
);
573 uno::Reference
< frame::XStorable
> xStorable
;
575 osl::MutexGuard
aGuard( m_aMutex
);
576 if ( m_xDocHolder
.is() )
577 xStorable
.set( m_xDocHolder
->GetComponent(), uno::UNO_QUERY
);
580 if( !xStorable
.is() )
581 throw uno::RuntimeException(); // TODO:
583 OUString aFilterName
= GetFilterName( nStorageFormat
);
585 SAL_WARN_IF( aFilterName
.isEmpty(), "embeddedobj.common", "Wrong document service name!" );
586 if ( aFilterName
.isEmpty() )
587 throw io::IOException(); // TODO:
589 uno::Sequence
< beans::PropertyValue
> aArgs( 4 );
590 aArgs
[0].Name
= "FilterName";
591 aArgs
[0].Value
<<= aFilterName
;
592 aArgs
[1].Name
= "OutputStream";
593 aArgs
[1].Value
<<= xTempOut
;
594 aArgs
[2].Name
= "DocumentBaseURL";
595 aArgs
[2].Value
<<= aBaseURL
;
596 aArgs
[3].Name
= "HierarchicalDocumentName";
597 aArgs
[3].Value
<<= aHierarchName
;
599 xStorable
->storeToURL( "private:stream", aArgs
);
602 xTempOut
->closeOutput();
604 catch( const uno::Exception
& )
606 SAL_WARN( "embeddedobj.common", "Looks like stream was closed already" );
613 void OCommonEmbeddedObject::SaveObject_Impl()
615 if ( m_xClientSite
.is() )
619 // check whether the component is modified,
620 // if not there is no need for storing
621 uno::Reference
< util::XModifiable
> xModifiable( m_xDocHolder
->GetComponent(), uno::UNO_QUERY
);
622 if ( xModifiable
.is() && !xModifiable
->isModified() )
625 catch( const uno::Exception
& )
629 m_xClientSite
->saveObject();
631 catch( const uno::Exception
& )
633 SAL_WARN( "embeddedobj.common", "The object was not stored!" );
639 OUString
OCommonEmbeddedObject::GetBaseURL_Impl() const
644 if ( m_xClientSite
.is() )
648 uno::Reference
< frame::XModel
> xParentModel( m_xClientSite
->getComponent(), uno::UNO_QUERY_THROW
);
649 uno::Sequence
< beans::PropertyValue
> aModelProps
= xParentModel
->getArgs();
650 for ( nInd
= 0; nInd
< aModelProps
.getLength(); nInd
++ )
651 if ( aModelProps
[nInd
].Name
== "DocumentBaseURL" )
653 aModelProps
[nInd
].Value
>>= aBaseURL
;
659 catch( const uno::Exception
& )
663 if ( aBaseURL
.isEmpty() )
665 for ( nInd
= 0; nInd
< m_aDocMediaDescriptor
.getLength(); nInd
++ )
666 if ( m_aDocMediaDescriptor
[nInd
].Name
== "DocumentBaseURL" )
668 m_aDocMediaDescriptor
[nInd
].Value
>>= aBaseURL
;
673 if ( aBaseURL
.isEmpty() )
674 aBaseURL
= m_aDefaultParentBaseURL
;
680 OUString
OCommonEmbeddedObject::GetBaseURLFrom_Impl(
681 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
682 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
687 for ( nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
688 if ( lArguments
[nInd
].Name
== "DocumentBaseURL" )
690 lArguments
[nInd
].Value
>>= aBaseURL
;
694 if ( aBaseURL
.isEmpty() )
696 for ( nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
697 if ( lObjArgs
[nInd
].Name
== "DefaultParentBaseURL" )
699 lObjArgs
[nInd
].Value
>>= aBaseURL
;
708 void OCommonEmbeddedObject::SwitchDocToStorage_Impl( const uno::Reference
< document::XStorageBasedDocument
>& xDoc
, const uno::Reference
< embed::XStorage
>& xStorage
)
710 xDoc
->switchToStorage( xStorage
);
712 uno::Reference
< util::XModifiable
> xModif( xDoc
, uno::UNO_QUERY
);
714 xModif
->setModified( false );
716 if ( m_xRecoveryStorage
.is() )
717 m_xRecoveryStorage
.clear();
722 OUString
getStringPropertyValue( const uno::Sequence
<beans::PropertyValue
>& rProps
, const OUString
& rName
)
726 for (sal_Int32 i
= 0; i
< rProps
.getLength(); ++i
)
728 if (rProps
[i
].Name
== rName
)
730 rProps
[i
].Value
>>= aStr
;
740 void OCommonEmbeddedObject::StoreDocToStorage_Impl(
741 const uno::Reference
<embed::XStorage
>& xStorage
,
742 const uno::Sequence
<beans::PropertyValue
>& rMediaArgs
,
743 const uno::Sequence
<beans::PropertyValue
>& rObjArgs
,
744 sal_Int32 nStorageFormat
,
745 const OUString
& aHierarchName
,
746 bool bAttachToTheStorage
)
748 SAL_WARN_IF( !xStorage
.is(), "embeddedobj.common", "No storage is provided for storing!" );
750 if ( !xStorage
.is() )
751 throw uno::RuntimeException(); // TODO:
753 uno::Reference
< document::XStorageBasedDocument
> xDoc
;
755 osl::MutexGuard
aGuard( m_aMutex
);
756 if ( m_xDocHolder
.is() )
757 xDoc
.set( m_xDocHolder
->GetComponent(), uno::UNO_QUERY
);
760 OUString aBaseURL
= GetBaseURLFrom_Impl(rMediaArgs
, rObjArgs
);
764 OUString aFilterName
= GetFilterName( nStorageFormat
);
766 // No filter found? Try the older format, e.g. Base has only that.
767 if (aFilterName
.isEmpty() && nStorageFormat
== SOFFICE_FILEFORMAT_CURRENT
)
768 aFilterName
= GetFilterName( SOFFICE_FILEFORMAT_60
);
770 SAL_WARN_IF( aFilterName
.isEmpty(), "embeddedobj.common", "Wrong document service name!" );
771 if ( aFilterName
.isEmpty() )
772 throw io::IOException(); // TODO:
774 uno::Sequence
<beans::PropertyValue
> aArgs(5);
775 aArgs
[0].Name
= "FilterName";
776 aArgs
[0].Value
<<= aFilterName
;
777 aArgs
[1].Name
= "HierarchicalDocumentName";
778 aArgs
[1].Value
<<= aHierarchName
;
779 aArgs
[2].Name
= "DocumentBaseURL";
780 aArgs
[2].Value
<<= aBaseURL
;
781 aArgs
[3].Name
= "SourceShellID";
782 aArgs
[3].Value
<<= getStringPropertyValue(rObjArgs
, "SourceShellID");
783 aArgs
[4].Name
= "DestinationShellID";
784 aArgs
[4].Value
<<= getStringPropertyValue(rObjArgs
, "DestinationShellID");
786 xDoc
->storeToStorage( xStorage
, aArgs
);
787 if ( bAttachToTheStorage
)
788 SwitchDocToStorage_Impl( xDoc
, xStorage
);
792 // store document to temporary stream based on temporary file
793 uno::Reference
< io::XInputStream
> xTempIn
= StoreDocumentToTempStream_Impl( nStorageFormat
, aBaseURL
, aHierarchName
);
795 SAL_WARN_IF( !xTempIn
.is(), "embeddedobj.common", "The stream reference can not be empty!" );
797 // open storage based on document temporary file for reading
798 uno::Reference
< lang::XSingleServiceFactory
> xStorageFactory
= embed::StorageFactory::create(m_xContext
);
800 uno::Sequence
< uno::Any
> aArgs(1);
801 aArgs
[0] <<= xTempIn
;
802 uno::Reference
< embed::XStorage
> xTempStorage( xStorageFactory
->createInstanceWithArguments( aArgs
),
803 uno::UNO_QUERY_THROW
);
805 // object storage must be committed automatically
806 xTempStorage
->copyToStorage( xStorage
);
811 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::CreateDocFromMediaDescr_Impl(
812 const uno::Sequence
< beans::PropertyValue
>& aMedDescr
)
814 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
815 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
817 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY_THROW
);
821 // set the document mode to embedded as the first action on the document!!!
822 EmbedAndReparentDoc_Impl( xDocument
);
824 xLoadable
->load( addAsTemplate( aMedDescr
) );
826 catch( const uno::Exception
& )
828 if ( xDocument
.is() )
832 xDocument
->close( true );
834 catch( const uno::Exception
& )
846 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::CreateTempDocFromLink_Impl()
848 uno::Reference
< util::XCloseable
> xResult
;
850 SAL_WARN_IF( !m_bIsLink
, "embeddedobj.common", "The object is not a linked one!" );
852 uno::Sequence
< beans::PropertyValue
> aTempMediaDescr
;
854 sal_Int32 nStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
856 nStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
858 catch ( const beans::IllegalTypeException
& )
860 // the container just has an unknown type, use current file format
862 catch ( const uno::Exception
& )
864 SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
867 if ( m_xDocHolder
->GetComponent().is() )
869 aTempMediaDescr
.realloc( 4 );
871 // TODO/LATER: may be private:stream should be used as target URL
872 OUString aTempFileURL
;
873 uno::Reference
< io::XInputStream
> xTempStream
= StoreDocumentToTempStream_Impl( SOFFICE_FILEFORMAT_CURRENT
,
878 // no need to let the file stay after the stream is removed since the embedded document
879 // can not be stored directly
880 uno::Reference
< beans::XPropertySet
> xTempStreamProps( xTempStream
, uno::UNO_QUERY_THROW
);
881 xTempStreamProps
->getPropertyValue("Uri") >>= aTempFileURL
;
883 catch( const uno::Exception
& )
887 SAL_WARN_IF( aTempFileURL
.isEmpty(), "embeddedobj.common", "Couldn't retrieve temporary file URL!" );
889 aTempMediaDescr
[0].Name
= "URL";
890 aTempMediaDescr
[0].Value
<<= aTempFileURL
;
891 aTempMediaDescr
[1].Name
= "InputStream";
892 aTempMediaDescr
[1].Value
<<= xTempStream
;
893 aTempMediaDescr
[2].Name
= "FilterName";
894 aTempMediaDescr
[2].Value
<<= GetFilterName( nStorageFormat
);
895 aTempMediaDescr
[3].Name
= "AsTemplate";
896 aTempMediaDescr
[3].Value
<<= true;
900 aTempMediaDescr
.realloc( 2 );
901 aTempMediaDescr
[0].Name
= "URL";
902 aTempMediaDescr
[0].Value
<<= m_aLinkURL
;
903 aTempMediaDescr
[1].Name
= "FilterName";
904 aTempMediaDescr
[1].Value
<<= m_aLinkFilterName
;
907 xResult
= CreateDocFromMediaDescr_Impl( aTempMediaDescr
);
913 void SAL_CALL
OCommonEmbeddedObject::setPersistentEntry(
914 const uno::Reference
< embed::XStorage
>& xStorage
,
915 const OUString
& sEntName
,
916 sal_Int32 nEntryConnectionMode
,
917 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
918 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
920 // the type of the object must be already set
921 // a kind of typedetection should be done in the factory
923 ::osl::MutexGuard
aGuard( m_aMutex
);
925 throw lang::DisposedException(); // TODO
927 if ( !xStorage
.is() )
928 throw lang::IllegalArgumentException( "No parent storage is provided!",
929 static_cast< ::cppu::OWeakObject
* >(this),
932 if ( sEntName
.isEmpty() )
933 throw lang::IllegalArgumentException( "Empty element name is provided!",
934 static_cast< ::cppu::OWeakObject
* >(this),
937 // May be LOADED should be forbidden here ???
938 if ( ( m_nObjectState
!= -1 || nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
939 && ( m_nObjectState
== -1 || nEntryConnectionMode
!= embed::EntryInitModes::NO_INIT
) )
941 // if the object is not loaded
942 // it can not get persistent representation without initialization
944 // if the object is loaded
945 // it can switch persistent representation only without initialization
947 throw embed::WrongStateException(
948 "Can't change persistent representation of activated object!",
949 static_cast< ::cppu::OWeakObject
* >(this) );
952 if ( m_bWaitSaveCompleted
)
954 if ( nEntryConnectionMode
!= embed::EntryInitModes::NO_INIT
)
955 throw embed::WrongStateException(
956 "The object waits for saveCompleted() call!",
957 static_cast< ::cppu::OWeakObject
* >(this) );
958 // saveCompleted is expected, handle it accordingly
959 if ( m_xNewParentStorage
== xStorage
&& m_aNewEntryName
== sEntName
)
961 saveCompleted( true );
965 // if a completely different entry is provided, switch first back to the old persistence in saveCompleted
966 // and then switch to the target persistence
967 bool bSwitchFurther
= ( m_xParentStorage
!= xStorage
|| m_aEntryName
!= sEntName
);
968 saveCompleted( false );
969 if ( !bSwitchFurther
)
973 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
974 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
975 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!" );
978 m_aEntryName
= sEntName
;
982 uno::Reference
< container::XNameAccess
> xNameAccess( xStorage
, uno::UNO_QUERY_THROW
);
984 // detect entry existence
985 bool bElExists
= xNameAccess
->hasByName( sEntName
);
987 m_aDocMediaDescriptor
= GetValuableArgs_Impl( lArguments
,
988 nEntryConnectionMode
!= embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT
);
991 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
992 if ( lArguments
[nInd
].Name
== "ReadOnly" )
993 lArguments
[nInd
].Value
>>= m_bReadOnly
;
995 // TODO: use lObjArgs for StoreVisualReplacement
996 for ( sal_Int32 nObjInd
= 0; nObjInd
< lObjArgs
.getLength(); nObjInd
++ )
997 if ( lObjArgs
[nObjInd
].Name
== "OutplaceDispatchInterceptor" )
999 uno::Reference
< frame::XDispatchProviderInterceptor
> xDispatchInterceptor
;
1000 if ( lObjArgs
[nObjInd
].Value
>>= xDispatchInterceptor
)
1001 m_xDocHolder
->SetOutplaceDispatchInterceptor( xDispatchInterceptor
);
1003 else if ( lObjArgs
[nObjInd
].Name
== "DefaultParentBaseURL" )
1005 lObjArgs
[nObjInd
].Value
>>= m_aDefaultParentBaseURL
;
1007 else if ( lObjArgs
[nObjInd
].Name
== "Parent" )
1009 lObjArgs
[nObjInd
].Value
>>= m_xParent
;
1011 else if ( lObjArgs
[nObjInd
].Name
== "IndividualMiscStatus" )
1013 sal_Int64 nMiscStatus
=0;
1014 lObjArgs
[nObjInd
].Value
>>= nMiscStatus
;
1015 m_nMiscStatus
|= nMiscStatus
;
1017 else if ( lObjArgs
[nObjInd
].Name
== "CloneFrom" )
1019 uno::Reference
< embed::XEmbeddedObject
> xObj
;
1020 lObjArgs
[nObjInd
].Value
>>= xObj
;
1023 m_bHasClonedSize
= true;
1024 m_aClonedSize
= xObj
->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
1025 m_nClonedMapUnit
= xObj
->getMapUnit( embed::Aspects::MSOLE_CONTENT
);
1028 else if ( lObjArgs
[nObjInd
].Name
== "OutplaceFrameProperties" )
1030 uno::Sequence
< uno::Any
> aOutFrameProps
;
1031 uno::Sequence
< beans::NamedValue
> aOutFramePropsTyped
;
1032 if ( lObjArgs
[nObjInd
].Value
>>= aOutFrameProps
)
1034 m_xDocHolder
->SetOutplaceFrameProperties( aOutFrameProps
);
1036 else if ( lObjArgs
[nObjInd
].Value
>>= aOutFramePropsTyped
)
1038 aOutFrameProps
.realloc( aOutFramePropsTyped
.getLength() );
1039 uno::Any
* pProp
= aOutFrameProps
.getArray();
1040 for ( const beans::NamedValue
* pTypedProp
= aOutFramePropsTyped
.getConstArray();
1041 pTypedProp
!= aOutFramePropsTyped
.getConstArray() + aOutFramePropsTyped
.getLength();
1042 ++pTypedProp
, ++pProp
1045 *pProp
<<= *pTypedProp
;
1047 m_xDocHolder
->SetOutplaceFrameProperties( aOutFrameProps
);
1050 SAL_WARN( "embeddedobj.common", "OCommonEmbeddedObject::setPersistentEntry: illegal type for argument 'OutplaceFrameProperties'!" );
1052 else if ( lObjArgs
[nObjInd
].Name
== "ModuleName" )
1054 lObjArgs
[nObjInd
].Value
>>= m_aModuleName
;
1056 else if ( lObjArgs
[nObjInd
].Name
== "EmbeddedScriptSupport" )
1058 OSL_VERIFY( lObjArgs
[nObjInd
].Value
>>= m_bEmbeddedScriptSupport
);
1060 else if ( lObjArgs
[nObjInd
].Name
== "DocumentRecoverySupport" )
1062 OSL_VERIFY( lObjArgs
[nObjInd
].Value
>>= m_bDocumentRecoverySupport
);
1064 else if ( lObjArgs
[nObjInd
].Name
== "RecoveryStorage" )
1066 OSL_VERIFY( lObjArgs
[nObjInd
].Value
>>= m_xRecoveryStorage
);
1070 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
1072 SwitchOwnPersistence( xStorage
, sEntName
);
1074 if ( nEntryConnectionMode
== embed::EntryInitModes::DEFAULT_INIT
)
1078 // the initialization from existing storage allows to leave object in loaded state
1079 m_nObjectState
= embed::EmbedStates::LOADED
;
1083 m_xDocHolder
->SetComponent( InitNewDocument_Impl(), m_bReadOnly
);
1084 if ( !m_xDocHolder
->GetComponent().is() )
1085 throw io::IOException(); // TODO: can not create document
1087 m_nObjectState
= embed::EmbedStates::RUNNING
;
1092 if ( ( nStorageMode
& embed::ElementModes::READWRITE
) != embed::ElementModes::READWRITE
)
1093 throw io::IOException();
1095 if ( nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
1097 // the document just already changed its storage to store to
1098 // the links to OOo documents for now ignore this call
1099 // TODO: OOo links will have persistence so it will be switched here
1101 else if ( nEntryConnectionMode
== embed::EntryInitModes::TRUNCATE_INIT
)
1103 if ( m_xRecoveryStorage
.is() )
1104 TransferMediaType( m_xRecoveryStorage
, m_xObjectStorage
);
1107 m_xDocHolder
->SetComponent( InitNewDocument_Impl(), m_bReadOnly
);
1109 if ( !m_xDocHolder
->GetComponent().is() )
1110 throw io::IOException(); // TODO: can not create document
1112 m_nObjectState
= embed::EmbedStates::RUNNING
;
1114 else if ( nEntryConnectionMode
== embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT
)
1116 m_xDocHolder
->SetComponent( CreateDocFromMediaDescr_Impl( lArguments
), m_bReadOnly
);
1117 m_nObjectState
= embed::EmbedStates::RUNNING
;
1119 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1124 throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
1125 static_cast< ::cppu::OWeakObject
* >(this),
1131 void SAL_CALL
OCommonEmbeddedObject::storeToEntry( const uno::Reference
< embed::XStorage
>& xStorage
,
1132 const OUString
& sEntName
,
1133 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1134 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1136 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1138 throw lang::DisposedException(); // TODO
1140 if ( m_nObjectState
== -1 )
1142 // the object is still not loaded
1143 throw embed::WrongStateException( "Can't store object without persistence!",
1144 static_cast< ::cppu::OWeakObject
* >(this) );
1147 if ( m_bWaitSaveCompleted
)
1148 throw embed::WrongStateException(
1149 "The object waits for saveCompleted() call!",
1150 static_cast< ::cppu::OWeakObject
* >(this) );
1152 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1153 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1154 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!" );
1158 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStorage
.is(), "The object has no valid persistence!" );
1160 sal_Int32 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1161 sal_Int32 nOriginalStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1163 nTargetStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( xStorage
);
1165 catch ( const beans::IllegalTypeException
& )
1167 // the container just has an unknown type, use current file format
1169 catch ( const uno::Exception
& )
1171 SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
1173 if (nTargetStorageFormat
== SOFFICE_FILEFORMAT_60
)
1175 SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
1176 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1177 // setting MediaType is done later anyway, no need to do it here
1182 nOriginalStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
1184 catch ( const beans::IllegalTypeException
& )
1186 // the container just has an unknown type, use current file format
1188 catch ( const uno::Exception
& )
1190 SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
1193 bool bTryOptimization
= false;
1194 for ( sal_Int32 nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
1196 // StoreVisualReplacement and VisualReplacement args have no sense here
1197 if ( lObjArgs
[nInd
].Name
== "CanTryOptimization" )
1198 lObjArgs
[nInd
].Value
>>= bTryOptimization
;
1201 bool bSwitchBackToLoaded
= false;
1203 // Storing to different format can be done only in running state.
1204 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1206 // TODO/LATER: copying is not legal for documents with relative links.
1207 if ( nTargetStorageFormat
== nOriginalStorageFormat
)
1209 bool bOptimizationWorks
= false;
1210 if ( bTryOptimization
)
1214 // try to use optimized copying
1215 uno::Reference
< embed::XOptimizedStorage
> xSource( m_xParentStorage
, uno::UNO_QUERY_THROW
);
1216 uno::Reference
< embed::XOptimizedStorage
> xTarget( xStorage
, uno::UNO_QUERY_THROW
);
1217 xSource
->copyElementDirectlyTo( m_aEntryName
, xTarget
, sEntName
);
1218 bOptimizationWorks
= true;
1220 catch( const uno::Exception
& )
1225 if ( !bOptimizationWorks
)
1226 m_xParentStorage
->copyElementTo( m_aEntryName
, xStorage
, sEntName
);
1230 changeState( embed::EmbedStates::RUNNING
);
1231 bSwitchBackToLoaded
= true;
1235 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
1237 uno::Reference
< embed::XStorage
> xSubStorage
=
1238 xStorage
->openStorageElement( sEntName
, embed::ElementModes::READWRITE
);
1240 if ( !xSubStorage
.is() )
1241 throw uno::RuntimeException(); //TODO
1244 // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1245 StoreDocToStorage_Impl(
1246 xSubStorage
, lArguments
, lObjArgs
, nTargetStorageFormat
, sEntName
, false );
1249 if ( bSwitchBackToLoaded
)
1250 changeState( embed::EmbedStates::LOADED
);
1253 // TODO: should the listener notification be done?
1257 void SAL_CALL
OCommonEmbeddedObject::storeAsEntry( const uno::Reference
< embed::XStorage
>& xStorage
,
1258 const OUString
& sEntName
,
1259 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1260 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1262 // TODO: use lObjArgs
1264 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1266 throw lang::DisposedException(); // TODO
1268 if ( m_nObjectState
== -1 )
1270 // the object is still not loaded
1271 throw embed::WrongStateException( "Can't store object without persistence!",
1272 static_cast< ::cppu::OWeakObject
* >(this) );
1275 if ( m_bWaitSaveCompleted
)
1276 throw embed::WrongStateException(
1277 "The object waits for saveCompleted() call!",
1278 static_cast< ::cppu::OWeakObject
* >(this) );
1280 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1281 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1282 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!" );
1285 m_aNewEntryName
= sEntName
;
1289 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStorage
.is(), "The object has no valid persistence!" );
1291 sal_Int32 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1292 sal_Int32 nOriginalStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1294 nTargetStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( xStorage
);
1296 catch ( const beans::IllegalTypeException
& )
1298 // the container just has an unknown type, use current file format
1300 catch ( const uno::Exception
& )
1302 SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
1304 if (nTargetStorageFormat
== SOFFICE_FILEFORMAT_60
)
1306 SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
1307 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1308 // setting MediaType is done later anyway, no need to do it here
1313 nOriginalStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
1315 catch ( const beans::IllegalTypeException
& )
1317 // the container just has an unknown type, use current file format
1319 catch ( const uno::Exception
& )
1321 SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
1324 PostEvent_Impl( "OnSaveAs" );
1326 bool bTryOptimization
= false;
1327 for ( sal_Int32 nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
1329 // StoreVisualReplacement and VisualReplacement args have no sense here
1330 if ( lObjArgs
[nInd
].Name
== "CanTryOptimization" )
1331 lObjArgs
[nInd
].Value
>>= bTryOptimization
;
1334 bool bSwitchBackToLoaded
= false;
1336 // Storing to different format can be done only in running state.
1337 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1339 // TODO/LATER: copying is not legal for documents with relative links.
1340 if ( nTargetStorageFormat
== nOriginalStorageFormat
)
1342 bool bOptimizationWorks
= false;
1343 if ( bTryOptimization
)
1347 // try to use optimized copying
1348 uno::Reference
< embed::XOptimizedStorage
> xSource( m_xParentStorage
, uno::UNO_QUERY_THROW
);
1349 uno::Reference
< embed::XOptimizedStorage
> xTarget( xStorage
, uno::UNO_QUERY_THROW
);
1350 xSource
->copyElementDirectlyTo( m_aEntryName
, xTarget
, sEntName
);
1351 bOptimizationWorks
= true;
1353 catch( const uno::Exception
& )
1358 if ( !bOptimizationWorks
)
1359 m_xParentStorage
->copyElementTo( m_aEntryName
, xStorage
, sEntName
);
1363 changeState( embed::EmbedStates::RUNNING
);
1364 bSwitchBackToLoaded
= true;
1368 uno::Reference
< embed::XStorage
> xSubStorage
=
1369 xStorage
->openStorageElement( sEntName
, embed::ElementModes::READWRITE
);
1371 if ( !xSubStorage
.is() )
1372 throw uno::RuntimeException(); //TODO
1374 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
1377 // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1378 StoreDocToStorage_Impl(
1379 xSubStorage
, lArguments
, lObjArgs
, nTargetStorageFormat
, sEntName
, false );
1382 if ( bSwitchBackToLoaded
)
1383 changeState( embed::EmbedStates::LOADED
);
1386 m_bWaitSaveCompleted
= true;
1387 m_xNewObjectStorage
= xSubStorage
;
1388 m_xNewParentStorage
= xStorage
;
1389 m_aNewEntryName
= sEntName
;
1390 m_aNewDocMediaDescriptor
= GetValuableArgs_Impl( lArguments
, true );
1392 // TODO: register listeners for storages above, in case they are disposed
1393 // an exception will be thrown on saveCompleted( true )
1395 // TODO: should the listener notification be done here or in saveCompleted?
1399 void SAL_CALL
OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew
)
1401 ::osl::MutexGuard
aGuard( m_aMutex
);
1403 throw lang::DisposedException(); // TODO
1405 if ( m_nObjectState
== -1 )
1407 // the object is still not loaded
1408 throw embed::WrongStateException( "Can't store object without persistence!",
1409 static_cast< ::cppu::OWeakObject
* >(this) );
1412 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1413 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1414 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!" );
1418 m_aEntryName
= m_aNewEntryName
;
1419 m_aNewEntryName
.clear();
1423 // it is allowed to call saveCompleted( false ) for nonstored objects
1424 if ( !m_bWaitSaveCompleted
&& !bUseNew
)
1427 SAL_WARN_IF( !m_bWaitSaveCompleted
, "embeddedobj.common", "Unexpected saveCompleted() call!" );
1428 if ( !m_bWaitSaveCompleted
)
1429 throw io::IOException(); // TODO: illegal call
1431 OSL_ENSURE( m_xNewObjectStorage
.is() && m_xNewParentStorage
.is() , "Internal object information is broken!" );
1432 if ( !m_xNewObjectStorage
.is() || !m_xNewParentStorage
.is() )
1433 throw uno::RuntimeException(); // TODO: broken internal information
1437 SwitchOwnPersistence( m_xNewParentStorage
, m_xNewObjectStorage
, m_aNewEntryName
);
1438 m_aDocMediaDescriptor
= m_aNewDocMediaDescriptor
;
1440 uno::Reference
< util::XModifiable
> xModif( m_xDocHolder
->GetComponent(), uno::UNO_QUERY
);
1442 xModif
->setModified( false );
1444 PostEvent_Impl( "OnSaveAsDone");
1449 m_xNewObjectStorage
->dispose();
1451 catch ( const uno::Exception
& )
1456 m_xNewObjectStorage
.clear();
1457 m_xNewParentStorage
.clear();
1458 m_aNewEntryName
.clear();
1459 m_aNewDocMediaDescriptor
.realloc( 0 );
1460 m_bWaitSaveCompleted
= false;
1464 // TODO: notify listeners
1466 if ( m_nUpdateMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
)
1468 // TODO: update visual representation
1474 sal_Bool SAL_CALL
OCommonEmbeddedObject::hasEntry()
1476 ::osl::MutexGuard
aGuard( m_aMutex
);
1478 throw lang::DisposedException(); // TODO
1480 if ( m_bWaitSaveCompleted
)
1481 throw embed::WrongStateException(
1482 "The object waits for saveCompleted() call!",
1483 static_cast< ::cppu::OWeakObject
* >(this) );
1485 if ( m_xObjectStorage
.is() )
1492 OUString SAL_CALL
OCommonEmbeddedObject::getEntryName()
1494 ::osl::MutexGuard
aGuard( m_aMutex
);
1496 throw lang::DisposedException(); // TODO
1498 if ( m_nObjectState
== -1 )
1500 // the object is still not loaded
1501 throw embed::WrongStateException( "The object persistence is not initialized!",
1502 static_cast< ::cppu::OWeakObject
* >(this) );
1505 if ( m_bWaitSaveCompleted
)
1506 throw embed::WrongStateException(
1507 "The object waits for saveCompleted() call!",
1508 static_cast< ::cppu::OWeakObject
* >(this) );
1510 return m_aEntryName
;
1514 void SAL_CALL
OCommonEmbeddedObject::storeOwn()
1516 // during switching from Activated to Running and from Running to Loaded states the object will
1517 // ask container to store the object, the container has to make decision
1520 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1522 throw lang::DisposedException(); // TODO
1524 if ( m_nObjectState
== -1 )
1526 // the object is still not loaded
1527 throw embed::WrongStateException( "Can't store object without persistence!",
1528 static_cast< ::cppu::OWeakObject
* >(this) );
1531 if ( m_bWaitSaveCompleted
)
1532 throw embed::WrongStateException(
1533 "The object waits for saveCompleted() call!",
1534 static_cast< ::cppu::OWeakObject
* >(this) );
1537 throw io::IOException(); // TODO: access denied
1539 // nothing to do, if the object is in loaded state
1540 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1543 PostEvent_Impl( "OnSave" );
1545 SAL_WARN_IF( !m_xDocHolder
->GetComponent().is(), "embeddedobj.common", "If an object is activated or in running state it must have a document!" );
1546 if ( !m_xDocHolder
->GetComponent().is() )
1547 throw uno::RuntimeException();
1551 // TODO: just store the document to its location
1552 uno::Reference
< frame::XStorable
> xStorable( m_xDocHolder
->GetComponent(), uno::UNO_QUERY_THROW
);
1554 // free the main mutex for the storing time
1563 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStorage
.is(), "The object has no valid persistence!" );
1565 if ( !m_xObjectStorage
.is() )
1566 throw io::IOException(); //TODO: access denied
1568 sal_Int32 nStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1570 nStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
1572 catch ( const beans::IllegalTypeException
& )
1574 // the container just has an unknown type, use current file format
1576 catch ( const uno::Exception
& )
1578 SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
1580 if (nStorageFormat
== SOFFICE_FILEFORMAT_60
)
1582 SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
1583 nStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1584 // setting MediaType is done later anyway, no need to do it here
1588 uno::Sequence
<beans::PropertyValue
> aEmpty
;
1589 uno::Sequence
<beans::PropertyValue
> aMediaArgs(1);
1590 aMediaArgs
[0].Name
= "DocumentBaseURL";
1591 aMediaArgs
[0].Value
<<= GetBaseURL_Impl();
1592 StoreDocToStorage_Impl( m_xObjectStorage
, aMediaArgs
, aEmpty
, nStorageFormat
, m_aEntryName
, true );
1596 uno::Reference
< util::XModifiable
> xModif( m_xDocHolder
->GetComponent(), uno::UNO_QUERY
);
1598 xModif
->setModified( false );
1600 PostEvent_Impl( "OnSaveDone" );
1604 sal_Bool SAL_CALL
OCommonEmbeddedObject::isReadonly()
1606 ::osl::MutexGuard
aGuard( m_aMutex
);
1608 throw lang::DisposedException(); // TODO
1610 if ( m_nObjectState
== -1 )
1612 // the object is still not loaded
1613 throw embed::WrongStateException( "The object persistence is not initialized!",
1614 static_cast< ::cppu::OWeakObject
* >(this) );
1617 if ( m_bWaitSaveCompleted
)
1618 throw embed::WrongStateException(
1619 "The object waits for saveCompleted() call!",
1620 static_cast< ::cppu::OWeakObject
* >(this) );
1626 void SAL_CALL
OCommonEmbeddedObject::reload(
1627 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1628 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1630 // TODO: use lObjArgs
1631 // for now this method is used only to switch readonly state
1633 ::osl::MutexGuard
aGuard( m_aMutex
);
1635 throw lang::DisposedException(); // TODO
1637 if ( m_nObjectState
== -1 )
1639 // the object is still not loaded
1640 throw embed::WrongStateException( "The object persistence is not initialized!",
1641 static_cast< ::cppu::OWeakObject
* >(this) );
1644 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
1646 // the object is still not loaded
1647 throw embed::WrongStateException(
1648 "The object must be in loaded state to be reloaded!",
1649 static_cast< ::cppu::OWeakObject
* >(this) );
1652 if ( m_bWaitSaveCompleted
)
1653 throw embed::WrongStateException(
1654 "The object waits for saveCompleted() call!",
1655 static_cast< ::cppu::OWeakObject
* >(this) );
1659 // reload of the link
1660 OUString aOldLinkFilter
= m_aLinkFilterName
;
1662 OUString aNewLinkFilter
;
1663 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
1665 if ( lArguments
[nInd
].Name
== "URL" )
1668 lArguments
[nInd
].Value
>>= m_aLinkURL
;
1669 m_aLinkFilterName
.clear();
1671 else if ( lArguments
[nInd
].Name
== "FilterName" )
1673 lArguments
[nInd
].Value
>>= aNewLinkFilter
;
1674 m_aLinkFilterName
.clear();
1678 ::comphelper::MimeConfigurationHelper
aHelper( m_xContext
);
1679 if ( m_aLinkFilterName
.isEmpty() )
1681 if ( !aNewLinkFilter
.isEmpty() )
1682 m_aLinkFilterName
= aNewLinkFilter
;
1685 uno::Sequence
< beans::PropertyValue
> aArgs( 1 );
1686 aArgs
[0].Name
= "URL";
1687 aArgs
[0].Value
<<= m_aLinkURL
;
1688 m_aLinkFilterName
= aHelper
.UpdateMediaDescriptorWithFilterName( aArgs
, false );
1692 if ( aOldLinkFilter
!= m_aLinkFilterName
)
1694 uno::Sequence
< beans::NamedValue
> aObject
= aHelper
.GetObjectPropsByFilter( m_aLinkFilterName
);
1696 // TODO/LATER: probably the document holder could be cleaned explicitly as in the destructor
1697 m_xDocHolder
.clear();
1699 LinkInit_Impl( aObject
, lArguments
, lObjArgs
);
1703 m_aDocMediaDescriptor
= GetValuableArgs_Impl( lArguments
, true );
1705 // TODO: use lObjArgs for StoreVisualReplacement
1706 for ( sal_Int32 nObjInd
= 0; nObjInd
< lObjArgs
.getLength(); nObjInd
++ )
1707 if ( lObjArgs
[nObjInd
].Name
== "OutplaceDispatchInterceptor" )
1709 uno::Reference
< frame::XDispatchProviderInterceptor
> xDispatchInterceptor
;
1710 if ( lObjArgs
[nObjInd
].Value
>>= xDispatchInterceptor
)
1711 m_xDocHolder
->SetOutplaceDispatchInterceptor( xDispatchInterceptor
);
1717 // when document allows reloading through API the object can be reloaded not only in loaded state
1719 bool bOldReadOnlyValue
= m_bReadOnly
;
1721 m_bReadOnly
= false;
1722 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
1723 if ( lArguments
[nInd
].Name
== "ReadOnly" )
1724 lArguments
[nInd
].Value
>>= m_bReadOnly
;
1726 if ( bOldReadOnlyValue
!= m_bReadOnly
&& !m_bIsLink
)
1728 // close own storage
1730 if ( m_xObjectStorage
.is() )
1731 m_xObjectStorage
->dispose();
1733 catch ( const uno::Exception
& )
1737 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
1738 m_xObjectStorage
= m_xParentStorage
->openStorageElement( m_aEntryName
, nStorageMode
);
1742 sal_Bool SAL_CALL
OCommonEmbeddedObject::isStored()
1744 if (!m_xObjectStorage
.is())
1747 return m_xObjectStorage
->getElementNames().hasElements();
1751 void SAL_CALL
OCommonEmbeddedObject::breakLink( const uno::Reference
< embed::XStorage
>& xStorage
,
1752 const OUString
& sEntName
)
1754 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1756 throw lang::DisposedException(); // TODO
1758 if (!m_bIsLink
|| m_nObjectState
== -1)
1760 // it must be a linked initialized object
1761 throw embed::WrongStateException(
1762 "The object is not a valid linked object!",
1763 static_cast< ::cppu::OWeakObject
* >(this) );
1765 // the current implementation of OOo links does not implement this method since it does not implement
1766 // all the set of interfaces required for OOo embedded object ( XEmbedPersist is not supported ).
1768 if ( !xStorage
.is() )
1769 throw lang::IllegalArgumentException( "No parent storage is provided!",
1770 static_cast< ::cppu::OWeakObject
* >(this),
1773 if ( sEntName
.isEmpty() )
1774 throw lang::IllegalArgumentException( "Empty element name is provided!",
1775 static_cast< ::cppu::OWeakObject
* >(this),
1778 if ( m_bWaitSaveCompleted
)
1779 throw embed::WrongStateException(
1780 "The object waits for saveCompleted() call!",
1781 static_cast< ::cppu::OWeakObject
* >(this) );
1783 uno::Reference
< container::XNameAccess
> xNameAccess( xStorage
, uno::UNO_QUERY_THROW
);
1785 m_bReadOnly
= false;
1787 if ( m_xParentStorage
!= xStorage
|| m_aEntryName
!= sEntName
)
1788 SwitchOwnPersistence( xStorage
, sEntName
);
1790 // for linked object it means that it becomes embedded object
1791 // the document must switch it's persistence also
1793 // TODO/LATER: handle the case when temp doc can not be created
1794 // the document is a new embedded object so it must be marked as modified
1795 uno::Reference
< util::XCloseable
> xDocument
= CreateTempDocFromLink_Impl();
1796 uno::Reference
< util::XModifiable
> xModif( m_xDocHolder
->GetComponent(), uno::UNO_QUERY_THROW
);
1799 xModif
->setModified( true );
1801 catch( const uno::Exception
& )
1804 m_xDocHolder
->SetComponent( xDocument
, m_bReadOnly
);
1805 SAL_WARN_IF( !m_xDocHolder
->GetComponent().is(), "embeddedobj.common", "If document can't be created, an exception must be thrown!" );
1807 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1809 // the state is changed and can not be switched to loaded state back without saving
1810 m_nObjectState
= embed::EmbedStates::RUNNING
;
1811 StateChangeNotification_Impl( false, embed::EmbedStates::LOADED
, m_nObjectState
, aGuard
);
1813 else if ( m_nObjectState
== embed::EmbedStates::ACTIVE
)
1814 m_xDocHolder
->Show();
1817 m_aLinkFilterName
.clear();
1822 sal_Bool SAL_CALL
OCommonEmbeddedObject::isLink()
1824 ::osl::MutexGuard
aGuard( m_aMutex
);
1826 throw lang::DisposedException(); // TODO
1832 OUString SAL_CALL
OCommonEmbeddedObject::getLinkURL()
1834 ::osl::MutexGuard
aGuard( m_aMutex
);
1836 throw lang::DisposedException(); // TODO
1839 throw embed::WrongStateException(
1840 "The object is not a link object!",
1841 static_cast< ::cppu::OWeakObject
* >(this) );
1846 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */