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>
57 using namespace ::com::sun::star
;
60 //------------------------------------------------------
61 uno::Sequence
< beans::PropertyValue
> GetValuableArgs_Impl( const uno::Sequence
< beans::PropertyValue
>& aMedDescr
,
62 sal_Bool bCanUseDocumentBaseURL
)
64 uno::Sequence
< beans::PropertyValue
> aResult
;
65 sal_Int32 nResLen
= 0;
67 for ( sal_Int32 nInd
= 0; nInd
< aMedDescr
.getLength(); nInd
++ )
69 if ( aMedDescr
[nInd
].Name
== "ComponentData" || aMedDescr
[nInd
].Name
== "DocumentTitle"
70 || aMedDescr
[nInd
].Name
== "InteractionHandler" || aMedDescr
[nInd
].Name
== "JumpMark"
71 // || aMedDescr[nInd].Name == "Password" // makes no sence for embedded objects
72 || aMedDescr
[nInd
].Name
== "Preview" || aMedDescr
[nInd
].Name
== "ReadOnly"
73 || aMedDescr
[nInd
].Name
== "StartPresentation" || aMedDescr
[nInd
].Name
== "RepairPackage"
74 || aMedDescr
[nInd
].Name
== "StatusIndicator" || aMedDescr
[nInd
].Name
== "ViewData"
75 || aMedDescr
[nInd
].Name
== "ViewId" || aMedDescr
[nInd
].Name
== "MacroExecutionMode"
76 || aMedDescr
[nInd
].Name
== "UpdateDocMode"
77 || (aMedDescr
[nInd
].Name
== "DocumentBaseURL" && bCanUseDocumentBaseURL
) )
79 aResult
.realloc( ++nResLen
);
80 aResult
[nResLen
-1] = aMedDescr
[nInd
];
87 //------------------------------------------------------
88 uno::Sequence
< beans::PropertyValue
> addAsTemplate( const uno::Sequence
< beans::PropertyValue
>& aOrig
)
90 sal_Bool bAsTemplateSet
= sal_False
;
91 sal_Int32 nLength
= aOrig
.getLength();
92 uno::Sequence
< beans::PropertyValue
> aResult( nLength
);
94 for ( sal_Int32 nInd
= 0; nInd
< nLength
; nInd
++ )
96 aResult
[nInd
].Name
= aOrig
[nInd
].Name
;
97 if ( aResult
[nInd
].Name
== "AsTemplate" )
99 aResult
[nInd
].Value
<<= sal_True
;
100 bAsTemplateSet
= sal_True
;
103 aResult
[nInd
].Value
= aOrig
[nInd
].Value
;
106 if ( !bAsTemplateSet
)
108 aResult
.realloc( nLength
+ 1 );
109 aResult
[nLength
].Name
= "AsTemplate";
110 aResult
[nLength
].Value
<<= sal_True
;
116 //------------------------------------------------------
117 uno::Reference
< io::XInputStream
> createTempInpStreamFromStor(
118 const uno::Reference
< embed::XStorage
>& xStorage
,
119 const uno::Reference
< uno::XComponentContext
>& xContext
)
121 SAL_WARN_IF( !xStorage
.is(), "embeddedobj.common", "The storage can not be empty!" );
123 uno::Reference
< io::XInputStream
> xResult
;
125 uno::Reference
< io::XStream
> xTempStream( io::TempFile::create(xContext
), uno::UNO_QUERY_THROW
);
127 uno::Reference
< lang::XSingleServiceFactory
> xStorageFactory( embed::StorageFactory::create(xContext
) );
129 uno::Sequence
< uno::Any
> aArgs( 2 );
130 aArgs
[0] <<= xTempStream
;
131 aArgs
[1] <<= embed::ElementModes::READWRITE
;
132 uno::Reference
< embed::XStorage
> xTempStorage( xStorageFactory
->createInstanceWithArguments( aArgs
),
134 if ( !xTempStorage
.is() )
135 throw uno::RuntimeException(); // TODO:
139 xStorage
->copyToStorage( xTempStorage
);
140 } catch( const uno::Exception
& e
)
142 throw embed::StorageWrappedTargetException(
143 OUString( "Can't copy storage!" ),
144 uno::Reference
< uno::XInterface
>(),
149 uno::Reference
< lang::XComponent
> xComponent( xTempStorage
, uno::UNO_QUERY
);
150 SAL_WARN_IF( !xComponent
.is(), "embeddedobj.common", "Wrong storage implementation!" );
151 if ( xComponent
.is() )
152 xComponent
->dispose();
154 catch ( const uno::Exception
& )
159 uno::Reference
< io::XOutputStream
> xTempOut
= xTempStream
->getOutputStream();
161 xTempOut
->closeOutput();
163 catch ( const uno::Exception
& )
167 xResult
= xTempStream
->getInputStream();
173 //------------------------------------------------------
174 static void TransferMediaType( const uno::Reference
< embed::XStorage
>& i_rSource
, const uno::Reference
< embed::XStorage
>& i_rTarget
)
178 const uno::Reference
< beans::XPropertySet
> xSourceProps( i_rSource
, uno::UNO_QUERY_THROW
);
179 const uno::Reference
< beans::XPropertySet
> xTargetProps( i_rTarget
, uno::UNO_QUERY_THROW
);
180 const OUString
sMediaTypePropName( "MediaType" );
181 xTargetProps
->setPropertyValue( sMediaTypePropName
, xSourceProps
->getPropertyValue( sMediaTypePropName
) );
183 catch( const uno::Exception
& )
185 DBG_UNHANDLED_EXCEPTION();
189 //------------------------------------------------------
190 static uno::Reference
< util::XCloseable
> CreateDocument( const uno::Reference
< uno::XComponentContext
>& _rxContext
,
191 const OUString
& _rDocumentServiceName
, bool _bEmbeddedScriptSupport
, const bool i_bDocumentRecoverySupport
)
193 ::comphelper::NamedValueCollection aArguments
;
194 aArguments
.put( "EmbeddedObject", (sal_Bool
)sal_True
);
195 aArguments
.put( "EmbeddedScriptSupport", (sal_Bool
)_bEmbeddedScriptSupport
);
196 aArguments
.put( "DocumentRecoverySupport", (sal_Bool
)i_bDocumentRecoverySupport
);
198 uno::Reference
< uno::XInterface
> xDocument
;
201 xDocument
= _rxContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
202 _rDocumentServiceName
, aArguments
.getWrappedPropertyValues(), _rxContext
);
204 catch( const uno::Exception
& )
206 // if an embedded object implementation does not support XInitialization,
207 // the default factory from cppuhelper will throw an
208 // IllegalArgumentException when we try to create the instance with arguments.
209 // Okay, so we fall back to creating the instance without any arguments.
210 OSL_ASSERT("Consider implementing interface XInitialization to avoid duplicate construction");
211 xDocument
= _rxContext
->getServiceManager()->createInstanceWithContext( _rDocumentServiceName
, _rxContext
);
214 SAL_WARN_IF(!xDocument
.is(), "embeddedobj.common", "Service " << _rDocumentServiceName
<< " is not available?");
215 return uno::Reference
< util::XCloseable
>( xDocument
, uno::UNO_QUERY
);
218 //------------------------------------------------------
219 static void SetDocToEmbedded( const uno::Reference
< frame::XModel
> xDocument
, const OUString
& aModuleName
)
221 if ( xDocument
.is() )
223 uno::Sequence
< beans::PropertyValue
> aSeq( 1 );
224 aSeq
[0].Name
= "SetEmbedded";
225 aSeq
[0].Value
<<= sal_True
;
226 xDocument
->attachResource( OUString(), aSeq
);
228 if ( !aModuleName
.isEmpty() )
232 uno::Reference
< frame::XModule
> xModule( xDocument
, uno::UNO_QUERY_THROW
);
233 xModule
->setIdentifier( aModuleName
);
235 catch( const uno::Exception
& )
241 //------------------------------------------------------
242 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference
< embed::XStorage
>& xNewParentStorage
,
243 const uno::Reference
< embed::XStorage
>& xNewObjectStorage
,
244 const OUString
& aNewName
)
246 if ( xNewParentStorage
== m_xParentStorage
&& aNewName
.equals( m_aEntryName
) )
248 SAL_WARN_IF( xNewObjectStorage
!= m_xObjectStorage
, "embeddedobj.common", "The storage must be the same!" );
252 uno::Reference
< lang::XComponent
> xComponent( m_xObjectStorage
, uno::UNO_QUERY
);
253 OSL_ENSURE( !m_xObjectStorage
.is() || xComponent
.is(), "Wrong storage implementation!" );
255 m_xObjectStorage
= xNewObjectStorage
;
256 m_xParentStorage
= xNewParentStorage
;
257 m_aEntryName
= aNewName
;
259 // the linked document should not be switched
262 uno::Reference
< document::XStorageBasedDocument
> xDoc( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
264 SwitchDocToStorage_Impl( xDoc
, m_xObjectStorage
);
268 if ( xComponent
.is() )
269 xComponent
->dispose();
271 catch ( const uno::Exception
& )
276 //------------------------------------------------------
277 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference
< embed::XStorage
>& xNewParentStorage
,
278 const OUString
& aNewName
)
280 if ( xNewParentStorage
== m_xParentStorage
&& aNewName
.equals( m_aEntryName
) )
283 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
285 uno::Reference
< embed::XStorage
> xNewOwnStorage
= xNewParentStorage
->openStorageElement( aNewName
, nStorageMode
);
286 SAL_WARN_IF( !xNewOwnStorage
.is(), "embeddedobj.common", "The method can not return empty reference!" );
288 SwitchOwnPersistence( xNewParentStorage
, xNewOwnStorage
, aNewName
);
291 //------------------------------------------------------
292 void OCommonEmbeddedObject::EmbedAndReparentDoc_Impl( const uno::Reference
< util::XCloseable
>& i_rxDocument
) const
294 SetDocToEmbedded( uno::Reference
< frame::XModel
>( i_rxDocument
, uno::UNO_QUERY
), m_aModuleName
);
298 uno::Reference
< container::XChild
> xChild( i_rxDocument
, uno::UNO_QUERY
);
300 xChild
->setParent( m_xParent
);
302 catch( const lang::NoSupportException
& )
304 SAL_WARN( "embeddedobj.common", "OCommonEmbeddedObject::EmbedAndReparentDoc: cannot set parent at document!" );
308 //------------------------------------------------------
309 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::InitNewDocument_Impl()
311 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
312 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
314 uno::Reference
< frame::XModel
> xModel( xDocument
, uno::UNO_QUERY
);
315 uno::Reference
< frame::XLoadable
> xLoadable( xModel
, uno::UNO_QUERY
);
316 if ( !xLoadable
.is() )
317 throw uno::RuntimeException();
321 // set the document mode to embedded as the first action on document!!!
322 EmbedAndReparentDoc_Impl( xDocument
);
324 // if we have a storage to recover the document from, do not use initNew, but instead load from that storage
325 bool bInitNew
= true;
326 if ( m_xRecoveryStorage
.is() )
328 uno::Reference
< document::XStorageBasedDocument
> xDoc( xLoadable
, uno::UNO_QUERY
);
329 SAL_WARN_IF( !xDoc
.is(), "embeddedobj.common", "OCommonEmbeddedObject::InitNewDocument_Impl: cannot recover from a storage when the document is not storage based!" );
332 ::comphelper::NamedValueCollection aLoadArgs
;
333 FillDefaultLoadArgs_Impl( m_xRecoveryStorage
, aLoadArgs
);
335 xDoc
->loadFromStorage( m_xRecoveryStorage
, aLoadArgs
.getPropertyValues() );
336 SwitchDocToStorage_Impl( xDoc
, m_xObjectStorage
);
343 // init document as a new
344 xLoadable
->initNew();
346 xModel
->attachResource( xModel
->getURL(), m_aDocMediaDescriptor
);
348 catch( const uno::Exception
& )
350 uno::Reference
< util::XCloseable
> xCloseable( xDocument
, uno::UNO_QUERY
);
351 if ( xCloseable
.is() )
355 xCloseable
->close( sal_True
);
357 catch( const uno::Exception
& )
368 //------------------------------------------------------
369 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::LoadLink_Impl()
371 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
372 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
374 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY
);
375 if ( !xLoadable
.is() )
376 throw uno::RuntimeException();
379 uno::Sequence
< beans::PropertyValue
> aArgs( nLen
);
380 aArgs
[0].Name
= "URL";
381 aArgs
[0].Value
<<= m_aLinkURL
;
382 aArgs
[1].Name
= "FilterName";
383 aArgs
[1].Value
<<= m_aLinkFilterName
;
384 if ( m_bLinkHasPassword
)
386 aArgs
.realloc( ++nLen
);
387 aArgs
[nLen
-1].Name
= "Password";
388 aArgs
[nLen
-1].Value
<<= m_aLinkPassword
;
391 aArgs
.realloc( m_aDocMediaDescriptor
.getLength() + nLen
);
392 for ( sal_Int32 nInd
= 0; nInd
< m_aDocMediaDescriptor
.getLength(); nInd
++ )
394 aArgs
[nInd
+nLen
].Name
= m_aDocMediaDescriptor
[nInd
].Name
;
395 aArgs
[nInd
+nLen
].Value
= m_aDocMediaDescriptor
[nInd
].Value
;
400 // the document is not really an embedded one, it is a link
401 EmbedAndReparentDoc_Impl( xDocument
);
404 xLoadable
->load( aArgs
);
406 if ( !m_bLinkHasPassword
)
408 // check if there is a password to cache
409 uno::Reference
< frame::XModel
> xModel( xLoadable
, uno::UNO_QUERY_THROW
);
410 uno::Sequence
< beans::PropertyValue
> aProps
= xModel
->getArgs();
411 for ( sal_Int32 nInd
= 0; nInd
< aProps
.getLength(); nInd
++ )
412 if ( aProps
[nInd
].Name
== "Password" && ( aProps
[nInd
].Value
>>= m_aLinkPassword
) )
414 m_bLinkHasPassword
= sal_True
;
419 catch( const uno::Exception
& )
421 uno::Reference
< util::XCloseable
> xCloseable( xDocument
, uno::UNO_QUERY
);
422 if ( xCloseable
.is() )
426 xCloseable
->close( sal_True
);
428 catch( const uno::Exception
& )
440 //------------------------------------------------------
441 OUString
OCommonEmbeddedObject::GetFilterName( sal_Int32 nVersion
) const
443 OUString aFilterName
= GetPresetFilterName();
444 if ( aFilterName
.isEmpty() )
447 ::comphelper::MimeConfigurationHelper
aHelper( m_xContext
);
448 aFilterName
= aHelper
.GetDefaultFilterFromServiceName( GetDocumentServiceName(), nVersion
);
449 } catch( const uno::Exception
& )
456 //------------------------------------------------------
457 void OCommonEmbeddedObject::FillDefaultLoadArgs_Impl( const uno::Reference
< embed::XStorage
>& i_rxStorage
,
458 ::comphelper::NamedValueCollection
& o_rLoadArgs
) const
460 o_rLoadArgs
.put( "DocumentBaseURL", GetBaseURL_Impl() );
461 o_rLoadArgs
.put( "HierarchicalDocumentName", m_aEntryName
);
462 o_rLoadArgs
.put( "ReadOnly", m_bReadOnly
);
464 OUString aFilterName
= GetFilterName( ::comphelper::OStorageHelper::GetXStorageFormat( i_rxStorage
) );
465 SAL_WARN_IF( aFilterName
.isEmpty(), "embeddedobj.common", "OCommonEmbeddedObject::FillDefaultLoadArgs_Impl: Wrong document service name!" );
466 if ( aFilterName
.isEmpty() )
467 throw io::IOException(); // TODO: error message/code
469 o_rLoadArgs
.put( "FilterName", aFilterName
);
472 //------------------------------------------------------
473 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::LoadDocumentFromStorage_Impl()
475 ENSURE_OR_THROW( m_xObjectStorage
.is(), "no object storage" );
477 const uno::Reference
< embed::XStorage
> xSourceStorage( m_xRecoveryStorage
.is() ? m_xRecoveryStorage
: m_xObjectStorage
);
479 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
480 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
482 //#i103460# ODF: take the size given from the parent frame as default
483 uno::Reference
< chart2::XChartDocument
> xChart( xDocument
, uno::UNO_QUERY
);
486 uno::Reference
< embed::XVisualObject
> xChartVisualObject( xChart
, uno::UNO_QUERY
);
487 if( xChartVisualObject
.is() )
488 xChartVisualObject
->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT
, m_aDefaultSizeForChart_In_100TH_MM
);
491 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY
);
492 uno::Reference
< document::XStorageBasedDocument
> xDoc( xDocument
, uno::UNO_QUERY
);
493 if ( !xDoc
.is() && !xLoadable
.is() ) ///BUG: This should be || instead of && ?
494 throw uno::RuntimeException();
496 ::comphelper::NamedValueCollection aLoadArgs
;
497 FillDefaultLoadArgs_Impl( xSourceStorage
, aLoadArgs
);
499 uno::Reference
< io::XInputStream
> xTempInpStream
;
502 xTempInpStream
= createTempInpStreamFromStor( xSourceStorage
, m_xContext
);
503 if ( !xTempInpStream
.is() )
504 throw uno::RuntimeException();
506 OUString aTempFileURL
;
509 // no need to let the file stay after the stream is removed since the embedded document
510 // can not be stored directly
511 uno::Reference
< beans::XPropertySet
> xTempStreamProps( xTempInpStream
, uno::UNO_QUERY_THROW
);
512 xTempStreamProps
->getPropertyValue("Uri") >>= aTempFileURL
;
514 catch( const uno::Exception
& )
518 SAL_WARN_IF( aTempFileURL
.isEmpty(), "embeddedobj.common", "Coudn't retrieve temporary file URL!" );
520 aLoadArgs
.put( "URL", aTempFileURL
);
521 aLoadArgs
.put( "InputStream", xTempInpStream
);
525 aLoadArgs
.merge( m_aDocMediaDescriptor
, true );
529 // set the document mode to embedded as the first step!!!
530 EmbedAndReparentDoc_Impl( xDocument
);
534 xDoc
->loadFromStorage( xSourceStorage
, aLoadArgs
.getPropertyValues() );
535 if ( xSourceStorage
!= m_xObjectStorage
)
536 SwitchDocToStorage_Impl( xDoc
, m_xObjectStorage
);
539 xLoadable
->load( aLoadArgs
.getPropertyValues() );
541 catch( const uno::Exception
& )
543 uno::Reference
< util::XCloseable
> xCloseable( xDocument
, uno::UNO_QUERY
);
544 if ( xCloseable
.is() )
548 xCloseable
->close( sal_True
);
550 catch( const uno::Exception
& )
552 DBG_UNHANDLED_EXCEPTION();
562 //------------------------------------------------------
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
);
574 throw uno::RuntimeException(); // TODO:
576 uno::Reference
< frame::XStorable
> xStorable
;
578 osl::MutexGuard
aGuard( m_aMutex
);
580 xStorable
= uno::Reference
< frame::XStorable
> ( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
583 if( !xStorable
.is() )
584 throw uno::RuntimeException(); // TODO:
586 OUString aFilterName
= GetFilterName( nStorageFormat
);
588 SAL_WARN_IF( aFilterName
.isEmpty(), "embeddedobj.common", "Wrong document service name!" );
589 if ( aFilterName
.isEmpty() )
590 throw io::IOException(); // TODO:
592 uno::Sequence
< beans::PropertyValue
> aArgs( 4 );
593 aArgs
[0].Name
= "FilterName";
594 aArgs
[0].Value
<<= aFilterName
;
595 aArgs
[1].Name
= "OutputStream";
596 aArgs
[1].Value
<<= xTempOut
;
597 aArgs
[2].Name
= "DocumentBaseURL";
598 aArgs
[2].Value
<<= aBaseURL
;
599 aArgs
[3].Name
= "HierarchicalDocumentName";
600 aArgs
[3].Value
<<= aHierarchName
;
602 xStorable
->storeToURL( OUString( "private:stream" ), aArgs
);
605 xTempOut
->closeOutput();
607 catch( const uno::Exception
& )
609 SAL_WARN( "embeddedobj.common", "Looks like stream was closed already" );
615 //------------------------------------------------------
616 void OCommonEmbeddedObject::SaveObject_Impl()
618 if ( m_xClientSite
.is() )
622 // check whether the component is modified,
623 // if not there is no need for storing
624 uno::Reference
< util::XModifiable
> xModifiable( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
625 if ( xModifiable
.is() && !xModifiable
->isModified() )
628 catch( const uno::Exception
& )
632 m_xClientSite
->saveObject();
634 catch( const uno::Exception
& )
636 SAL_WARN( "embeddedobj.common", "The object was not stored!" );
641 //------------------------------------------------------
642 OUString
OCommonEmbeddedObject::GetBaseURL_Impl() const
647 if ( m_xClientSite
.is() )
651 uno::Reference
< frame::XModel
> xParentModel( m_xClientSite
->getComponent(), uno::UNO_QUERY_THROW
);
652 uno::Sequence
< beans::PropertyValue
> aModelProps
= xParentModel
->getArgs();
653 for ( nInd
= 0; nInd
< aModelProps
.getLength(); nInd
++ )
654 if ( aModelProps
[nInd
].Name
.equals(
655 OUString( "DocumentBaseURL" ) ) )
657 aModelProps
[nInd
].Value
>>= aBaseURL
;
663 catch( const uno::Exception
& )
667 if ( aBaseURL
.isEmpty() )
669 for ( nInd
= 0; nInd
< m_aDocMediaDescriptor
.getLength(); nInd
++ )
670 if ( m_aDocMediaDescriptor
[nInd
].Name
.equals(
671 OUString( "DocumentBaseURL" ) ) )
673 m_aDocMediaDescriptor
[nInd
].Value
>>= aBaseURL
;
678 if ( aBaseURL
.isEmpty() )
679 aBaseURL
= m_aDefaultParentBaseURL
;
684 //------------------------------------------------------
685 OUString
OCommonEmbeddedObject::GetBaseURLFrom_Impl(
686 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
687 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
692 for ( nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
693 if ( lArguments
[nInd
].Name
== "DocumentBaseURL" )
695 lArguments
[nInd
].Value
>>= aBaseURL
;
699 if ( aBaseURL
.isEmpty() )
701 for ( nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
702 if ( lObjArgs
[nInd
].Name
== "DefaultParentBaseURL" )
704 lObjArgs
[nInd
].Value
>>= aBaseURL
;
713 //------------------------------------------------------
714 void OCommonEmbeddedObject::SwitchDocToStorage_Impl( const uno::Reference
< document::XStorageBasedDocument
>& xDoc
, const uno::Reference
< embed::XStorage
>& xStorage
)
716 xDoc
->switchToStorage( xStorage
);
718 uno::Reference
< util::XModifiable
> xModif( xDoc
, uno::UNO_QUERY
);
720 xModif
->setModified( sal_False
);
722 if ( m_xRecoveryStorage
.is() )
723 m_xRecoveryStorage
.clear();
726 //------------------------------------------------------
727 void OCommonEmbeddedObject::StoreDocToStorage_Impl( const uno::Reference
< embed::XStorage
>& xStorage
,
728 sal_Int32 nStorageFormat
,
729 const OUString
& aBaseURL
,
730 const OUString
& aHierarchName
,
731 sal_Bool bAttachToTheStorage
)
733 SAL_WARN_IF( !xStorage
.is(), "embeddedobj.common", "No storage is provided for storing!" );
735 if ( !xStorage
.is() )
736 throw uno::RuntimeException(); // TODO:
738 uno::Reference
< document::XStorageBasedDocument
> xDoc
;
740 osl::MutexGuard
aGuard( m_aMutex
);
742 xDoc
= uno::Reference
< document::XStorageBasedDocument
>( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
747 OUString aFilterName
= GetFilterName( nStorageFormat
);
749 SAL_WARN_IF( aFilterName
.isEmpty(), "embeddedobj.common", "Wrong document service name!" );
750 if ( aFilterName
.isEmpty() )
751 throw io::IOException(); // TODO:
753 uno::Sequence
< beans::PropertyValue
> aArgs( 3 );
754 aArgs
[0].Name
= "FilterName";
755 aArgs
[0].Value
<<= aFilterName
;
756 aArgs
[2].Name
= "DocumentBaseURL";
757 aArgs
[2].Value
<<= aBaseURL
;
758 aArgs
[1].Name
= "HierarchicalDocumentName";
759 aArgs
[1].Value
<<= aHierarchName
;
761 xDoc
->storeToStorage( xStorage
, aArgs
);
762 if ( bAttachToTheStorage
)
763 SwitchDocToStorage_Impl( xDoc
, xStorage
);
767 // store document to temporary stream based on temporary file
768 uno::Reference
< io::XInputStream
> xTempIn
= StoreDocumentToTempStream_Impl( nStorageFormat
, aBaseURL
, aHierarchName
);
770 SAL_WARN_IF( !xTempIn
.is(), "embeddedobj.common", "The stream reference can not be empty!" );
772 // open storage based on document temporary file for reading
773 uno::Reference
< lang::XSingleServiceFactory
> xStorageFactory
= embed::StorageFactory::create(m_xContext
);
775 uno::Sequence
< uno::Any
> aArgs(1);
776 aArgs
[0] <<= xTempIn
;
777 uno::Reference
< embed::XStorage
> xTempStorage( xStorageFactory
->createInstanceWithArguments( aArgs
),
779 if ( !xTempStorage
.is() )
780 throw uno::RuntimeException(); // TODO:
782 // object storage must be commited automatically
783 xTempStorage
->copyToStorage( xStorage
);
787 //------------------------------------------------------
788 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::CreateDocFromMediaDescr_Impl(
789 const uno::Sequence
< beans::PropertyValue
>& aMedDescr
)
791 uno::Reference
< util::XCloseable
> xDocument( CreateDocument( m_xContext
, GetDocumentServiceName(),
792 m_bEmbeddedScriptSupport
, m_bDocumentRecoverySupport
) );
794 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY
);
795 if ( !xLoadable
.is() )
796 throw uno::RuntimeException();
800 // set the document mode to embedded as the first action on the document!!!
801 EmbedAndReparentDoc_Impl( xDocument
);
803 xLoadable
->load( addAsTemplate( aMedDescr
) );
805 catch( const uno::Exception
& )
807 uno::Reference
< util::XCloseable
> xCloseable( xDocument
, uno::UNO_QUERY
);
808 if ( xCloseable
.is() )
812 xCloseable
->close( sal_True
);
814 catch( const uno::Exception
& )
825 //------------------------------------------------------
826 uno::Reference
< util::XCloseable
> OCommonEmbeddedObject::CreateTempDocFromLink_Impl()
828 uno::Reference
< util::XCloseable
> xResult
;
830 SAL_WARN_IF( !m_bIsLink
, "embeddedobj.common", "The object is not a linked one!" );
832 uno::Sequence
< beans::PropertyValue
> aTempMediaDescr
;
834 sal_Int32 nStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
836 nStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
838 catch ( const beans::IllegalTypeException
& )
840 // the container just has an unknown type, use current file format
842 catch ( const uno::Exception
& )
844 SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
847 if ( m_pDocHolder
->GetComponent().is() )
849 aTempMediaDescr
.realloc( 4 );
851 // TODO/LATER: may be private:stream should be used as target URL
852 OUString aTempFileURL
;
853 uno::Reference
< io::XInputStream
> xTempStream
= StoreDocumentToTempStream_Impl( SOFFICE_FILEFORMAT_CURRENT
,
858 // no need to let the file stay after the stream is removed since the embedded document
859 // can not be stored directly
860 uno::Reference
< beans::XPropertySet
> xTempStreamProps( xTempStream
, uno::UNO_QUERY_THROW
);
861 xTempStreamProps
->getPropertyValue("Uri") >>= aTempFileURL
;
863 catch( const uno::Exception
& )
867 SAL_WARN_IF( aTempFileURL
.isEmpty(), "embeddedobj.common", "Couldn't retrieve temporary file URL!" );
869 aTempMediaDescr
[0].Name
= "URL";
870 aTempMediaDescr
[0].Value
<<= aTempFileURL
;
871 aTempMediaDescr
[1].Name
= "InputStream";
872 aTempMediaDescr
[1].Value
<<= xTempStream
;
873 aTempMediaDescr
[2].Name
= "FilterName";
874 aTempMediaDescr
[2].Value
<<= GetFilterName( nStorageFormat
);
875 aTempMediaDescr
[3].Name
= "AsTemplate";
876 aTempMediaDescr
[3].Value
<<= sal_True
;
880 aTempMediaDescr
.realloc( 2 );
881 aTempMediaDescr
[0].Name
= "URL";
882 aTempMediaDescr
[0].Value
<<= m_aLinkURL
;
883 aTempMediaDescr
[1].Name
= "FilterName";
884 aTempMediaDescr
[1].Value
<<= m_aLinkFilterName
;
887 xResult
= CreateDocFromMediaDescr_Impl( aTempMediaDescr
);
892 //------------------------------------------------------
893 void SAL_CALL
OCommonEmbeddedObject::setPersistentEntry(
894 const uno::Reference
< embed::XStorage
>& xStorage
,
895 const OUString
& sEntName
,
896 sal_Int32 nEntryConnectionMode
,
897 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
898 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
899 throw ( lang::IllegalArgumentException
,
900 embed::WrongStateException
,
903 uno::RuntimeException
)
905 SAL_INFO( "embeddedobj.common", "embeddedobj (mv76033) OCommonEmbeddedObject::setPersistentEntry" );
907 // the type of the object must be already set
908 // a kind of typedetection should be done in the factory
910 ::osl::MutexGuard
aGuard( m_aMutex
);
912 throw lang::DisposedException(); // TODO
914 if ( !xStorage
.is() )
915 throw lang::IllegalArgumentException( OUString( "No parent storage is provided!\n" ),
916 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ),
919 if ( sEntName
.isEmpty() )
920 throw lang::IllegalArgumentException( OUString( "Empty element name is provided!\n" ),
921 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ),
924 // May be LOADED should be forbidden here ???
925 if ( ( m_nObjectState
!= -1 || nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
926 && ( m_nObjectState
== -1 || nEntryConnectionMode
!= embed::EntryInitModes::NO_INIT
) )
928 // if the object is not loaded
929 // it can not get persistent representation without initialization
931 // if the object is loaded
932 // it can switch persistent representation only without initialization
934 throw embed::WrongStateException(
935 OUString( "Can't change persistent representation of activated object!\n" ),
936 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
939 if ( m_bWaitSaveCompleted
)
941 if ( nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
943 // saveCompleted is expected, handle it accordingly
944 if ( m_xNewParentStorage
== xStorage
&& m_aNewEntryName
.equals( sEntName
) )
946 saveCompleted( sal_True
);
950 // if a completely different entry is provided, switch first back to the old persistence in saveCompleted
951 // and then switch to the target persistence
952 sal_Bool bSwitchFurther
= ( m_xParentStorage
!= xStorage
|| !m_aEntryName
.equals( sEntName
) );
953 saveCompleted( sal_False
);
954 if ( !bSwitchFurther
)
958 throw embed::WrongStateException(
959 OUString( "The object waits for saveCompleted() call!\n" ),
960 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
963 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
964 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
965 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
968 m_aEntryName
= sEntName
;
972 uno::Reference
< container::XNameAccess
> xNameAccess( xStorage
, uno::UNO_QUERY
);
973 if ( !xNameAccess
.is() )
974 throw uno::RuntimeException(); //TODO
976 // detect entry existence
977 sal_Bool bElExists
= xNameAccess
->hasByName( sEntName
);
979 m_aDocMediaDescriptor
= GetValuableArgs_Impl( lArguments
,
980 nEntryConnectionMode
!= embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT
);
982 m_bReadOnly
= sal_False
;
983 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
984 if ( lArguments
[nInd
].Name
== "ReadOnly" )
985 lArguments
[nInd
].Value
>>= m_bReadOnly
;
987 // TODO: use lObjArgs for StoreVisualReplacement
988 for ( sal_Int32 nObjInd
= 0; nObjInd
< lObjArgs
.getLength(); nObjInd
++ )
989 if ( lObjArgs
[nObjInd
].Name
== "OutplaceDispatchInterceptor" )
991 uno::Reference
< frame::XDispatchProviderInterceptor
> xDispatchInterceptor
;
992 if ( lObjArgs
[nObjInd
].Value
>>= xDispatchInterceptor
)
993 m_pDocHolder
->SetOutplaceDispatchInterceptor( xDispatchInterceptor
);
995 else if ( lObjArgs
[nObjInd
].Name
== "DefaultParentBaseURL" )
997 lObjArgs
[nObjInd
].Value
>>= m_aDefaultParentBaseURL
;
999 else if ( lObjArgs
[nObjInd
].Name
== "Parent" )
1001 lObjArgs
[nObjInd
].Value
>>= m_xParent
;
1003 else if ( lObjArgs
[nObjInd
].Name
== "IndividualMiscStatus" )
1005 sal_Int64 nMiscStatus
=0;
1006 lObjArgs
[nObjInd
].Value
>>= nMiscStatus
;
1007 m_nMiscStatus
|= nMiscStatus
;
1009 else if ( lObjArgs
[nObjInd
].Name
== "CloneFrom" )
1011 uno::Reference
< embed::XEmbeddedObject
> xObj
;
1012 lObjArgs
[nObjInd
].Value
>>= xObj
;
1015 m_bHasClonedSize
= sal_True
;
1016 m_aClonedSize
= xObj
->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
1017 m_nClonedMapUnit
= xObj
->getMapUnit( embed::Aspects::MSOLE_CONTENT
);
1020 else if ( lObjArgs
[nObjInd
].Name
== "OutplaceFrameProperties" )
1022 uno::Sequence
< uno::Any
> aOutFrameProps
;
1023 uno::Sequence
< beans::NamedValue
> aOutFramePropsTyped
;
1024 if ( lObjArgs
[nObjInd
].Value
>>= aOutFrameProps
)
1026 m_pDocHolder
->SetOutplaceFrameProperties( aOutFrameProps
);
1028 else if ( lObjArgs
[nObjInd
].Value
>>= aOutFramePropsTyped
)
1030 aOutFrameProps
.realloc( aOutFramePropsTyped
.getLength() );
1031 uno::Any
* pProp
= aOutFrameProps
.getArray();
1032 for ( const beans::NamedValue
* pTypedProp
= aOutFramePropsTyped
.getConstArray();
1033 pTypedProp
!= aOutFramePropsTyped
.getConstArray() + aOutFramePropsTyped
.getLength();
1034 ++pTypedProp
, ++pProp
1037 *pProp
<<= *pTypedProp
;
1039 m_pDocHolder
->SetOutplaceFrameProperties( aOutFrameProps
);
1042 SAL_WARN( "embeddedobj.common", "OCommonEmbeddedObject::setPersistentEntry: illegal type for argument 'OutplaceFrameProperties'!" );
1044 else if ( lObjArgs
[nObjInd
].Name
== "ModuleName" )
1046 lObjArgs
[nObjInd
].Value
>>= m_aModuleName
;
1048 else if ( lObjArgs
[nObjInd
].Name
== "EmbeddedScriptSupport" )
1050 OSL_VERIFY( lObjArgs
[nObjInd
].Value
>>= m_bEmbeddedScriptSupport
);
1052 else if ( lObjArgs
[nObjInd
].Name
== "DocumentRecoverySupport" )
1054 OSL_VERIFY( lObjArgs
[nObjInd
].Value
>>= m_bDocumentRecoverySupport
);
1056 else if ( lObjArgs
[nObjInd
].Name
== "RecoveryStorage" )
1058 OSL_VERIFY( lObjArgs
[nObjInd
].Value
>>= m_xRecoveryStorage
);
1062 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
1064 SwitchOwnPersistence( xStorage
, sEntName
);
1066 if ( nEntryConnectionMode
== embed::EntryInitModes::DEFAULT_INIT
)
1070 // the initialization from existing storage allows to leave object in loaded state
1071 m_nObjectState
= embed::EmbedStates::LOADED
;
1075 m_pDocHolder
->SetComponent( InitNewDocument_Impl(), m_bReadOnly
);
1076 if ( !m_pDocHolder
->GetComponent().is() )
1077 throw io::IOException(); // TODO: can not create document
1079 m_nObjectState
= embed::EmbedStates::RUNNING
;
1084 if ( ( nStorageMode
& embed::ElementModes::READWRITE
) != embed::ElementModes::READWRITE
)
1085 throw io::IOException();
1087 if ( nEntryConnectionMode
== embed::EntryInitModes::NO_INIT
)
1089 // the document just already changed its storage to store to
1090 // the links to OOo documents for now ignore this call
1091 // TODO: OOo links will have persistence so it will be switched here
1093 else if ( nEntryConnectionMode
== embed::EntryInitModes::TRUNCATE_INIT
)
1095 if ( m_xRecoveryStorage
.is() )
1096 TransferMediaType( m_xRecoveryStorage
, m_xObjectStorage
);
1099 m_pDocHolder
->SetComponent( InitNewDocument_Impl(), m_bReadOnly
);
1101 if ( !m_pDocHolder
->GetComponent().is() )
1102 throw io::IOException(); // TODO: can not create document
1104 m_nObjectState
= embed::EmbedStates::RUNNING
;
1106 else if ( nEntryConnectionMode
== embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT
)
1108 m_pDocHolder
->SetComponent( CreateDocFromMediaDescr_Impl( lArguments
), m_bReadOnly
);
1109 m_nObjectState
= embed::EmbedStates::RUNNING
;
1111 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1116 throw lang::IllegalArgumentException( OUString( "Wrong connection mode is provided!\n" ),
1117 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ),
1122 //------------------------------------------------------
1123 void SAL_CALL
OCommonEmbeddedObject::storeToEntry( const uno::Reference
< embed::XStorage
>& xStorage
,
1124 const OUString
& sEntName
,
1125 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1126 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1127 throw ( lang::IllegalArgumentException
,
1128 embed::WrongStateException
,
1131 uno::RuntimeException
)
1133 SAL_INFO( "embeddedobj.common", "embeddedobj (mv76033) OCommonEmbeddedObject::storeToEntry" );
1135 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1137 throw lang::DisposedException(); // TODO
1139 if ( m_nObjectState
== -1 )
1141 // the object is still not loaded
1142 throw embed::WrongStateException( OUString( "Can't store object without persistence!\n" ),
1143 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1146 if ( m_bWaitSaveCompleted
)
1147 throw embed::WrongStateException(
1148 OUString( "The object waits for saveCompleted() call!\n" ),
1149 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1151 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1152 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1153 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1157 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStorage
.is(), "The object has no valid persistence!\n" );
1159 sal_Int32 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1160 sal_Int32 nOriginalStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1162 nTargetStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( xStorage
);
1164 catch ( const beans::IllegalTypeException
& )
1166 // the container just has an unknown type, use current file format
1168 catch ( const uno::Exception
& )
1170 SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
1175 nOriginalStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
1177 catch ( const beans::IllegalTypeException
& )
1179 // the container just has an unknown type, use current file format
1181 catch ( const uno::Exception
& )
1183 SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
1186 sal_Bool bTryOptimization
= sal_False
;
1187 for ( sal_Int32 nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
1189 // StoreVisualReplacement and VisualReplacement args have no sence here
1190 if ( lObjArgs
[nInd
].Name
== "CanTryOptimization" )
1191 lObjArgs
[nInd
].Value
>>= bTryOptimization
;
1194 sal_Bool bSwitchBackToLoaded
= sal_False
;
1196 // Storing to different format can be done only in running state.
1197 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1199 // TODO/LATER: copying is not legal for documents with relative links.
1200 if ( nTargetStorageFormat
== nOriginalStorageFormat
)
1202 sal_Bool bOptimizationWorks
= sal_False
;
1203 if ( bTryOptimization
)
1207 // try to use optimized copying
1208 uno::Reference
< embed::XOptimizedStorage
> xSource( m_xParentStorage
, uno::UNO_QUERY_THROW
);
1209 uno::Reference
< embed::XOptimizedStorage
> xTarget( xStorage
, uno::UNO_QUERY_THROW
);
1210 xSource
->copyElementDirectlyTo( m_aEntryName
, xTarget
, sEntName
);
1211 bOptimizationWorks
= sal_True
;
1213 catch( const uno::Exception
& )
1218 if ( !bOptimizationWorks
)
1219 m_xParentStorage
->copyElementTo( m_aEntryName
, xStorage
, sEntName
);
1223 changeState( embed::EmbedStates::RUNNING
);
1224 bSwitchBackToLoaded
= sal_True
;
1228 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
1230 uno::Reference
< embed::XStorage
> xSubStorage
=
1231 xStorage
->openStorageElement( sEntName
, embed::ElementModes::READWRITE
);
1233 if ( !xSubStorage
.is() )
1234 throw uno::RuntimeException(); //TODO
1237 // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1238 StoreDocToStorage_Impl( xSubStorage
, nTargetStorageFormat
, GetBaseURLFrom_Impl( lArguments
, lObjArgs
), sEntName
, sal_False
);
1241 if ( bSwitchBackToLoaded
)
1242 changeState( embed::EmbedStates::LOADED
);
1245 // TODO: should the listener notification be done?
1248 //------------------------------------------------------
1249 void SAL_CALL
OCommonEmbeddedObject::storeAsEntry( const uno::Reference
< embed::XStorage
>& xStorage
,
1250 const OUString
& sEntName
,
1251 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1252 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1253 throw ( lang::IllegalArgumentException
,
1254 embed::WrongStateException
,
1257 uno::RuntimeException
)
1259 SAL_INFO( "embeddedobj.common", "embeddedobj (mv76033) OCommonEmbeddedObject::storeAsEntry" );
1261 // TODO: use lObjArgs
1263 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1265 throw lang::DisposedException(); // TODO
1267 if ( m_nObjectState
== -1 )
1269 // the object is still not loaded
1270 throw embed::WrongStateException( OUString( "Can't store object without persistence!\n" ),
1271 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1274 if ( m_bWaitSaveCompleted
)
1275 throw embed::WrongStateException(
1276 OUString( "The object waits for saveCompleted() call!\n" ),
1277 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1279 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1280 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1281 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1284 m_aNewEntryName
= sEntName
;
1288 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStorage
.is(), "The object has no valid persistence!\n" );
1290 sal_Int32 nTargetStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1291 sal_Int32 nOriginalStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1293 nTargetStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( xStorage
);
1295 catch ( const beans::IllegalTypeException
& )
1297 // the container just has an unknown type, use current file format
1299 catch ( const uno::Exception
& )
1301 SAL_WARN( "embeddedobj.common", "Can not retrieve target storage media type!" );
1306 nOriginalStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
1308 catch ( const beans::IllegalTypeException
& )
1310 // the container just has an unknown type, use current file format
1312 catch ( const uno::Exception
& )
1314 SAL_WARN( "embeddedobj.common", "Can not retrieve own storage media type!" );
1317 PostEvent_Impl( OUString( "OnSaveAs" ) );
1319 sal_Bool bTryOptimization
= sal_False
;
1320 for ( sal_Int32 nInd
= 0; nInd
< lObjArgs
.getLength(); nInd
++ )
1322 // StoreVisualReplacement and VisualReplacement args have no sence here
1323 if ( lObjArgs
[nInd
].Name
== "CanTryOptimization" )
1324 lObjArgs
[nInd
].Value
>>= bTryOptimization
;
1327 sal_Bool bSwitchBackToLoaded
= sal_False
;
1329 // Storing to different format can be done only in running state.
1330 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1332 // TODO/LATER: copying is not legal for documents with relative links.
1333 if ( nTargetStorageFormat
== nOriginalStorageFormat
)
1335 sal_Bool bOptimizationWorks
= sal_False
;
1336 if ( bTryOptimization
)
1340 // try to use optimized copying
1341 uno::Reference
< embed::XOptimizedStorage
> xSource( m_xParentStorage
, uno::UNO_QUERY_THROW
);
1342 uno::Reference
< embed::XOptimizedStorage
> xTarget( xStorage
, uno::UNO_QUERY_THROW
);
1343 xSource
->copyElementDirectlyTo( m_aEntryName
, xTarget
, sEntName
);
1344 bOptimizationWorks
= sal_True
;
1346 catch( const uno::Exception
& )
1351 if ( !bOptimizationWorks
)
1352 m_xParentStorage
->copyElementTo( m_aEntryName
, xStorage
, sEntName
);
1356 changeState( embed::EmbedStates::RUNNING
);
1357 bSwitchBackToLoaded
= sal_True
;
1361 uno::Reference
< embed::XStorage
> xSubStorage
=
1362 xStorage
->openStorageElement( sEntName
, embed::ElementModes::READWRITE
);
1364 if ( !xSubStorage
.is() )
1365 throw uno::RuntimeException(); //TODO
1367 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
1370 // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1371 StoreDocToStorage_Impl( xSubStorage
, nTargetStorageFormat
, GetBaseURLFrom_Impl( lArguments
, lObjArgs
), sEntName
, sal_False
);
1374 if ( bSwitchBackToLoaded
)
1375 changeState( embed::EmbedStates::LOADED
);
1378 m_bWaitSaveCompleted
= sal_True
;
1379 m_xNewObjectStorage
= xSubStorage
;
1380 m_xNewParentStorage
= xStorage
;
1381 m_aNewEntryName
= sEntName
;
1382 m_aNewDocMediaDescriptor
= GetValuableArgs_Impl( lArguments
, sal_True
);
1384 // TODO: register listeners for storages above, in case thay are disposed
1385 // an exception will be thrown on saveCompleted( true )
1387 // TODO: should the listener notification be done here or in saveCompleted?
1390 //------------------------------------------------------
1391 void SAL_CALL
OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew
)
1392 throw ( embed::WrongStateException
,
1394 uno::RuntimeException
)
1396 SAL_INFO( "embeddedobj.common", "embeddedobj (mv76033) OCommonEmbeddedObject::saveCompleted" );
1398 ::osl::MutexGuard
aGuard( m_aMutex
);
1400 throw lang::DisposedException(); // TODO
1402 if ( m_nObjectState
== -1 )
1404 // the object is still not loaded
1405 throw embed::WrongStateException( OUString( "Can't store object without persistence!\n" ),
1406 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1409 // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1410 // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1411 // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1415 m_aEntryName
= m_aNewEntryName
;
1416 m_aNewEntryName
= OUString();
1420 // it is allowed to call saveCompleted( false ) for nonstored objects
1421 if ( !m_bWaitSaveCompleted
&& !bUseNew
)
1424 SAL_WARN_IF( !m_bWaitSaveCompleted
, "embeddedobj.common", "Unexpected saveCompleted() call!" );
1425 if ( !m_bWaitSaveCompleted
)
1426 throw io::IOException(); // TODO: illegal call
1428 OSL_ENSURE( m_xNewObjectStorage
.is() && m_xNewParentStorage
.is() , "Internal object information is broken!\n" );
1429 if ( !m_xNewObjectStorage
.is() || !m_xNewParentStorage
.is() )
1430 throw uno::RuntimeException(); // TODO: broken internal information
1434 SwitchOwnPersistence( m_xNewParentStorage
, m_xNewObjectStorage
, m_aNewEntryName
);
1435 m_aDocMediaDescriptor
= m_aNewDocMediaDescriptor
;
1437 uno::Reference
< util::XModifiable
> xModif( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
1439 xModif
->setModified( sal_False
);
1441 PostEvent_Impl( OUString( "OnSaveAsDone" ));
1446 uno::Reference
< lang::XComponent
> xComponent( m_xNewObjectStorage
, uno::UNO_QUERY
);
1447 SAL_WARN_IF( !xComponent
.is(), "embeddedobj.common", "Wrong storage implementation!" );
1448 if ( xComponent
.is() )
1449 xComponent
->dispose();
1451 catch ( const uno::Exception
& )
1456 m_xNewObjectStorage
= uno::Reference
< embed::XStorage
>();
1457 m_xNewParentStorage
= uno::Reference
< embed::XStorage
>();
1458 m_aNewEntryName
= OUString();
1459 m_aNewDocMediaDescriptor
.realloc( 0 );
1460 m_bWaitSaveCompleted
= sal_False
;
1464 // TODO: notify listeners
1466 if ( m_nUpdateMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
)
1468 // TODO: update visual representation
1473 //------------------------------------------------------
1474 sal_Bool SAL_CALL
OCommonEmbeddedObject::hasEntry()
1475 throw ( embed::WrongStateException
,
1476 uno::RuntimeException
)
1478 ::osl::MutexGuard
aGuard( m_aMutex
);
1480 throw lang::DisposedException(); // TODO
1482 if ( m_bWaitSaveCompleted
)
1483 throw embed::WrongStateException(
1484 OUString( "The object waits for saveCompleted() call!\n" ),
1485 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1487 if ( m_xObjectStorage
.is() )
1493 //------------------------------------------------------
1494 OUString SAL_CALL
OCommonEmbeddedObject::getEntryName()
1495 throw ( embed::WrongStateException
,
1496 uno::RuntimeException
)
1498 ::osl::MutexGuard
aGuard( m_aMutex
);
1500 throw lang::DisposedException(); // TODO
1502 if ( m_nObjectState
== -1 )
1504 // the object is still not loaded
1505 throw embed::WrongStateException( OUString( "The object persistence is not initialized!\n" ),
1506 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1509 if ( m_bWaitSaveCompleted
)
1510 throw embed::WrongStateException(
1511 OUString( "The object waits for saveCompleted() call!\n" ),
1512 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1514 return m_aEntryName
;
1517 //------------------------------------------------------
1518 void SAL_CALL
OCommonEmbeddedObject::storeOwn()
1519 throw ( embed::WrongStateException
,
1522 uno::RuntimeException
)
1524 SAL_INFO( "embeddedobj.common", "embeddedobj (mv76033) OCommonEmbeddedObject::storeOwn" );
1526 // during switching from Activated to Running and from Running to Loaded states the object will
1527 // ask container to store the object, the container has to make decision
1530 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1532 throw lang::DisposedException(); // TODO
1534 if ( m_nObjectState
== -1 )
1536 // the object is still not loaded
1537 throw embed::WrongStateException( OUString( "Can't store object without persistence!\n" ),
1538 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1541 if ( m_bWaitSaveCompleted
)
1542 throw embed::WrongStateException(
1543 OUString( "The object waits for saveCompleted() call!\n" ),
1544 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1547 throw io::IOException(); // TODO: access denied
1549 // nothing to do, if the object is in loaded state
1550 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1553 PostEvent_Impl( OUString( "OnSave" ) );
1555 SAL_WARN_IF( !m_pDocHolder
->GetComponent().is(), "embeddedobj.common", "If an object is activated or in running state it must have a document!" );
1556 if ( !m_pDocHolder
->GetComponent().is() )
1557 throw uno::RuntimeException();
1561 // TODO: just store the document to it's location
1562 uno::Reference
< frame::XStorable
> xStorable( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
1563 if ( !xStorable
.is() )
1564 throw uno::RuntimeException(); // TODO
1566 // free the main mutex for the storing time
1575 OSL_ENSURE( m_xParentStorage
.is() && m_xObjectStorage
.is(), "The object has no valid persistence!\n" );
1577 if ( !m_xObjectStorage
.is() )
1578 throw io::IOException(); //TODO: access denied
1580 sal_Int32 nStorageFormat
= SOFFICE_FILEFORMAT_CURRENT
;
1582 nStorageFormat
= ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage
);
1584 catch ( const beans::IllegalTypeException
& )
1586 // the container just has an unknown type, use current file format
1588 catch ( const uno::Exception
& )
1590 SAL_WARN( "embeddedobj.common", "Can not retrieve storage media type!" );
1594 StoreDocToStorage_Impl( m_xObjectStorage
, nStorageFormat
, GetBaseURL_Impl(), m_aEntryName
, sal_True
);
1598 uno::Reference
< util::XModifiable
> xModif( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
1600 xModif
->setModified( sal_False
);
1602 PostEvent_Impl( OUString( "OnSaveDone" ) );
1605 //------------------------------------------------------
1606 sal_Bool SAL_CALL
OCommonEmbeddedObject::isReadonly()
1607 throw ( embed::WrongStateException
,
1608 uno::RuntimeException
)
1610 ::osl::MutexGuard
aGuard( m_aMutex
);
1612 throw lang::DisposedException(); // TODO
1614 if ( m_nObjectState
== -1 )
1616 // the object is still not loaded
1617 throw embed::WrongStateException( OUString( "The object persistence is not initialized!\n" ),
1618 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1621 if ( m_bWaitSaveCompleted
)
1622 throw embed::WrongStateException(
1623 OUString( "The object waits for saveCompleted() call!\n" ),
1624 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1629 //------------------------------------------------------
1630 void SAL_CALL
OCommonEmbeddedObject::reload(
1631 const uno::Sequence
< beans::PropertyValue
>& lArguments
,
1632 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
1633 throw ( lang::IllegalArgumentException
,
1634 embed::WrongStateException
,
1637 uno::RuntimeException
)
1639 // TODO: use lObjArgs
1640 // for now this method is used only to switch readonly state
1642 ::osl::MutexGuard
aGuard( m_aMutex
);
1644 throw lang::DisposedException(); // TODO
1646 if ( m_nObjectState
== -1 )
1648 // the object is still not loaded
1649 throw embed::WrongStateException( OUString( "The object persistence is not initialized!\n" ),
1650 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1653 if ( m_nObjectState
!= embed::EmbedStates::LOADED
)
1655 // the object is still not loaded
1656 throw embed::WrongStateException(
1657 OUString( "The object must be in loaded state to be reloaded!\n" ),
1658 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1661 if ( m_bWaitSaveCompleted
)
1662 throw embed::WrongStateException(
1663 OUString( "The object waits for saveCompleted() call!\n" ),
1664 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1668 // reload of the link
1669 OUString aOldLinkFilter
= m_aLinkFilterName
;
1671 OUString aNewLinkFilter
;
1672 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
1674 if ( lArguments
[nInd
].Name
== "URL" )
1677 lArguments
[nInd
].Value
>>= m_aLinkURL
;
1678 m_aLinkFilterName
= OUString();
1680 else if ( lArguments
[nInd
].Name
== "FilterName" )
1682 lArguments
[nInd
].Value
>>= aNewLinkFilter
;
1683 m_aLinkFilterName
= OUString();
1687 ::comphelper::MimeConfigurationHelper
aHelper( m_xContext
);
1688 if ( m_aLinkFilterName
.isEmpty() )
1690 if ( !aNewLinkFilter
.isEmpty() )
1691 m_aLinkFilterName
= aNewLinkFilter
;
1694 uno::Sequence
< beans::PropertyValue
> aArgs( 1 );
1695 aArgs
[0].Name
= "URL";
1696 aArgs
[0].Value
<<= m_aLinkURL
;
1697 m_aLinkFilterName
= aHelper
.UpdateMediaDescriptorWithFilterName( aArgs
, sal_False
);
1701 if ( !aOldLinkFilter
.equals( m_aLinkFilterName
) )
1703 uno::Sequence
< beans::NamedValue
> aObject
= aHelper
.GetObjectPropsByFilter( m_aLinkFilterName
);
1705 // TODO/LATER: probably the document holder could be cleaned explicitly as in the destructor
1706 m_pDocHolder
->release();
1707 m_pDocHolder
= NULL
;
1709 LinkInit_Impl( aObject
, lArguments
, lObjArgs
);
1713 m_aDocMediaDescriptor
= GetValuableArgs_Impl( lArguments
, sal_True
);
1715 // TODO: use lObjArgs for StoreVisualReplacement
1716 for ( sal_Int32 nObjInd
= 0; nObjInd
< lObjArgs
.getLength(); nObjInd
++ )
1717 if ( lObjArgs
[nObjInd
].Name
== "OutplaceDispatchInterceptor" )
1719 uno::Reference
< frame::XDispatchProviderInterceptor
> xDispatchInterceptor
;
1720 if ( lObjArgs
[nObjInd
].Value
>>= xDispatchInterceptor
)
1721 m_pDocHolder
->SetOutplaceDispatchInterceptor( xDispatchInterceptor
);
1727 // when document allows reloading through API the object can be reloaded not only in loaded state
1729 sal_Bool bOldReadOnlyValue
= m_bReadOnly
;
1731 m_bReadOnly
= sal_False
;
1732 for ( sal_Int32 nInd
= 0; nInd
< lArguments
.getLength(); nInd
++ )
1733 if ( lArguments
[nInd
].Name
== "ReadOnly" )
1734 lArguments
[nInd
].Value
>>= m_bReadOnly
;
1736 if ( bOldReadOnlyValue
!= m_bReadOnly
&& !m_bIsLink
)
1738 // close own storage
1740 uno::Reference
< lang::XComponent
> xComponent( m_xObjectStorage
, uno::UNO_QUERY
);
1741 OSL_ENSURE( !m_xObjectStorage
.is() || xComponent
.is(), "Wrong storage implementation!" );
1742 if ( xComponent
.is() )
1743 xComponent
->dispose();
1745 catch ( const uno::Exception
& )
1749 sal_Int32 nStorageMode
= m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
;
1750 m_xObjectStorage
= m_xParentStorage
->openStorageElement( m_aEntryName
, nStorageMode
);
1754 //------------------------------------------------------
1755 void SAL_CALL
OCommonEmbeddedObject::breakLink( const uno::Reference
< embed::XStorage
>& xStorage
,
1756 const OUString
& sEntName
)
1757 throw ( lang::IllegalArgumentException
,
1758 embed::WrongStateException
,
1761 uno::RuntimeException
)
1763 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
1765 throw lang::DisposedException(); // TODO
1769 // it must be a linked initialized object
1770 throw embed::WrongStateException(
1771 OUString( "The object is not a valid linked object!\n" ),
1772 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1776 // the current implementation of OOo links does not implement this method since it does not implement
1777 // all the set of interfaces required for OOo embedded object ( XEmbedPersist is not supported ).
1780 if ( !xStorage
.is() )
1781 throw lang::IllegalArgumentException( OUString( "No parent storage is provided!\n" ),
1782 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ),
1785 if ( sEntName
.isEmpty() )
1786 throw lang::IllegalArgumentException( OUString( "Empty element name is provided!\n" ),
1787 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ),
1790 if ( !m_bIsLink
|| m_nObjectState
== -1 )
1792 // it must be a linked initialized object
1793 throw embed::WrongStateException(
1794 OUString( "The object is not a valid linked object!\n" ),
1795 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1798 if ( m_bWaitSaveCompleted
)
1799 throw embed::WrongStateException(
1800 OUString( "The object waits for saveCompleted() call!\n" ),
1801 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1803 uno::Reference
< container::XNameAccess
> xNameAccess( xStorage
, uno::UNO_QUERY
);
1804 if ( !xNameAccess
.is() )
1805 throw uno::RuntimeException(); //TODO
1807 // detect entry existence
1808 /*sal_Bool bElExists =*/ xNameAccess
->hasByName( sEntName
);
1810 m_bReadOnly
= sal_False
;
1812 if ( m_xParentStorage
!= xStorage
|| !m_aEntryName
.equals( sEntName
) )
1813 SwitchOwnPersistence( xStorage
, sEntName
);
1815 // for linked object it means that it becomes embedded object
1816 // the document must switch it's persistence also
1818 // TODO/LATER: handle the case when temp doc can not be created
1819 // the document is a new embedded object so it must be marked as modified
1820 uno::Reference
< util::XCloseable
> xDocument
= CreateTempDocFromLink_Impl();
1821 uno::Reference
< util::XModifiable
> xModif( m_pDocHolder
->GetComponent(), uno::UNO_QUERY
);
1823 throw uno::RuntimeException();
1826 xModif
->setModified( sal_True
);
1828 catch( const uno::Exception
& )
1831 m_pDocHolder
->SetComponent( xDocument
, m_bReadOnly
);
1832 SAL_WARN_IF( !m_pDocHolder
->GetComponent().is(), "embeddedobj.common", "If document cant be created, an exception must be thrown!" );
1834 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
1836 // the state is changed and can not be switched to loaded state back without saving
1837 m_nObjectState
= embed::EmbedStates::RUNNING
;
1838 StateChangeNotification_Impl( sal_False
, embed::EmbedStates::LOADED
, m_nObjectState
, aGuard
);
1840 else if ( m_nObjectState
== embed::EmbedStates::ACTIVE
)
1841 m_pDocHolder
->Show();
1843 m_bIsLink
= sal_False
;
1844 m_aLinkFilterName
= OUString();
1845 m_aLinkURL
= OUString();
1848 //------------------------------------------------------
1849 sal_Bool SAL_CALL
OCommonEmbeddedObject::isLink()
1850 throw ( embed::WrongStateException
,
1851 uno::RuntimeException
)
1853 ::osl::MutexGuard
aGuard( m_aMutex
);
1855 throw lang::DisposedException(); // TODO
1860 //------------------------------------------------------
1861 OUString SAL_CALL
OCommonEmbeddedObject::getLinkURL()
1862 throw ( embed::WrongStateException
,
1864 uno::RuntimeException
)
1866 ::osl::MutexGuard
aGuard( m_aMutex
);
1868 throw lang::DisposedException(); // TODO
1871 throw embed::WrongStateException(
1872 OUString( "The object is not a link object!\n" ),
1873 uno::Reference
< uno::XInterface
>( static_cast< ::cppu::OWeakObject
* >(this) ) );
1878 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */