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/EmbedVerbs.hpp>
25 #include <com/sun/star/embed/EntryInitModes.hpp>
26 #include <com/sun/star/embed/XStorage.hpp>
27 #include <com/sun/star/embed/XOptimizedStorage.hpp>
28 #include <com/sun/star/embed/ElementModes.hpp>
29 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
30 #include <com/sun/star/embed/StorageFactory.hpp>
31 #include <com/sun/star/io/TempFile.hpp>
32 #include <com/sun/star/frame/XModel.hpp>
33 #include <com/sun/star/frame/XStorable.hpp>
34 #include <com/sun/star/frame/XLoadable.hpp>
35 #include <com/sun/star/frame/XComponentLoader.hpp>
36 #include <com/sun/star/frame/XModule.hpp>
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
39 #include <com/sun/star/lang/DisposedException.hpp>
40 #include <com/sun/star/util/XModifiable.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/container/XChild.hpp>
44 #include <com/sun/star/util/XCloseable.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/beans/IllegalTypeException.hpp>
47 #include <com/sun/star/chart2/XChartDocument.hpp>
49 #include <comphelper/fileformat.h>
50 #include <comphelper/processfactory.hxx>
51 #include <comphelper/storagehelper.hxx>
52 #include <comphelper/mimeconfighelper.hxx>
53 #include <comphelper/namedvaluecollection.hxx>
55 #include <tools/diagnose_ex.h>
56 #include "persistence.hxx"
58 using namespace ::com::sun::star
;
62 uno::Sequence
< beans::PropertyValue
> GetValuableArgs_Impl( const uno::Sequence
< beans::PropertyValue
>& aMedDescr
,
63 bool bCanUseDocumentBaseURL
)
65 uno::Sequence
< beans::PropertyValue
> aResult
;
66 sal_Int32 nResLen
= 0;
68 for ( sal_Int32 nInd
= 0; nInd
< aMedDescr
.getLength(); nInd
++ )
70 if ( aMedDescr
[nInd
].Name
== "ComponentData" || aMedDescr
[nInd
].Name
== "DocumentTitle"
71 || aMedDescr
[nInd
].Name
== "InteractionHandler" || aMedDescr
[nInd
].Name
== "JumpMark"
72 // || aMedDescr[nInd].Name == "Password" // makes no sense for embedded objects
73 || aMedDescr
[nInd
].Name
== "Preview" || aMedDescr
[nInd
].Name
== "ReadOnly"
74 || aMedDescr
[nInd
].Name
== "StartPresentation" || aMedDescr
[nInd
].Name
== "RepairPackage"
75 || aMedDescr
[nInd
].Name
== "StatusIndicator" || aMedDescr
[nInd
].Name
== "ViewData"
76 || aMedDescr
[nInd
].Name
== "ViewId" || aMedDescr
[nInd
].Name
== "MacroExecutionMode"
77 || aMedDescr
[nInd
].Name
== "UpdateDocMode"
78 || (aMedDescr
[nInd
].Name
== "DocumentBaseURL" && bCanUseDocumentBaseURL
) )
80 aResult
.realloc( ++nResLen
);
81 aResult
[nResLen
-1] = aMedDescr
[nInd
];
89 uno::Sequence
< beans::PropertyValue
> addAsTemplate( const uno::Sequence
< beans::PropertyValue
>& aOrig
)
91 bool bAsTemplateSet
= false;
92 sal_Int32 nLength
= aOrig
.getLength();
93 uno::Sequence
< beans::PropertyValue
> aResult( nLength
);
95 for ( sal_Int32 nInd
= 0; nInd
< nLength
; nInd
++ )
97 aResult
[nInd
].Name
= aOrig
[nInd
].Name
;
98 if ( aResult
[nInd
].Name
== "AsTemplate" )
100 aResult
[nInd
].Value
<<= sal_True
;
101 bAsTemplateSet
= true;
104 aResult
[nInd
].Value
= aOrig
[nInd
].Value
;
107 if ( !bAsTemplateSet
)
109 aResult
.realloc( nLength
+ 1 );
110 aResult
[nLength
].Name
= "AsTemplate";
111 aResult
[nLength
].Value
<<= sal_True
;
118 uno::Reference
< io::XInputStream
> createTempInpStreamFromStor(
119 const uno::Reference
< embed::XStorage
>& xStorage
,
120 const uno::Reference
< uno::XComponentContext
>& xContext
)
122 SAL_WARN_IF( !xStorage
.is(), "embeddedobj.common", "The storage can not be empty!" );
124 uno::Reference
< io::XInputStream
> xResult
;
126 uno::Reference
< io::XStream
> xTempStream( io::TempFile::create(xContext
), uno::UNO_QUERY_THROW
);
128 uno::Reference
< lang::XSingleServiceFactory
> xStorageFactory( embed::StorageFactory::create(xContext
) );
130 uno::Sequence
< uno::Any
> aArgs( 2 );
131 aArgs
[0] <<= xTempStream
;
132 aArgs
[1] <<= embed::ElementModes::READWRITE
;
133 uno::Reference
< embed::XStorage
> xTempStorage( xStorageFactory
->createInstanceWithArguments( aArgs
),
135 if ( !xTempStorage
.is() )
136 throw uno::RuntimeException(); // TODO:
140 xStorage
->copyToStorage( xTempStorage
);
141 } catch( const uno::Exception
& e
)
143 throw embed::StorageWrappedTargetException(
144 "Can't copy storage!",
145 uno::Reference
< uno::XInterface
>(),
150 uno::Reference
< lang::XComponent
> xComponent( xTempStorage
, uno::UNO_QUERY
);
151 SAL_WARN_IF( !xComponent
.is(), "embeddedobj.common", "Wrong storage implementation!" );
152 if ( xComponent
.is() )
153 xComponent
->dispose();
155 catch ( const uno::Exception
& )
160 uno::Reference
< io::XOutputStream
> xTempOut
= xTempStream
->getOutputStream();
162 xTempOut
->closeOutput();
164 catch ( const uno::Exception
& )
168 xResult
= xTempStream
->getInputStream();
175 static void TransferMediaType( const uno::Reference
< embed::XStorage
>& i_rSource
, const uno::Reference
< embed::XStorage
>& i_rTarget
)
179 const uno::Reference
< beans::XPropertySet
> xSourceProps( i_rSource
, uno::UNO_QUERY_THROW
);
180 const uno::Reference
< beans::XPropertySet
> xTargetProps( i_rTarget
, uno::UNO_QUERY_THROW
);
181 const OUString
sMediaTypePropName( "MediaType" );
182 xTargetProps
->setPropertyValue( sMediaTypePropName
, xSourceProps
->getPropertyValue( sMediaTypePropName
) );
184 catch( const uno::Exception
& )
186 DBG_UNHANDLED_EXCEPTION();
191 static uno::Reference
< util::XCloseable
> CreateDocument( const uno::Reference
< uno::XComponentContext
>& _rxContext
,
192 const OUString
& _rDocumentServiceName
, bool _bEmbeddedScriptSupport
, const bool i_bDocumentRecoverySupport
)
194 ::comphelper::NamedValueCollection aArguments
;
195 aArguments
.put( "EmbeddedObject", true );
196 aArguments
.put( "EmbeddedScriptSupport", _bEmbeddedScriptSupport
);
197 aArguments
.put( "DocumentRecoverySupport", i_bDocumentRecoverySupport
);
199 uno::Reference
< uno::XInterface
> xDocument
;
202 xDocument
= _rxContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
203 _rDocumentServiceName
, aArguments
.getWrappedPropertyValues(), _rxContext
);
205 catch( const uno::Exception
& )
207 // if an embedded object implementation does not support XInitialization,
208 // the default factory from cppuhelper will throw an
209 // IllegalArgumentException when we try to create the instance with arguments.
210 // Okay, so we fall back to creating the instance without any arguments.
211 OSL_FAIL("Consider implementing interface XInitialization to avoid duplicate construction");
212 xDocument
= _rxContext
->getServiceManager()->createInstanceWithContext( _rDocumentServiceName
, _rxContext
);
215 SAL_WARN_IF(!xDocument
.is(), "embeddedobj.common", "Service " << _rDocumentServiceName
<< " is not available?");
216 return uno::Reference
< util::XCloseable
>( xDocument
, uno::UNO_QUERY
);
220 static void SetDocToEmbedded( const uno::Reference
< frame::XModel
>& rDocument
, const OUString
& aModuleName
)
224 uno::Sequence
< beans::PropertyValue
> aSeq( 1 );
225 aSeq
[0].Name
= "SetEmbedded";
226 aSeq
[0].Value
<<= sal_True
;
227 rDocument
->attachResource( OUString(), aSeq
);
229 if ( !aModuleName
.isEmpty() )
233 uno::Reference
< frame::XModule
> xModule( rDocument
, uno::UNO_QUERY_THROW
);
234 xModule
->setIdentifier( aModuleName
);
236 catch( const uno::Exception
& )
243 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference
< embed::XStorage
>& xNewParentStorage
,
244 const uno::Reference
< embed::XStorage
>& xNewObjectStorage
,
245 const OUString
& aNewName
)
247 if ( xNewParentStorage
== m_xParentStorage
&& aNewName
.equals( m_aEntryName
) )
249 SAL_WARN_IF( xNewObjectStorage
!= m_xObjectStorage
, "embeddedobj.common", "The storage must be the same!" );
253 uno::Reference
< lang::XComponent
> xComponent( m_xObjectStorage
, uno::UNO_QUERY
);
254 OSL_ENSURE( !m_xObjectStorage
.is() || xComponent
.is(), "Wrong storage implementation!" );
256 m_xObjectStorage
= xNewObjectStorage
;
257 m_xParentStorage
= xNewParentStorage
;
258 m_aEntryName
= aNewName
;
260 // the linked document should not be switched
263 uno::Reference
< document::XStorageBasedDocument
> xDoc( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
265 SwitchDocToStorage_Impl( xDoc
, m_xObjectStorage
);
269 if ( xComponent
.is() )
270 xComponent
->dispose();
272 catch ( const uno::Exception
& )
278 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference
< embed::XStorage
>& xNewParentStorage
,
279 const OUString
& aNewName
)
281 if ( xNewParentStorage
== m_xParentStorage
&& aNewName
.equals( m_aEntryName
) )
284 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
286 uno::Reference
< embed::XStorage
> xNewOwnStorage
= xNewParentStorage
->openStorageElement( aNewName
, nStorageMode
);
287 SAL_WARN_IF( !xNewOwnStorage
.is(), "embeddedobj.common", "The method can not return empty reference!" );
289 SwitchOwnPersistence( xNewParentStorage
, xNewOwnStorage
, aNewName
);
293 void OCommonEmbeddedObject::EmbedAndReparentDoc_Impl( const uno::Reference
< util::XCloseable
>& i_rxDocument
) const
295 SetDocToEmbedded( uno::Reference
< frame::XModel
>( i_rxDocument
, uno::UNO_QUERY
), m_aModuleName
);
299 uno::Reference
< container::XChild
> xChild( i_rxDocument
, uno::UNO_QUERY
);
301 xChild
->setParent( m_xParent
);
303 catch( const lang::NoSupportException
& )
305 SAL_WARN( "embeddedobj.common", "OCommonEmbeddedObject::EmbedAndReparentDoc: cannot set parent at document!" );
310 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::InitNewDocument_Impl()
312 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
313 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
315 uno::Reference
< frame::XModel
> xModel( xDocument
, uno::UNO_QUERY
);
316 uno::Reference
< frame::XLoadable
> xLoadable( xModel
, uno::UNO_QUERY
);
317 if ( !xLoadable
.is() )
318 throw uno::RuntimeException();
322 // set the document mode to embedded as the first action on document!!!
323 EmbedAndReparentDoc_Impl( xDocument
);
325 // if we have a storage to recover the document from, do not use initNew, but instead load from that storage
326 bool bInitNew
= true;
327 if ( m_xRecoveryStorage
.is() )
329 uno::Reference
< document::XStorageBasedDocument
> xDoc( xLoadable
, uno::UNO_QUERY
);
330 SAL_WARN_IF( !xDoc
.is(), "embeddedobj.common", "OCommonEmbeddedObject::InitNewDocument_Impl: cannot recover from a storage when the document is not storage based!" );
333 ::comphelper::NamedValueCollection aLoadArgs
;
334 FillDefaultLoadArgs_Impl( m_xRecoveryStorage
, aLoadArgs
);
336 xDoc
->loadFromStorage( m_xRecoveryStorage
, aLoadArgs
.getPropertyValues() );
337 SwitchDocToStorage_Impl( xDoc
, m_xObjectStorage
);
344 // init document as a new
345 xLoadable
->initNew();
347 xModel
->attachResource( xModel
->getURL(), m_aDocMediaDescriptor
);
349 catch( const uno::Exception
& )
351 uno::Reference
< util::XCloseable
> xCloseable( xDocument
, uno::UNO_QUERY
);
352 if ( xCloseable
.is() )
356 xCloseable
->close( sal_True
);
358 catch( const uno::Exception
& )
370 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::LoadLink_Impl()
372 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
373 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
375 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY
);
376 if ( !xLoadable
.is() )
377 throw uno::RuntimeException();
380 uno::Sequence
< beans::PropertyValue
> aArgs( nLen
);
381 aArgs
[0].Name
= "URL";
382 aArgs
[0].Value
<<= m_aLinkURL
;
383 aArgs
[1].Name
= "FilterName";
384 aArgs
[1].Value
<<= m_aLinkFilterName
;
385 if ( m_bLinkHasPassword
)
387 aArgs
.realloc( ++nLen
);
388 aArgs
[nLen
-1].Name
= "Password";
389 aArgs
[nLen
-1].Value
<<= m_aLinkPassword
;
392 aArgs
.realloc( m_aDocMediaDescriptor
.getLength() + nLen
);
393 for ( sal_Int32 nInd
= 0; nInd
< m_aDocMediaDescriptor
.getLength(); nInd
++ )
395 aArgs
[nInd
+nLen
].Name
= m_aDocMediaDescriptor
[nInd
].Name
;
396 aArgs
[nInd
+nLen
].Value
= m_aDocMediaDescriptor
[nInd
].Value
;
401 // the document is not really an embedded one, it is a link
402 EmbedAndReparentDoc_Impl( xDocument
);
405 xLoadable
->load( aArgs
);
407 if ( !m_bLinkHasPassword
)
409 // check if there is a password to cache
410 uno::Reference
< frame::XModel
> xModel( xLoadable
, uno::UNO_QUERY_THROW
);
411 uno::Sequence
< beans::PropertyValue
> aProps
= xModel
->getArgs();
412 for ( sal_Int32 nInd
= 0; nInd
< aProps
.getLength(); nInd
++ )
413 if ( aProps
[nInd
].Name
== "Password" && ( aProps
[nInd
].Value
>>= m_aLinkPassword
) )
415 m_bLinkHasPassword
= true;
420 catch( const uno::Exception
& )
422 uno::Reference
< util::XCloseable
> xCloseable( xDocument
, uno::UNO_QUERY
);
423 if ( xCloseable
.is() )
427 xCloseable
->close( sal_True
);
429 catch( const uno::Exception
& )
442 OUString
OCommonEmbeddedObject::GetFilterName( sal_Int32 nVersion
) const
444 OUString aFilterName
= GetPresetFilterName();
445 if ( aFilterName
.isEmpty() )
448 ::comphelper::MimeConfigurationHelper
aHelper( m_xContext
);
449 aFilterName
= aHelper
.GetDefaultFilterFromServiceName( GetDocumentServiceName(), nVersion
);
451 // If no filter is found, fall back to the FileFormatVersion=6200 filter, Base only has that.
452 if (aFilterName
.isEmpty() && nVersion
== SOFFICE_FILEFORMAT_CURRENT
)
453 aFilterName
= aHelper
.GetDefaultFilterFromServiceName(GetDocumentServiceName(), SOFFICE_FILEFORMAT_60
);
454 } catch( const uno::Exception
& )
462 void OCommonEmbeddedObject::FillDefaultLoadArgs_Impl( const uno::Reference
< embed::XStorage
>& i_rxStorage
,
463 ::comphelper::NamedValueCollection
& o_rLoadArgs
) const
465 o_rLoadArgs
.put( "DocumentBaseURL", GetBaseURL_Impl() );
466 o_rLoadArgs
.put( "HierarchicalDocumentName", m_aEntryName
);
467 o_rLoadArgs
.put( "ReadOnly", m_bReadOnly
);
469 OUString aFilterName
= GetFilterName( ::comphelper::OStorageHelper::GetXStorageFormat( i_rxStorage
) );
470 SAL_WARN_IF( aFilterName
.isEmpty(), "embeddedobj.common", "OCommonEmbeddedObject::FillDefaultLoadArgs_Impl: Wrong document service name!" );
471 if ( aFilterName
.isEmpty() )
472 throw io::IOException(); // TODO: error message/code
474 o_rLoadArgs
.put( "FilterName", aFilterName
);
478 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::LoadDocumentFromStorage_Impl()
480 ENSURE_OR_THROW( m_xObjectStorage
.is(), "no object storage" );
482 const uno::Reference
< embed::XStorage
> xSourceStorage( m_xRecoveryStorage
.is() ? m_xRecoveryStorage
: m_xObjectStorage
);
484 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
485 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
487 //#i103460# ODF: take the size given from the parent frame as default
488 uno::Reference
< chart2::XChartDocument
> xChart( xDocument
, uno::UNO_QUERY
);
491 uno::Reference
< embed::XVisualObject
> xChartVisualObject( xChart
, uno::UNO_QUERY
);
492 if( xChartVisualObject
.is() )
493 xChartVisualObject
->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT
, m_aDefaultSizeForChart_In_100TH_MM
);
496 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY
);
497 uno::Reference
< document::XStorageBasedDocument
> xDoc( xDocument
, uno::UNO_QUERY
);
498 if ( !xDoc
.is() && !xLoadable
.is() ) ///BUG: This should be || instead of && ?
499 throw uno::RuntimeException();
501 ::comphelper::NamedValueCollection aLoadArgs
;
502 FillDefaultLoadArgs_Impl( xSourceStorage
, aLoadArgs
);
504 uno::Reference
< io::XInputStream
> xTempInpStream
;
507 xTempInpStream
= createTempInpStreamFromStor( xSourceStorage
, m_xContext
);
508 if ( !xTempInpStream
.is() )
509 throw uno::RuntimeException();
511 OUString aTempFileURL
;
514 // no need to let the file stay after the stream is removed since the embedded document
515 // can not be stored directly
516 uno::Reference
< beans::XPropertySet
> xTempStreamProps( xTempInpStream
, uno::UNO_QUERY_THROW
);
517 xTempStreamProps
->getPropertyValue("Uri") >>= aTempFileURL
;
519 catch( const uno::Exception
& )
523 SAL_WARN_IF( aTempFileURL
.isEmpty(), "embeddedobj.common", "Coudn't retrieve temporary file URL!" );
525 aLoadArgs
.put( "URL", aTempFileURL
);
526 aLoadArgs
.put( "InputStream", xTempInpStream
);
530 aLoadArgs
.merge( m_aDocMediaDescriptor
, true );
534 // set the document mode to embedded as the first step!!!
535 EmbedAndReparentDoc_Impl( xDocument
);
539 xDoc
->loadFromStorage( xSourceStorage
, aLoadArgs
.getPropertyValues() );
540 if ( xSourceStorage
!= m_xObjectStorage
)
541 SwitchDocToStorage_Impl( xDoc
, m_xObjectStorage
);
544 xLoadable
->load( aLoadArgs
.getPropertyValues() );
546 catch( const uno::Exception
& )
548 uno::Reference
< util::XCloseable
> xCloseable( xDocument
, uno::UNO_QUERY
);
549 if ( xCloseable
.is() )
553 xCloseable
->close( sal_True
);
555 catch( const uno::Exception
& )
557 DBG_UNHANDLED_EXCEPTION();
568 uno::Reference
< io::XInputStream
> OCommonEmbeddedObject::StoreDocumentToTempStream_Impl(
569 sal_Int32 nStorageFormat
,
570 const OUString
& aBaseURL
,
571 const OUString
& aHierarchName
)
573 uno::Reference
< io::XOutputStream
> xTempOut(
574 io::TempFile::create(m_xContext
),
575 uno::UNO_QUERY_THROW
);
576 uno::Reference
< io::XInputStream
> aResult( xTempOut
, uno::UNO_QUERY
);
579 throw uno::RuntimeException(); // TODO:
581 uno::Reference
< frame::XStorable
> xStorable
;
583 osl::MutexGuard
aGuard( m_aMutex
);
585 xStorable
= uno::Reference
< frame::XStorable
> ( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
588 if( !xStorable
.is() )
589 throw uno::RuntimeException(); // TODO:
591 OUString aFilterName
= GetFilterName( nStorageFormat
);
593 SAL_WARN_IF( aFilterName
.isEmpty(), "embeddedobj.common", "Wrong document service name!" );
594 if ( aFilterName
.isEmpty() )
595 throw io::IOException(); // TODO:
597 uno::Sequence
< beans::PropertyValue
> aArgs( 4 );
598 aArgs
[0].Name
= "FilterName";
599 aArgs
[0].Value
<<= aFilterName
;
600 aArgs
[1].Name
= "OutputStream";
601 aArgs
[1].Value
<<= xTempOut
;
602 aArgs
[2].Name
= "DocumentBaseURL";
603 aArgs
[2].Value
<<= aBaseURL
;
604 aArgs
[3].Name
= "HierarchicalDocumentName";
605 aArgs
[3].Value
<<= aHierarchName
;
607 xStorable
->storeToURL( OUString( "private:stream" ), aArgs
);
610 xTempOut
->closeOutput();
612 catch( const uno::Exception
& )
614 SAL_WARN( "embeddedobj.common", "Looks like stream was closed already" );
621 void OCommonEmbeddedObject::SaveObject_Impl()
623 if ( m_xClientSite
.is() )
627 // check whether the component is modified,
628 // if not there is no need for storing
629 uno::Reference
< util::XModifiable
> xModifiable( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
630 if ( xModifiable
.is() && !xModifiable
->isModified() )
633 catch( const uno::Exception
& )
637 m_xClientSite
->saveObject();
639 catch( const uno::Exception
& )
641 SAL_WARN( "embeddedobj.common", "The object was not stored!" );
647 OUString
OCommonEmbeddedObject::GetBaseURL_Impl() const
652 if ( m_xClientSite
.is() )
656 uno::Reference
< frame::XModel
> xParentModel( m_xClientSite
->getComponent(), uno::UNO_QUERY_THROW
);
657 uno::Sequence
< beans::PropertyValue
> aModelProps
= xParentModel
->getArgs();
658 for ( nInd
= 0; nInd
< aModelProps
.getLength(); nInd
++ )
659 if ( aModelProps
[nInd
].Name
== "DocumentBaseURL" )
661 aModelProps
[nInd
].Value
>>= aBaseURL
;
667 catch( const uno::Exception
& )
671 if ( aBaseURL
.isEmpty() )
673 for ( nInd
= 0; nInd
< m_aDocMediaDescriptor
.getLength(); nInd
++ )
674 if ( m_aDocMediaDescriptor
[nInd
].Name
== "DocumentBaseURL" )
676 m_aDocMediaDescriptor
[nInd
].Value
>>= aBaseURL
;
681 if ( aBaseURL
.isEmpty() )
682 aBaseURL
= m_aDefaultParentBaseURL
;
688 OUString
OCommonEmbeddedObject::GetBaseURLFrom_Impl(
689 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
690 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
695 for ( nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
696 if ( lArguments
[nInd
].Name
== "DocumentBaseURL" )
698 lArguments
[nInd
].Value
>>= aBaseURL
;
702 if ( aBaseURL
.isEmpty() )
704 for ( nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
705 if ( lObjArgs
[nInd
].Name
== "DefaultParentBaseURL" )
707 lObjArgs
[nInd
].Value
>>= aBaseURL
;
717 void OCommonEmbeddedObject::SwitchDocToStorage_Impl( const uno::Reference
< document::XStorageBasedDocument
>& xDoc
, const uno::Reference
< embed::XStorage
>& xStorage
)
719 xDoc
->switchToStorage( xStorage
);
721 uno::Reference
< util::XModifiable
> xModif( xDoc
, uno::UNO_QUERY
);
723 xModif
->setModified( sal_False
);
725 if ( m_xRecoveryStorage
.is() )
726 m_xRecoveryStorage
.clear();
731 OUString
getStringPropertyValue( const uno::Sequence
<beans::PropertyValue
>& rProps
, const OUString
& rName
)
735 for (sal_Int32 i
= 0; i
< rProps
.getLength(); ++i
)
737 if (rProps
[i
].Name
== rName
)
739 rProps
[i
].Value
>>= aStr
;
749 void OCommonEmbeddedObject::StoreDocToStorage_Impl(
750 const uno::Reference
<embed::XStorage
>& xStorage
,
751 const uno::Sequence
<beans::PropertyValue
>& rMediaArgs
,
752 const uno::Sequence
<beans::PropertyValue
>& rObjArgs
,
753 sal_Int32 nStorageFormat
,
754 const OUString
& aHierarchName
,
755 bool bAttachToTheStorage
)
757 SAL_WARN_IF( !xStorage
.is(), "embeddedobj.common", "No storage is provided for storing!" );
759 if ( !xStorage
.is() )
760 throw uno::RuntimeException(); // TODO:
762 uno::Reference
< document::XStorageBasedDocument
> xDoc
;
764 osl::MutexGuard
aGuard( m_aMutex
);
766 xDoc
= uno::Reference
< document::XStorageBasedDocument
>( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
769 OUString aBaseURL
= GetBaseURLFrom_Impl(rMediaArgs
, rObjArgs
);
773 OUString aFilterName
= GetFilterName( nStorageFormat
);
775 // No filter found? Try the older format, e.g. Base has only that.
776 if (aFilterName
.isEmpty() && nStorageFormat
== SOFFICE_FILEFORMAT_CURRENT
)
777 aFilterName
= GetFilterName( SOFFICE_FILEFORMAT_60
);
779 SAL_WARN_IF( aFilterName
.isEmpty(), "embeddedobj.common", "Wrong document service name!" );
780 if ( aFilterName
.isEmpty() )
781 throw io::IOException(); // TODO:
783 uno::Sequence
<beans::PropertyValue
> aArgs(5);
784 aArgs
[0].Name
= "FilterName";
785 aArgs
[0].Value
<<= aFilterName
;
786 aArgs
[1].Name
= "HierarchicalDocumentName";
787 aArgs
[1].Value
<<= aHierarchName
;
788 aArgs
[2].Name
= "DocumentBaseURL";
789 aArgs
[2].Value
<<= aBaseURL
;
790 aArgs
[3].Name
= "SourceShellID";
791 aArgs
[3].Value
<<= getStringPropertyValue(rObjArgs
, "SourceShellID");
792 aArgs
[4].Name
= "DestinationShellID";
793 aArgs
[4].Value
<<= getStringPropertyValue(rObjArgs
, "DestinationShellID");
795 xDoc
->storeToStorage( xStorage
, aArgs
);
796 if ( bAttachToTheStorage
)
797 SwitchDocToStorage_Impl( xDoc
, xStorage
);
801 // store document to temporary stream based on temporary file
802 uno::Reference
< io::XInputStream
> xTempIn
= StoreDocumentToTempStream_Impl( nStorageFormat
, aBaseURL
, aHierarchName
);
804 SAL_WARN_IF( !xTempIn
.is(), "embeddedobj.common", "The stream reference can not be empty!" );
806 // open storage based on document temporary file for reading
807 uno::Reference
< lang::XSingleServiceFactory
> xStorageFactory
= embed::StorageFactory::create(m_xContext
);
809 uno::Sequence
< uno::Any
> aArgs(1);
810 aArgs
[0] <<= xTempIn
;
811 uno::Reference
< embed::XStorage
> xTempStorage( xStorageFactory
->createInstanceWithArguments( aArgs
),
813 if ( !xTempStorage
.is() )
814 throw uno::RuntimeException(); // TODO:
816 // object storage must be committed automatically
817 xTempStorage
->copyToStorage( xStorage
);
822 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::CreateDocFromMediaDescr_Impl(
823 const uno::Sequence
< beans::PropertyValue
>& aMedDescr
)
825 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
826 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
828 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY
);
829 if ( !xLoadable
.is() )
830 throw uno::RuntimeException();
834 // set the document mode to embedded as the first action on the document!!!
835 EmbedAndReparentDoc_Impl( xDocument
);
837 xLoadable
->load( addAsTemplate( aMedDescr
) );
839 catch( const uno::Exception
& )
841 uno::Reference
< util::XCloseable
> xCloseable( xDocument
, uno::UNO_QUERY
);
842 if ( xCloseable
.is() )
846 xCloseable
->close( sal_True
);
848 catch( const uno::Exception
& )
860 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::CreateTempDocFromLink_Impl()
862 uno::Reference
< util::XCloseable
> xResult
;
864 SAL_WARN_IF( !m_bIsLink
, "embeddedobj.common", "The object is not a linked one!" );
866 uno::Sequence
< beans::PropertyValue
> aTempMediaDescr
;
868 sal_Int32 nStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
870 nStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
872 catch ( const beans::IllegalTypeException
& )
874 // the container just has an unknown type, use current file format
876 catch ( const uno::Exception
& )
878 SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
881 if ( m_pDocHolder
->GetComponent().is() )
883 aTempMediaDescr
.realloc( 4 );
885 // TODO/LATER: may be private:stream should be used as target URL
886 OUString aTempFileURL
;
887 uno::Reference
< io::XInputStream
> xTempStream
= StoreDocumentToTempStream_Impl( SOFFICE_FILEFORMAT_CURRENT
,
892 // no need to let the file stay after the stream is removed since the embedded document
893 // can not be stored directly
894 uno::Reference
< beans::XPropertySet
> xTempStreamProps( xTempStream
, uno::UNO_QUERY_THROW
);
895 xTempStreamProps
->getPropertyValue("Uri") >>= aTempFileURL
;
897 catch( const uno::Exception
& )
901 SAL_WARN_IF( aTempFileURL
.isEmpty(), "embeddedobj.common", "Couldn't retrieve temporary file URL!" );
903 aTempMediaDescr
[0].Name
= "URL";
904 aTempMediaDescr
[0].Value
<<= aTempFileURL
;
905 aTempMediaDescr
[1].Name
= "InputStream";
906 aTempMediaDescr
[1].Value
<<= xTempStream
;
907 aTempMediaDescr
[2].Name
= "FilterName";
908 aTempMediaDescr
[2].Value
<<= GetFilterName( nStorageFormat
);
909 aTempMediaDescr
[3].Name
= "AsTemplate";
910 aTempMediaDescr
[3].Value
<<= sal_True
;
914 aTempMediaDescr
.realloc( 2 );
915 aTempMediaDescr
[0].Name
= "URL";
916 aTempMediaDescr
[0].Value
<<= m_aLinkURL
;
917 aTempMediaDescr
[1].Name
= "FilterName";
918 aTempMediaDescr
[1].Value
<<= m_aLinkFilterName
;
921 xResult
= CreateDocFromMediaDescr_Impl( aTempMediaDescr
);
927 void SAL_CALL
OCommonEmbeddedObject::setPersistentEntry(
928 const uno::Reference
< embed::XStorage
>& xStorage
,
929 const OUString
& sEntName
,
930 sal_Int32 nEntryConnectionMode
,
931 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
932 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
933 throw ( lang::IllegalArgumentException
,
934 embed::WrongStateException
,
937 uno::RuntimeException
, std::exception
)
939 // the type of the object must be already set
940 // a kind of typedetection should be done in the factory
942 ::osl::MutexGuard
aGuard( m_aMutex
);
944 throw lang::DisposedException(); // TODO
946 if ( !xStorage
.is() )
947 throw lang::IllegalArgumentException( "No parent storage is provided!",
948 static_cast< ::cppu::OWeakObject
* >(this),
951 if ( sEntName
.isEmpty() )
952 throw lang::IllegalArgumentException( "Empty element name is provided!",
953 static_cast< ::cppu::OWeakObject
* >(this),
956 // May be LOADED should be forbidden here ???
957 if ( ( m_nObjectState
!= -1 || nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
958 && ( m_nObjectState
== -1 || nEntryConnectionMode
!= embed::EntryInitModes::NO_INIT
) )
960 // if the object is not loaded
961 // it can not get persistent representation without initialization
963 // if the object is loaded
964 // it can switch persistent representation only without initialization
966 throw embed::WrongStateException(
967 "Can't change persistent representation of activated object!",
968 static_cast< ::cppu::OWeakObject
* >(this) );
971 if ( m_bWaitSaveCompleted
)
973 if ( nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
975 // saveCompleted is expected, handle it accordingly
976 if ( m_xNewParentStorage
== xStorage
&& m_aNewEntryName
.equals( sEntName
) )
978 saveCompleted( sal_True
);
982 // if a completely different entry is provided, switch first back to the old persistence in saveCompleted
983 // and then switch to the target persistence
984 bool bSwitchFurther
= ( m_xParentStorage
!= xStorage
|| !m_aEntryName
.equals( sEntName
) );
985 saveCompleted( sal_False
);
986 if ( !bSwitchFurther
)
990 throw embed::WrongStateException(
991 "The object waits for saveCompleted() call!",
992 static_cast< ::cppu::OWeakObject
* >(this) );
995 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
996 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
997 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1000 m_aEntryName
= sEntName
;
1004 uno::Reference
< container::XNameAccess
> xNameAccess( xStorage
, uno::UNO_QUERY
);
1005 if ( !xNameAccess
.is() )
1006 throw uno::RuntimeException(); //TODO
1008 // detect entry existence
1009 bool bElExists
= xNameAccess
->hasByName( sEntName
);
1011 m_aDocMediaDescriptor
= GetValuableArgs_Impl( lArguments
,
1012 nEntryConnectionMode
!= embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT
);
1014 m_bReadOnly
= false;
1015 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
1016 if ( lArguments
[nInd
].Name
== "ReadOnly" )
1017 lArguments
[nInd
].Value
>>= m_bReadOnly
;
1019 // TODO: use lObjArgs for StoreVisualReplacement
1020 for ( sal_Int32 nObjInd
= 0; nObjInd
< lObjArgs
.getLength(); nObjInd
++ )
1021 if ( lObjArgs
[nObjInd
].Name
== "OutplaceDispatchInterceptor" )
1023 uno::Reference
< frame::XDispatchProviderInterceptor
> xDispatchInterceptor
;
1024 if ( lObjArgs
[nObjInd
].Value
>>= xDispatchInterceptor
)
1025 m_pDocHolder
->SetOutplaceDispatchInterceptor( xDispatchInterceptor
);
1027 else if ( lObjArgs
[nObjInd
].Name
== "DefaultParentBaseURL" )
1029 lObjArgs
[nObjInd
].Value
>>= m_aDefaultParentBaseURL
;
1031 else if ( lObjArgs
[nObjInd
].Name
== "Parent" )
1033 lObjArgs
[nObjInd
].Value
>>= m_xParent
;
1035 else if ( lObjArgs
[nObjInd
].Name
== "IndividualMiscStatus" )
1037 sal_Int64 nMiscStatus
=0;
1038 lObjArgs
[nObjInd
].Value
>>= nMiscStatus
;
1039 m_nMiscStatus
|= nMiscStatus
;
1041 else if ( lObjArgs
[nObjInd
].Name
== "CloneFrom" )
1043 uno::Reference
< embed::XEmbeddedObject
> xObj
;
1044 lObjArgs
[nObjInd
].Value
>>= xObj
;
1047 m_bHasClonedSize
= true;
1048 m_aClonedSize
= xObj
->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
1049 m_nClonedMapUnit
= xObj
->getMapUnit( embed::Aspects::MSOLE_CONTENT
);
1052 else if ( lObjArgs
[nObjInd
].Name
== "OutplaceFrameProperties" )
1054 uno::Sequence
< uno::Any
> aOutFrameProps
;
1055 uno::Sequence
< beans::NamedValue
> aOutFramePropsTyped
;
1056 if ( lObjArgs
[nObjInd
].Value
>>= aOutFrameProps
)
1058 m_pDocHolder
->SetOutplaceFrameProperties( aOutFrameProps
);
1060 else if ( lObjArgs
[nObjInd
].Value
>>= aOutFramePropsTyped
)
1062 aOutFrameProps
.realloc( aOutFramePropsTyped
.getLength() );
1063 uno::Any
* pProp
= aOutFrameProps
.getArray();
1064 for ( const beans::NamedValue
* pTypedProp
= aOutFramePropsTyped
.getConstArray();
1065 pTypedProp
!= aOutFramePropsTyped
.getConstArray() + aOutFramePropsTyped
.getLength();
1066 ++pTypedProp
, ++pProp
1069 *pProp
<<= *pTypedProp
;
1071 m_pDocHolder
->SetOutplaceFrameProperties( aOutFrameProps
);
1074 SAL_WARN( "embeddedobj.common", "OCommonEmbeddedObject::setPersistentEntry: illegal type for argument 'OutplaceFrameProperties'!" );
1076 else if ( lObjArgs
[nObjInd
].Name
== "ModuleName" )
1078 lObjArgs
[nObjInd
].Value
>>= m_aModuleName
;
1080 else if ( lObjArgs
[nObjInd
].Name
== "EmbeddedScriptSupport" )
1082 OSL_VERIFY( lObjArgs
[nObjInd
].Value
>>= m_bEmbeddedScriptSupport
);
1084 else if ( lObjArgs
[nObjInd
].Name
== "DocumentRecoverySupport" )
1086 OSL_VERIFY( lObjArgs
[nObjInd
].Value
>>= m_bDocumentRecoverySupport
);
1088 else if ( lObjArgs
[nObjInd
].Name
== "RecoveryStorage" )
1090 OSL_VERIFY( lObjArgs
[nObjInd
].Value
>>= m_xRecoveryStorage
);
1094 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
1096 SwitchOwnPersistence( xStorage
, sEntName
);
1098 if ( nEntryConnectionMode
== embed::EntryInitModes::DEFAULT_INIT
)
1102 // the initialization from existing storage allows to leave object in loaded state
1103 m_nObjectState
= embed::EmbedStates::LOADED
;
1107 m_pDocHolder
->SetComponent( InitNewDocument_Impl(), m_bReadOnly
);
1108 if ( !m_pDocHolder
->GetComponent().is() )
1109 throw io::IOException(); // TODO: can not create document
1111 m_nObjectState
= embed::EmbedStates::RUNNING
;
1116 if ( ( nStorageMode
& embed::ElementModes::READWRITE
) != embed::ElementModes::READWRITE
)
1117 throw io::IOException();
1119 if ( nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
1121 // the document just already changed its storage to store to
1122 // the links to OOo documents for now ignore this call
1123 // TODO: OOo links will have persistence so it will be switched here
1125 else if ( nEntryConnectionMode
== embed::EntryInitModes::TRUNCATE_INIT
)
1127 if ( m_xRecoveryStorage
.is() )
1128 TransferMediaType( m_xRecoveryStorage
, m_xObjectStorage
);
1131 m_pDocHolder
->SetComponent( InitNewDocument_Impl(), m_bReadOnly
);
1133 if ( !m_pDocHolder
->GetComponent().is() )
1134 throw io::IOException(); // TODO: can not create document
1136 m_nObjectState
= embed::EmbedStates::RUNNING
;
1138 else if ( nEntryConnectionMode
== embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT
)
1140 m_pDocHolder
->SetComponent( CreateDocFromMediaDescr_Impl( lArguments
), m_bReadOnly
);
1141 m_nObjectState
= embed::EmbedStates::RUNNING
;
1143 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1148 throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
1149 static_cast< ::cppu::OWeakObject
* >(this),
1155 void SAL_CALL
OCommonEmbeddedObject::storeToEntry( const uno::Reference
< embed::XStorage
>& xStorage
,
1156 const OUString
& sEntName
,
1157 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1158 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1159 throw ( lang::IllegalArgumentException
,
1160 embed::WrongStateException
,
1163 uno::RuntimeException
, std::exception
)
1165 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1167 throw lang::DisposedException(); // TODO
1169 if ( m_nObjectState
== -1 )
1171 // the object is still not loaded
1172 throw embed::WrongStateException( "Can't store object without persistence!",
1173 static_cast< ::cppu::OWeakObject
* >(this) );
1176 if ( m_bWaitSaveCompleted
)
1177 throw embed::WrongStateException(
1178 "The object waits for saveCompleted() call!",
1179 static_cast< ::cppu::OWeakObject
* >(this) );
1181 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1182 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1183 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1187 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStorage
.is(), "The object has no valid persistence!\n" );
1189 sal_Int32 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1190 sal_Int32 nOriginalStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1192 nTargetStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( xStorage
);
1194 catch ( const beans::IllegalTypeException
& )
1196 // the container just has an unknown type, use current file format
1198 catch ( const uno::Exception
& )
1200 SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
1202 if (nTargetStorageFormat
== SOFFICE_FILEFORMAT_60
)
1204 SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
1205 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1206 // setting MediaType is done later anyway, no need to do it here
1211 nOriginalStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
1213 catch ( const beans::IllegalTypeException
& )
1215 // the container just has an unknown type, use current file format
1217 catch ( const uno::Exception
& )
1219 SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
1222 bool bTryOptimization
= false;
1223 for ( sal_Int32 nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
1225 // StoreVisualReplacement and VisualReplacement args have no sense here
1226 if ( lObjArgs
[nInd
].Name
== "CanTryOptimization" )
1227 lObjArgs
[nInd
].Value
>>= bTryOptimization
;
1230 bool bSwitchBackToLoaded
= false;
1232 // Storing to different format can be done only in running state.
1233 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1235 // TODO/LATER: copying is not legal for documents with relative links.
1236 if ( nTargetStorageFormat
== nOriginalStorageFormat
)
1238 bool bOptimizationWorks
= false;
1239 if ( bTryOptimization
)
1243 // try to use optimized copying
1244 uno::Reference
< embed::XOptimizedStorage
> xSource( m_xParentStorage
, uno::UNO_QUERY_THROW
);
1245 uno::Reference
< embed::XOptimizedStorage
> xTarget( xStorage
, uno::UNO_QUERY_THROW
);
1246 xSource
->copyElementDirectlyTo( m_aEntryName
, xTarget
, sEntName
);
1247 bOptimizationWorks
= true;
1249 catch( const uno::Exception
& )
1254 if ( !bOptimizationWorks
)
1255 m_xParentStorage
->copyElementTo( m_aEntryName
, xStorage
, sEntName
);
1259 changeState( embed::EmbedStates::RUNNING
);
1260 bSwitchBackToLoaded
= true;
1264 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
1266 uno::Reference
< embed::XStorage
> xSubStorage
=
1267 xStorage
->openStorageElement( sEntName
, embed::ElementModes::READWRITE
);
1269 if ( !xSubStorage
.is() )
1270 throw uno::RuntimeException(); //TODO
1273 // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1274 StoreDocToStorage_Impl(
1275 xSubStorage
, lArguments
, lObjArgs
, nTargetStorageFormat
, sEntName
, false );
1278 if ( bSwitchBackToLoaded
)
1279 changeState( embed::EmbedStates::LOADED
);
1282 // TODO: should the listener notification be done?
1286 void SAL_CALL
OCommonEmbeddedObject::storeAsEntry( const uno::Reference
< embed::XStorage
>& xStorage
,
1287 const OUString
& sEntName
,
1288 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1289 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1290 throw ( lang::IllegalArgumentException
,
1291 embed::WrongStateException
,
1294 uno::RuntimeException
, std::exception
)
1296 // TODO: use lObjArgs
1298 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1300 throw lang::DisposedException(); // TODO
1302 if ( m_nObjectState
== -1 )
1304 // the object is still not loaded
1305 throw embed::WrongStateException( "Can't store object without persistence!",
1306 static_cast< ::cppu::OWeakObject
* >(this) );
1309 if ( m_bWaitSaveCompleted
)
1310 throw embed::WrongStateException(
1311 "The object waits for saveCompleted() call!",
1312 static_cast< ::cppu::OWeakObject
* >(this) );
1314 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1315 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1316 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1319 m_aNewEntryName
= sEntName
;
1323 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStorage
.is(), "The object has no valid persistence!\n" );
1325 sal_Int32 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1326 sal_Int32 nOriginalStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1328 nTargetStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( xStorage
);
1330 catch ( const beans::IllegalTypeException
& )
1332 // the container just has an unknown type, use current file format
1334 catch ( const uno::Exception
& )
1336 SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
1338 if (nTargetStorageFormat
== SOFFICE_FILEFORMAT_60
)
1340 SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
1341 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1342 // setting MediaType is done later anyway, no need to do it here
1347 nOriginalStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
1349 catch ( const beans::IllegalTypeException
& )
1351 // the container just has an unknown type, use current file format
1353 catch ( const uno::Exception
& )
1355 SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
1358 PostEvent_Impl( OUString( "OnSaveAs" ) );
1360 bool bTryOptimization
= false;
1361 for ( sal_Int32 nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
1363 // StoreVisualReplacement and VisualReplacement args have no sense here
1364 if ( lObjArgs
[nInd
].Name
== "CanTryOptimization" )
1365 lObjArgs
[nInd
].Value
>>= bTryOptimization
;
1368 bool bSwitchBackToLoaded
= false;
1370 // Storing to different format can be done only in running state.
1371 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1373 // TODO/LATER: copying is not legal for documents with relative links.
1374 if ( nTargetStorageFormat
== nOriginalStorageFormat
)
1376 bool bOptimizationWorks
= false;
1377 if ( bTryOptimization
)
1381 // try to use optimized copying
1382 uno::Reference
< embed::XOptimizedStorage
> xSource( m_xParentStorage
, uno::UNO_QUERY_THROW
);
1383 uno::Reference
< embed::XOptimizedStorage
> xTarget( xStorage
, uno::UNO_QUERY_THROW
);
1384 xSource
->copyElementDirectlyTo( m_aEntryName
, xTarget
, sEntName
);
1385 bOptimizationWorks
= true;
1387 catch( const uno::Exception
& )
1392 if ( !bOptimizationWorks
)
1393 m_xParentStorage
->copyElementTo( m_aEntryName
, xStorage
, sEntName
);
1397 changeState( embed::EmbedStates::RUNNING
);
1398 bSwitchBackToLoaded
= true;
1402 uno::Reference
< embed::XStorage
> xSubStorage
=
1403 xStorage
->openStorageElement( sEntName
, embed::ElementModes::READWRITE
);
1405 if ( !xSubStorage
.is() )
1406 throw uno::RuntimeException(); //TODO
1408 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
1411 // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1412 StoreDocToStorage_Impl(
1413 xSubStorage
, lArguments
, lObjArgs
, nTargetStorageFormat
, sEntName
, false );
1416 if ( bSwitchBackToLoaded
)
1417 changeState( embed::EmbedStates::LOADED
);
1420 m_bWaitSaveCompleted
= true;
1421 m_xNewObjectStorage
= xSubStorage
;
1422 m_xNewParentStorage
= xStorage
;
1423 m_aNewEntryName
= sEntName
;
1424 m_aNewDocMediaDescriptor
= GetValuableArgs_Impl( lArguments
, true );
1426 // TODO: register listeners for storages above, in case thay are disposed
1427 // an exception will be thrown on saveCompleted( true )
1429 // TODO: should the listener notification be done here or in saveCompleted?
1433 void SAL_CALL
OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew
)
1434 throw ( embed::WrongStateException
,
1436 uno::RuntimeException
, std::exception
)
1438 ::osl::MutexGuard
aGuard( m_aMutex
);
1440 throw lang::DisposedException(); // TODO
1442 if ( m_nObjectState
== -1 )
1444 // the object is still not loaded
1445 throw embed::WrongStateException( "Can't store object without persistence!",
1446 static_cast< ::cppu::OWeakObject
* >(this) );
1449 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1450 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1451 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1455 m_aEntryName
= m_aNewEntryName
;
1456 m_aNewEntryName
.clear();
1460 // it is allowed to call saveCompleted( false ) for nonstored objects
1461 if ( !m_bWaitSaveCompleted
&& !bUseNew
)
1464 SAL_WARN_IF( !m_bWaitSaveCompleted
, "embeddedobj.common", "Unexpected saveCompleted() call!" );
1465 if ( !m_bWaitSaveCompleted
)
1466 throw io::IOException(); // TODO: illegal call
1468 OSL_ENSURE( m_xNewObjectStorage
.is() && m_xNewParentStorage
.is() , "Internal object information is broken!\n" );
1469 if ( !m_xNewObjectStorage
.is() || !m_xNewParentStorage
.is() )
1470 throw uno::RuntimeException(); // TODO: broken internal information
1474 SwitchOwnPersistence( m_xNewParentStorage
, m_xNewObjectStorage
, m_aNewEntryName
);
1475 m_aDocMediaDescriptor
= m_aNewDocMediaDescriptor
;
1477 uno::Reference
< util::XModifiable
> xModif( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
1479 xModif
->setModified( sal_False
);
1481 PostEvent_Impl( OUString( "OnSaveAsDone" ));
1486 uno::Reference
< lang::XComponent
> xComponent( m_xNewObjectStorage
, uno::UNO_QUERY
);
1487 SAL_WARN_IF( !xComponent
.is(), "embeddedobj.common", "Wrong storage implementation!" );
1488 if ( xComponent
.is() )
1489 xComponent
->dispose();
1491 catch ( const uno::Exception
& )
1496 m_xNewObjectStorage
= uno::Reference
< embed::XStorage
>();
1497 m_xNewParentStorage
= uno::Reference
< embed::XStorage
>();
1498 m_aNewEntryName
.clear();
1499 m_aNewDocMediaDescriptor
.realloc( 0 );
1500 m_bWaitSaveCompleted
= false;
1504 // TODO: notify listeners
1506 if ( m_nUpdateMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
)
1508 // TODO: update visual representation
1514 sal_Bool SAL_CALL
OCommonEmbeddedObject::hasEntry()
1515 throw ( embed::WrongStateException
,
1516 uno::RuntimeException
, std::exception
)
1518 ::osl::MutexGuard
aGuard( m_aMutex
);
1520 throw lang::DisposedException(); // TODO
1522 if ( m_bWaitSaveCompleted
)
1523 throw embed::WrongStateException(
1524 "The object waits for saveCompleted() call!",
1525 static_cast< ::cppu::OWeakObject
* >(this) );
1527 if ( m_xObjectStorage
.is() )
1534 OUString SAL_CALL
OCommonEmbeddedObject::getEntryName()
1535 throw ( embed::WrongStateException
,
1536 uno::RuntimeException
, std::exception
)
1538 ::osl::MutexGuard
aGuard( m_aMutex
);
1540 throw lang::DisposedException(); // TODO
1542 if ( m_nObjectState
== -1 )
1544 // the object is still not loaded
1545 throw embed::WrongStateException( "The object persistence is not initialized!",
1546 static_cast< ::cppu::OWeakObject
* >(this) );
1549 if ( m_bWaitSaveCompleted
)
1550 throw embed::WrongStateException(
1551 "The object waits for saveCompleted() call!",
1552 static_cast< ::cppu::OWeakObject
* >(this) );
1554 return m_aEntryName
;
1558 void SAL_CALL
OCommonEmbeddedObject::storeOwn()
1559 throw ( embed::WrongStateException
,
1562 uno::RuntimeException
, std::exception
)
1564 // during switching from Activated to Running and from Running to Loaded states the object will
1565 // ask container to store the object, the container has to make decision
1568 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1570 throw lang::DisposedException(); // TODO
1572 if ( m_nObjectState
== -1 )
1574 // the object is still not loaded
1575 throw embed::WrongStateException( "Can't store object without persistence!",
1576 static_cast< ::cppu::OWeakObject
* >(this) );
1579 if ( m_bWaitSaveCompleted
)
1580 throw embed::WrongStateException(
1581 "The object waits for saveCompleted() call!",
1582 static_cast< ::cppu::OWeakObject
* >(this) );
1585 throw io::IOException(); // TODO: access denied
1587 // nothing to do, if the object is in loaded state
1588 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1591 PostEvent_Impl( OUString( "OnSave" ) );
1593 SAL_WARN_IF( !m_pDocHolder
->GetComponent().is(), "embeddedobj.common", "If an object is activated or in running state it must have a document!" );
1594 if ( !m_pDocHolder
->GetComponent().is() )
1595 throw uno::RuntimeException();
1599 // TODO: just store the document to it's location
1600 uno::Reference
< frame::XStorable
> xStorable( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
1601 if ( !xStorable
.is() )
1602 throw uno::RuntimeException(); // TODO
1604 // free the main mutex for the storing time
1613 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStorage
.is(), "The object has no valid persistence!\n" );
1615 if ( !m_xObjectStorage
.is() )
1616 throw io::IOException(); //TODO: access denied
1618 sal_Int32 nStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1620 nStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
1622 catch ( const beans::IllegalTypeException
& )
1624 // the container just has an unknown type, use current file format
1626 catch ( const uno::Exception
& )
1628 SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
1630 if (nStorageFormat
== SOFFICE_FILEFORMAT_60
)
1632 SAL_INFO("embeddedobj.common", "fdo#78159: Storing OOoXML as ODF");
1633 nStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1634 // setting MediaType is done later anyway, no need to do it here
1638 uno::Sequence
<beans::PropertyValue
> aEmpty
;
1639 uno::Sequence
<beans::PropertyValue
> aMediaArgs(1);
1640 aMediaArgs
[0].Name
= "DocumentBaseURL";
1641 aMediaArgs
[0].Value
<<= GetBaseURL_Impl();
1642 StoreDocToStorage_Impl( m_xObjectStorage
, aMediaArgs
, aEmpty
, nStorageFormat
, m_aEntryName
, true );
1646 uno::Reference
< util::XModifiable
> xModif( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
1648 xModif
->setModified( sal_False
);
1650 PostEvent_Impl( OUString( "OnSaveDone" ) );
1654 sal_Bool SAL_CALL
OCommonEmbeddedObject::isReadonly()
1655 throw ( embed::WrongStateException
,
1656 uno::RuntimeException
, std::exception
)
1658 ::osl::MutexGuard
aGuard( m_aMutex
);
1660 throw lang::DisposedException(); // TODO
1662 if ( m_nObjectState
== -1 )
1664 // the object is still not loaded
1665 throw embed::WrongStateException( "The object persistence is not initialized!",
1666 static_cast< ::cppu::OWeakObject
* >(this) );
1669 if ( m_bWaitSaveCompleted
)
1670 throw embed::WrongStateException(
1671 "The object waits for saveCompleted() call!",
1672 static_cast< ::cppu::OWeakObject
* >(this) );
1678 void SAL_CALL
OCommonEmbeddedObject::reload(
1679 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1680 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1681 throw ( lang::IllegalArgumentException
,
1682 embed::WrongStateException
,
1685 uno::RuntimeException
, std::exception
)
1687 // TODO: use lObjArgs
1688 // for now this method is used only to switch readonly state
1690 ::osl::MutexGuard
aGuard( m_aMutex
);
1692 throw lang::DisposedException(); // TODO
1694 if ( m_nObjectState
== -1 )
1696 // the object is still not loaded
1697 throw embed::WrongStateException( "The object persistence is not initialized!",
1698 static_cast< ::cppu::OWeakObject
* >(this) );
1701 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
1703 // the object is still not loaded
1704 throw embed::WrongStateException(
1705 "The object must be in loaded state to be reloaded!",
1706 static_cast< ::cppu::OWeakObject
* >(this) );
1709 if ( m_bWaitSaveCompleted
)
1710 throw embed::WrongStateException(
1711 "The object waits for saveCompleted() call!",
1712 static_cast< ::cppu::OWeakObject
* >(this) );
1716 // reload of the link
1717 OUString aOldLinkFilter
= m_aLinkFilterName
;
1719 OUString aNewLinkFilter
;
1720 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
1722 if ( lArguments
[nInd
].Name
== "URL" )
1725 lArguments
[nInd
].Value
>>= m_aLinkURL
;
1726 m_aLinkFilterName
.clear();
1728 else if ( lArguments
[nInd
].Name
== "FilterName" )
1730 lArguments
[nInd
].Value
>>= aNewLinkFilter
;
1731 m_aLinkFilterName
.clear();
1735 ::comphelper::MimeConfigurationHelper
aHelper( m_xContext
);
1736 if ( m_aLinkFilterName
.isEmpty() )
1738 if ( !aNewLinkFilter
.isEmpty() )
1739 m_aLinkFilterName
= aNewLinkFilter
;
1742 uno::Sequence
< beans::PropertyValue
> aArgs( 1 );
1743 aArgs
[0].Name
= "URL";
1744 aArgs
[0].Value
<<= m_aLinkURL
;
1745 m_aLinkFilterName
= aHelper
.UpdateMediaDescriptorWithFilterName( aArgs
, false );
1749 if ( !aOldLinkFilter
.equals( m_aLinkFilterName
) )
1751 uno::Sequence
< beans::NamedValue
> aObject
= aHelper
.GetObjectPropsByFilter( m_aLinkFilterName
);
1753 // TODO/LATER: probably the document holder could be cleaned explicitly as in the destructor
1754 m_pDocHolder
->release();
1755 m_pDocHolder
= NULL
;
1757 LinkInit_Impl( aObject
, lArguments
, lObjArgs
);
1761 m_aDocMediaDescriptor
= GetValuableArgs_Impl( lArguments
, true );
1763 // TODO: use lObjArgs for StoreVisualReplacement
1764 for ( sal_Int32 nObjInd
= 0; nObjInd
< lObjArgs
.getLength(); nObjInd
++ )
1765 if ( lObjArgs
[nObjInd
].Name
== "OutplaceDispatchInterceptor" )
1767 uno::Reference
< frame::XDispatchProviderInterceptor
> xDispatchInterceptor
;
1768 if ( lObjArgs
[nObjInd
].Value
>>= xDispatchInterceptor
)
1769 m_pDocHolder
->SetOutplaceDispatchInterceptor( xDispatchInterceptor
);
1775 // when document allows reloading through API the object can be reloaded not only in loaded state
1777 bool bOldReadOnlyValue
= m_bReadOnly
;
1779 m_bReadOnly
= false;
1780 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
1781 if ( lArguments
[nInd
].Name
== "ReadOnly" )
1782 lArguments
[nInd
].Value
>>= m_bReadOnly
;
1784 if ( bOldReadOnlyValue
!= m_bReadOnly
&& !m_bIsLink
)
1786 // close own storage
1788 uno::Reference
< lang::XComponent
> xComponent( m_xObjectStorage
, uno::UNO_QUERY
);
1789 OSL_ENSURE( !m_xObjectStorage
.is() || xComponent
.is(), "Wrong storage implementation!" );
1790 if ( xComponent
.is() )
1791 xComponent
->dispose();
1793 catch ( const uno::Exception
& )
1797 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
1798 m_xObjectStorage
= m_xParentStorage
->openStorageElement( m_aEntryName
, nStorageMode
);
1802 sal_Bool SAL_CALL
OCommonEmbeddedObject::isStored() throw (css::uno::RuntimeException
, std::exception
)
1804 uno::Reference
<container::XNameAccess
> xNA(m_xObjectStorage
, uno::UNO_QUERY
);
1808 return xNA
->getElementNames().getLength() > 0;
1812 void SAL_CALL
OCommonEmbeddedObject::breakLink( const uno::Reference
< embed::XStorage
>& xStorage
,
1813 const OUString
& sEntName
)
1814 throw ( lang::IllegalArgumentException
,
1815 embed::WrongStateException
,
1818 uno::RuntimeException
, std::exception
)
1820 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1822 throw lang::DisposedException(); // TODO
1826 // it must be a linked initialized object
1827 throw embed::WrongStateException(
1828 "The object is not a valid linked object!",
1829 static_cast< ::cppu::OWeakObject
* >(this) );
1833 // the current implementation of OOo links does not implement this method since it does not implement
1834 // all the set of interfaces required for OOo embedded object ( XEmbedPersist is not supported ).
1837 if ( !xStorage
.is() )
1838 throw lang::IllegalArgumentException( "No parent storage is provided!",
1839 static_cast< ::cppu::OWeakObject
* >(this),
1842 if ( sEntName
.isEmpty() )
1843 throw lang::IllegalArgumentException( "Empty element name is provided!",
1844 static_cast< ::cppu::OWeakObject
* >(this),
1847 if ( !m_bIsLink
|| m_nObjectState
== -1 )
1849 // it must be a linked initialized object
1850 throw embed::WrongStateException(
1851 "The object is not a valid linked object!",
1852 static_cast< ::cppu::OWeakObject
* >(this) );
1855 if ( m_bWaitSaveCompleted
)
1856 throw embed::WrongStateException(
1857 "The object waits for saveCompleted() call!",
1858 static_cast< ::cppu::OWeakObject
* >(this) );
1860 uno::Reference
< container::XNameAccess
> xNameAccess( xStorage
, uno::UNO_QUERY
);
1861 if ( !xNameAccess
.is() )
1862 throw uno::RuntimeException(); //TODO
1864 m_bReadOnly
= false;
1866 if ( m_xParentStorage
!= xStorage
|| !m_aEntryName
.equals( sEntName
) )
1867 SwitchOwnPersistence( xStorage
, sEntName
);
1869 // for linked object it means that it becomes embedded object
1870 // the document must switch it's persistence also
1872 // TODO/LATER: handle the case when temp doc can not be created
1873 // the document is a new embedded object so it must be marked as modified
1874 uno::Reference
< util::XCloseable
> xDocument
= CreateTempDocFromLink_Impl();
1875 uno::Reference
< util::XModifiable
> xModif( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
1877 throw uno::RuntimeException();
1880 xModif
->setModified( sal_True
);
1882 catch( const uno::Exception
& )
1885 m_pDocHolder
->SetComponent( xDocument
, m_bReadOnly
);
1886 SAL_WARN_IF( !m_pDocHolder
->GetComponent().is(), "embeddedobj.common", "If document can't be created, an exception must be thrown!" );
1888 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1890 // the state is changed and can not be switched to loaded state back without saving
1891 m_nObjectState
= embed::EmbedStates::RUNNING
;
1892 StateChangeNotification_Impl( false, embed::EmbedStates::LOADED
, m_nObjectState
, aGuard
);
1894 else if ( m_nObjectState
== embed::EmbedStates::ACTIVE
)
1895 m_pDocHolder
->Show();
1898 m_aLinkFilterName
.clear();
1903 sal_Bool SAL_CALL
OCommonEmbeddedObject::isLink()
1904 throw ( embed::WrongStateException
,
1905 uno::RuntimeException
, std::exception
)
1907 ::osl::MutexGuard
aGuard( m_aMutex
);
1909 throw lang::DisposedException(); // TODO
1915 OUString SAL_CALL
OCommonEmbeddedObject::getLinkURL()
1916 throw ( embed::WrongStateException
,
1918 uno::RuntimeException
, std::exception
)
1920 ::osl::MutexGuard
aGuard( m_aMutex
);
1922 throw lang::DisposedException(); // TODO
1925 throw embed::WrongStateException(
1926 "The object is not a link object!",
1927 static_cast< ::cppu::OWeakObject
* >(this) );
1932 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */