xref: /trunk/main/embeddedobj/source/commonembedding/persistence.cxx (revision d666495c4f609ab94ddded8b0141831070b22d11)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_embeddedobj.hxx"
26 
27 #include <commonembobj.hxx>
28 #include <com/sun/star/embed/Aspects.hpp>
29 #include <com/sun/star/document/XStorageBasedDocument.hpp>
30 #include <com/sun/star/embed/EmbedStates.hpp>
31 #include <com/sun/star/embed/EmbedVerbs.hpp>
32 #include <com/sun/star/embed/EntryInitModes.hpp>
33 #include <com/sun/star/embed/XStorage.hpp>
34 #include <com/sun/star/embed/XOptimizedStorage.hpp>
35 #include <com/sun/star/embed/ElementModes.hpp>
36 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/frame/XStorable.hpp>
39 #include <com/sun/star/frame/XLoadable.hpp>
40 #include <com/sun/star/frame/XComponentLoader.hpp>
41 #include <com/sun/star/frame/XModule.hpp>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
44 #include <com/sun/star/lang/DisposedException.hpp>
45 #include <com/sun/star/util/XModifiable.hpp>
46 
47 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCEESS_HPP_
48 #include <com/sun/star/container/XNameAccess.hpp>
49 #endif
50 #include <com/sun/star/container/XChild.hpp>
51 #include <com/sun/star/util/XCloseable.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/beans/IllegalTypeException.hpp>
54 #include <com/sun/star/chart2/XChartDocument.hpp>
55 
56 #include <comphelper/configurationhelper.hxx>
57 #include <comphelper/fileformat.h>
58 #include <comphelper/storagehelper.hxx>
59 #include <comphelper/mimeconfighelper.hxx>
60 #include <comphelper/namedvaluecollection.hxx>
61 
62 #include <rtl/logfile.hxx>
63 
64 #include <tools/diagnose_ex.h>
65 
66 #define USE_STORAGEBASED_DOCUMENT
67 
68 using namespace ::com::sun::star;
69 
70 
71 //------------------------------------------------------
72 // the values of Save/ODF/DefaultVersion that select strict ODF 1.2 and 1.3 (SvtSaveOptions::ODFVER_012, ODFVER_013)
IsStrictODF12_Impl(const uno::Reference<lang::XMultiServiceFactory> & xFactory)73 static sal_Bool IsStrictODF12_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
74 {
75     try
76     {
77         sal_Int16 nVersion = 0;
78         ::comphelper::ConfigurationHelper::readDirectKey(
79                 xFactory,
80                 ::rtl::OUString::createFromAscii( "org.openoffice.Office.Common/" ),
81                 ::rtl::OUString::createFromAscii( "Save/ODF" ),
82                 ::rtl::OUString::createFromAscii( "DefaultVersion" ),
83                 ::comphelper::ConfigurationHelper::E_READONLY ) >>= nVersion;
84         return nVersion == 4 || nVersion == 5;
85     }
86     catch ( uno::Exception& )
87     {
88     }
89 
90     return sal_False;
91 }
92 
93 //------------------------------------------------------
GetValuableArgs_Impl(const uno::Sequence<beans::PropertyValue> & aMedDescr,sal_Bool bCanUseDocumentBaseURL)94 uno::Sequence< beans::PropertyValue > GetValuableArgs_Impl( const uno::Sequence< beans::PropertyValue >& aMedDescr,
95                                                             sal_Bool bCanUseDocumentBaseURL )
96 {
97     uno::Sequence< beans::PropertyValue > aResult;
98     sal_Int32 nResLen = 0;
99 
100     for ( sal_Int32 nInd = 0; nInd < aMedDescr.getLength(); nInd++ )
101     {
102         if ( aMedDescr[nInd].Name.equalsAscii( "ComponentData" )
103           || aMedDescr[nInd].Name.equalsAscii( "DocumentTitle" )
104           || aMedDescr[nInd].Name.equalsAscii( "InteractionHandler" )
105           || aMedDescr[nInd].Name.equalsAscii( "JumpMark" )
106           // || aMedDescr[nInd].Name.equalsAscii( "Password" ) makes no sense for embedded objects
107           || aMedDescr[nInd].Name.equalsAscii( "Preview" )
108           || aMedDescr[nInd].Name.equalsAscii( "ReadOnly" )
109           || aMedDescr[nInd].Name.equalsAscii( "StartPresentation" )
110           || aMedDescr[nInd].Name.equalsAscii( "RepairPackage" )
111           || aMedDescr[nInd].Name.equalsAscii( "StatusIndicator" )
112           || aMedDescr[nInd].Name.equalsAscii( "ViewData" )
113           || aMedDescr[nInd].Name.equalsAscii( "ViewId" )
114           || aMedDescr[nInd].Name.equalsAscii( "MacroExecutionMode" )
115           || aMedDescr[nInd].Name.equalsAscii( "UpdateDocMode" )
116           || (aMedDescr[nInd].Name.equalsAscii( "DocumentBaseURL" ) && bCanUseDocumentBaseURL) )
117         {
118             aResult.realloc( ++nResLen );
119             aResult[nResLen-1] = aMedDescr[nInd];
120         }
121     }
122 
123     return aResult;
124 }
125 
126 //------------------------------------------------------
addAsTemplate(const uno::Sequence<beans::PropertyValue> & aOrig)127 uno::Sequence< beans::PropertyValue > addAsTemplate( const uno::Sequence< beans::PropertyValue >& aOrig )
128 {
129     sal_Bool bAsTemplateSet = sal_False;
130     sal_Int32 nLength = aOrig.getLength();
131     uno::Sequence< beans::PropertyValue > aResult( nLength );
132 
133     for ( sal_Int32 nInd = 0; nInd < nLength; nInd++ )
134     {
135         aResult[nInd].Name = aOrig[nInd].Name;
136         if ( aResult[nInd].Name.equalsAscii( "AsTemplate" ) )
137         {
138             aResult[nInd].Value <<= sal_True;
139             bAsTemplateSet = sal_True;
140         }
141         else
142             aResult[nInd].Value = aOrig[nInd].Value;
143     }
144 
145     if ( !bAsTemplateSet )
146     {
147         aResult.realloc( nLength + 1 );
148         aResult[nLength].Name = ::rtl::OUString::createFromAscii( "AsTemplate" );
149         aResult[nLength].Value <<= sal_True;
150     }
151 
152     return aResult;
153 }
154 
155 //------------------------------------------------------
createTempInpStreamFromStor(const uno::Reference<embed::XStorage> & xStorage,const uno::Reference<lang::XMultiServiceFactory> & xFactory)156 uno::Reference< io::XInputStream > createTempInpStreamFromStor(
157                                                             const uno::Reference< embed::XStorage >& xStorage,
158                                                             const uno::Reference< lang::XMultiServiceFactory >& xFactory )
159 {
160     OSL_ENSURE( xStorage.is(), "The storage can not be empty!" );
161 
162     uno::Reference< io::XInputStream > xResult;
163 
164     const ::rtl::OUString aServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
165     uno::Reference < io::XStream > xTempStream = uno::Reference < io::XStream > (
166                                                             xFactory->createInstance ( aServiceName ),
167                                                             uno::UNO_QUERY );
168     if ( xTempStream.is() )
169     {
170         uno::Reference < lang::XSingleServiceFactory > xStorageFactory(
171                     xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.embed.StorageFactory" ) ),
172                     uno::UNO_QUERY );
173 
174         uno::Sequence< uno::Any > aArgs( 2 );
175         aArgs[0] <<= xTempStream;
176         aArgs[1] <<= embed::ElementModes::READWRITE;
177         uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArgs ),
178                                                         uno::UNO_QUERY );
179         if ( !xTempStorage.is() )
180             throw uno::RuntimeException(); // TODO:
181 
182         try
183         {
184             xStorage->copyToStorage( xTempStorage );
185         } catch( uno::Exception& e )
186         {
187             throw embed::StorageWrappedTargetException(
188                         ::rtl::OUString::createFromAscii( "Can't copy storage!" ),
189                         uno::Reference< uno::XInterface >(),
190                         uno::makeAny( e ) );
191         }
192 
193         try {
194             uno::Reference< lang::XComponent > xComponent( xTempStorage, uno::UNO_QUERY );
195             OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" );
196             if ( xComponent.is() )
197                 xComponent->dispose();
198         }
199         catch ( uno::Exception& )
200         {
201         }
202 
203         try {
204             uno::Reference< io::XOutputStream > xTempOut = xTempStream->getOutputStream();
205             if ( xTempOut.is() )
206                 xTempOut->closeOutput();
207         }
208         catch ( uno::Exception& )
209         {
210         }
211 
212         xResult = xTempStream->getInputStream();
213     }
214 
215     return xResult;
216 
217 }
218 
219 //------------------------------------------------------
TransferMediaType(const uno::Reference<embed::XStorage> & i_rSource,const uno::Reference<embed::XStorage> & i_rTarget)220 static void TransferMediaType( const uno::Reference< embed::XStorage >& i_rSource, const uno::Reference< embed::XStorage >& i_rTarget )
221 {
222     try
223     {
224         const uno::Reference< beans::XPropertySet > xSourceProps( i_rSource, uno::UNO_QUERY_THROW );
225         const uno::Reference< beans::XPropertySet > xTargetProps( i_rTarget, uno::UNO_QUERY_THROW );
226         const ::rtl::OUString sMediaTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
227         xTargetProps->setPropertyValue( sMediaTypePropName, xSourceProps->getPropertyValue( sMediaTypePropName ) );
228     }
229     catch( const uno::Exception& )
230     {
231         DBG_UNHANDLED_EXCEPTION();
232     }
233 }
234 
235 //------------------------------------------------------
CreateDocument(const uno::Reference<lang::XMultiServiceFactory> & _rxFactory,const::rtl::OUString & _rDocumentServiceName,bool _bEmbeddedScriptSupport,const bool i_bDocumentRecoverySupport)236 static uno::Reference< util::XCloseable > CreateDocument( const uno::Reference< lang::XMultiServiceFactory >& _rxFactory,
237     const ::rtl::OUString& _rDocumentServiceName, bool _bEmbeddedScriptSupport, const bool i_bDocumentRecoverySupport )
238 {
239     ::comphelper::NamedValueCollection aArguments;
240     aArguments.put( "EmbeddedObject", (sal_Bool)sal_True );
241     aArguments.put( "EmbeddedScriptSupport", (sal_Bool)_bEmbeddedScriptSupport );
242     aArguments.put( "DocumentRecoverySupport", (sal_Bool)i_bDocumentRecoverySupport );
243 
244     uno::Reference< uno::XInterface > xDocument;
245     try
246     {
247         xDocument = _rxFactory->createInstanceWithArguments( _rDocumentServiceName, aArguments.getWrappedPropertyValues() );
248     }
249     catch( const uno::Exception& )
250     {
251         // if an embedded object implementation does not support XInitialization,
252         // the default factory from cppuhelper will throw an
253         // IllegalArgumentException when we try to create the instance with arguments.
254         // Okay, so we fall back to creating the instance without any arguments.
255         OSL_ASSERT("Consider implementing interface XInitialization to avoid duplicate construction");
256         xDocument = _rxFactory->createInstance( _rDocumentServiceName );
257     }
258 
259     return uno::Reference< util::XCloseable >( xDocument, uno::UNO_QUERY );
260 }
261 
262 //------------------------------------------------------
SetDocToEmbedded(const uno::Reference<frame::XModel> xDocument,const::rtl::OUString & aModuleName)263 static void SetDocToEmbedded( const uno::Reference< frame::XModel > xDocument, const ::rtl::OUString& aModuleName )
264 {
265     if ( xDocument.is() )
266     {
267         uno::Sequence< beans::PropertyValue > aSeq( 1 );
268         aSeq[0].Name = ::rtl::OUString::createFromAscii( "SetEmbedded" );
269         aSeq[0].Value <<= sal_True;
270         xDocument->attachResource( ::rtl::OUString(), aSeq );
271 
272         if ( aModuleName.getLength() )
273         {
274             try
275             {
276                 uno::Reference< frame::XModule > xModule( xDocument, uno::UNO_QUERY_THROW );
277                 xModule->setIdentifier( aModuleName );
278             }
279             catch( uno::Exception& )
280             {}
281         }
282     }
283 }
284 
285 //------------------------------------------------------
SwitchOwnPersistence(const uno::Reference<embed::XStorage> & xNewParentStorage,const uno::Reference<embed::XStorage> & xNewObjectStorage,const::rtl::OUString & aNewName)286 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
287                                                   const uno::Reference< embed::XStorage >& xNewObjectStorage,
288                                                   const ::rtl::OUString& aNewName )
289 {
290     if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
291     {
292         OSL_ENSURE( xNewObjectStorage == m_xObjectStorage, "The storage must be the same!\n" );
293         return;
294     }
295 
296     uno::Reference< lang::XComponent > xComponent( m_xObjectStorage, uno::UNO_QUERY );
297     OSL_ENSURE( !m_xObjectStorage.is() || xComponent.is(), "Wrong storage implementation!" );
298 
299     m_xObjectStorage = xNewObjectStorage;
300     m_xParentStorage = xNewParentStorage;
301     m_aEntryName = aNewName;
302 
303 #ifdef USE_STORAGEBASED_DOCUMENT
304     // the linked document should not be switched
305     if ( !m_bIsLink )
306     {
307         uno::Reference< document::XStorageBasedDocument > xDoc( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
308         if ( xDoc.is() )
309             SwitchDocToStorage_Impl( xDoc, m_xObjectStorage );
310     }
311 #endif
312 
313     try {
314         if ( xComponent.is() )
315             xComponent->dispose();
316     }
317     catch ( uno::Exception& )
318     {
319     }
320 }
321 
322 //------------------------------------------------------
SwitchOwnPersistence(const uno::Reference<embed::XStorage> & xNewParentStorage,const::rtl::OUString & aNewName)323 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
324                                                   const ::rtl::OUString& aNewName )
325 {
326     if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
327         return;
328 
329     sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
330 
331     uno::Reference< embed::XStorage > xNewOwnStorage = xNewParentStorage->openStorageElement( aNewName, nStorageMode );
332     OSL_ENSURE( xNewOwnStorage.is(), "The method can not return empty reference!" );
333 
334     SwitchOwnPersistence( xNewParentStorage, xNewOwnStorage, aNewName );
335 }
336 
337 //------------------------------------------------------
EmbedAndReparentDoc_Impl(const uno::Reference<util::XCloseable> & i_rxDocument) const338 void OCommonEmbeddedObject::EmbedAndReparentDoc_Impl( const uno::Reference< util::XCloseable >& i_rxDocument ) const
339 {
340     SetDocToEmbedded( uno::Reference< frame::XModel >( i_rxDocument, uno::UNO_QUERY ), m_aModuleName );
341 
342     try
343     {
344         uno::Reference < container::XChild > xChild( i_rxDocument, uno::UNO_QUERY );
345         if ( xChild.is() )
346             xChild->setParent( m_xParent );
347     }
348     catch( const lang::NoSupportException & )
349     {
350         OSL_ENSURE( false, "OCommonEmbeddedObject::EmbedAndReparentDoc: cannot set parent at document!" );
351     }
352 }
353 
354 //------------------------------------------------------
InitNewDocument_Impl()355 uno::Reference< util::XCloseable > OCommonEmbeddedObject::InitNewDocument_Impl()
356 {
357     uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(),
358                                                 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
359 
360     uno::Reference< frame::XModel > xModel( xDocument, uno::UNO_QUERY );
361     uno::Reference< frame::XLoadable > xLoadable( xModel, uno::UNO_QUERY );
362     if ( !xLoadable.is() )
363         throw uno::RuntimeException();
364 
365     try
366     {
367         // set the document mode to embedded as the first action on document!!!
368         EmbedAndReparentDoc_Impl( xDocument );
369 
370         // if we have a storage to recover the document from, do not use initNew, but instead load from that storage
371         bool bInitNew = true;
372         if ( m_xRecoveryStorage.is() )
373         {
374             uno::Reference< document::XStorageBasedDocument > xDoc( xLoadable, uno::UNO_QUERY );
375             OSL_ENSURE( xDoc.is(), "OCommonEmbeddedObject::InitNewDocument_Impl: cannot recover from a storage when the document is not storage based!" );
376             if ( xDoc.is() )
377             {
378                 ::comphelper::NamedValueCollection aLoadArgs;
379                 FillDefaultLoadArgs_Impl( m_xRecoveryStorage, aLoadArgs );
380 
381                 xDoc->loadFromStorage( m_xRecoveryStorage, aLoadArgs.getPropertyValues() );
382                 SwitchDocToStorage_Impl( xDoc, m_xObjectStorage );
383                 bInitNew = false;
384             }
385         }
386 
387         if ( bInitNew )
388         {
389             // init document as a new
390             xLoadable->initNew();
391         }
392         xModel->attachResource( xModel->getURL(), m_aDocMediaDescriptor );
393     }
394     catch( uno::Exception& )
395     {
396         uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
397         if ( xCloseable.is() )
398         {
399             try
400             {
401                 xCloseable->close( sal_True );
402             }
403             catch( uno::Exception& )
404             {
405             }
406         }
407 
408         throw; // TODO
409     }
410 
411     return xDocument;
412 }
413 
414 //------------------------------------------------------
LoadLink_Impl()415 uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl()
416 {
417     uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(),
418                                                 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
419 
420     uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY );
421     if ( !xLoadable.is() )
422         throw uno::RuntimeException();
423 
424     sal_Int32 nLen = 2;
425     uno::Sequence< beans::PropertyValue > aArgs( nLen );
426     aArgs[0].Name = ::rtl::OUString::createFromAscii( "URL" );
427     aArgs[0].Value <<= m_aLinkURL;
428     aArgs[1].Name = ::rtl::OUString::createFromAscii( "FilterName" );
429     aArgs[1].Value <<= m_aLinkFilterName;
430     if ( m_bLinkHasPassword )
431     {
432         aArgs.realloc( ++nLen );
433         aArgs[nLen-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Password" ) );
434         aArgs[nLen-1].Value <<= m_aLinkPassword;
435     }
436 
437     aArgs.realloc( m_aDocMediaDescriptor.getLength() + nLen );
438     for ( sal_Int32 nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ )
439     {
440         aArgs[nInd+nLen].Name = m_aDocMediaDescriptor[nInd].Name;
441         aArgs[nInd+nLen].Value = m_aDocMediaDescriptor[nInd].Value;
442     }
443 
444     try
445     {
446         // the document is not really an embedded one, it is a link
447         EmbedAndReparentDoc_Impl( xDocument );
448 
449         // load the document
450         xLoadable->load( aArgs );
451 
452         if ( !m_bLinkHasPassword )
453         {
454             // check if there is a password to cache
455             uno::Reference< frame::XModel > xModel( xLoadable, uno::UNO_QUERY_THROW );
456             uno::Sequence< beans::PropertyValue > aProps = xModel->getArgs();
457             for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ )
458                 if ( aProps[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Password" ) ) )
459                   && ( aProps[nInd].Value >>= m_aLinkPassword ) )
460                 {
461                     m_bLinkHasPassword = sal_True;
462                     break;
463                 }
464         }
465     }
466     catch( uno::Exception& )
467     {
468         uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
469         if ( xCloseable.is() )
470         {
471             try
472             {
473                 xCloseable->close( sal_True );
474             }
475             catch( uno::Exception& )
476             {
477             }
478         }
479 
480         throw; // TODO
481     }
482 
483     return xDocument;
484 
485 }
486 
487 //------------------------------------------------------
GetFilterName(sal_Int32 nVersion) const488 ::rtl::OUString OCommonEmbeddedObject::GetFilterName( sal_Int32 nVersion ) const
489 {
490     ::rtl::OUString aFilterName = GetPresetFilterName();
491     if ( !aFilterName.getLength() )
492     {
493         try {
494             ::comphelper::MimeConfigurationHelper aHelper( m_xFactory );
495             aFilterName = aHelper.GetDefaultFilterFromServiceName( GetDocumentServiceName(), nVersion );
496         } catch( uno::Exception& )
497         {}
498     }
499 
500     return aFilterName;
501 }
502 
503 //------------------------------------------------------
FillDefaultLoadArgs_Impl(const uno::Reference<embed::XStorage> & i_rxStorage,::comphelper::NamedValueCollection & o_rLoadArgs) const504 void OCommonEmbeddedObject::FillDefaultLoadArgs_Impl( const uno::Reference< embed::XStorage >& i_rxStorage,
505         ::comphelper::NamedValueCollection& o_rLoadArgs ) const
506 {
507     o_rLoadArgs.put( "DocumentBaseURL", GetBaseURL_Impl() );
508     o_rLoadArgs.put( "HierarchicalDocumentName", m_aEntryName );
509     o_rLoadArgs.put( "ReadOnly", m_bReadOnly );
510 
511     ::rtl::OUString aFilterName = GetFilterName( ::comphelper::OStorageHelper::GetXStorageFormat( i_rxStorage ) );
512     OSL_ENSURE( aFilterName.getLength(), "OCommonEmbeddedObject::FillDefaultLoadArgs_Impl: Wrong document service name!" );
513     if ( !aFilterName.getLength() )
514         throw io::IOException();    // TODO: error message/code
515 
516     o_rLoadArgs.put( "FilterName", aFilterName );
517 }
518 
519 //------------------------------------------------------
LoadDocumentFromStorage_Impl()520 uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadDocumentFromStorage_Impl()
521 {
522     ENSURE_OR_THROW( m_xObjectStorage.is(), "no object storage" );
523 
524     const uno::Reference< embed::XStorage > xSourceStorage( m_xRecoveryStorage.is() ? m_xRecoveryStorage : m_xObjectStorage );
525 
526     uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(),
527                                                 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
528 
529     //#i103460# ODF: take the size given from the parent frame as default
530     uno::Reference< chart2::XChartDocument > xChart( xDocument, uno::UNO_QUERY );
531     if( xChart.is() )
532     {
533         uno::Reference< embed::XVisualObject > xChartVisualObject( xChart, uno::UNO_QUERY );
534         if( xChartVisualObject.is() )
535             xChartVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, m_aDefaultSizeForChart_In_100TH_MM );
536     }
537 
538     uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY );
539     uno::Reference< document::XStorageBasedDocument > xDoc
540 #ifdef USE_STORAGEBASED_DOCUMENT
541             ( xDocument, uno::UNO_QUERY )
542 #endif
543             ;
544     if ( !xDoc.is() && !xLoadable.is() ) ///BUG: This should be || instead of && ?
545         throw uno::RuntimeException();
546 
547     ::comphelper::NamedValueCollection aLoadArgs;
548     FillDefaultLoadArgs_Impl( xSourceStorage, aLoadArgs );
549 
550     uno::Reference< io::XInputStream > xTempInpStream;
551     if ( !xDoc.is() )
552     {
553         xTempInpStream = createTempInpStreamFromStor( xSourceStorage, m_xFactory );
554         if ( !xTempInpStream.is() )
555             throw uno::RuntimeException();
556 
557         ::rtl::OUString aTempFileURL;
558         try
559         {
560             // no need to let the file stay after the stream is removed since the embedded document
561             // can not be stored directly
562             uno::Reference< beans::XPropertySet > xTempStreamProps( xTempInpStream, uno::UNO_QUERY_THROW );
563             xTempStreamProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ) >>= aTempFileURL;
564         }
565         catch( uno::Exception& )
566         {
567         }
568 
569         OSL_ENSURE( aTempFileURL.getLength(), "Couldn't retrieve temporary file URL!\n" );
570 
571         aLoadArgs.put( "URL", aTempFileURL );
572         aLoadArgs.put( "InputStream", xTempInpStream );
573     }
574 
575     // aLoadArgs.put( "AsTemplate", sal_True );
576 
577     aLoadArgs.merge( m_aDocMediaDescriptor, true );
578 
579     try
580     {
581         // set the document mode to embedded as the first step!!!
582         EmbedAndReparentDoc_Impl( xDocument );
583 
584         if ( xDoc.is() )
585         {
586             xDoc->loadFromStorage( xSourceStorage, aLoadArgs.getPropertyValues() );
587             if ( xSourceStorage != m_xObjectStorage )
588                 SwitchDocToStorage_Impl( xDoc, m_xObjectStorage );
589         }
590         else
591             xLoadable->load( aLoadArgs.getPropertyValues() );
592     }
593     catch( uno::Exception& )
594     {
595         uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
596         if ( xCloseable.is() )
597         {
598             try
599             {
600                 xCloseable->close( sal_True );
601             }
602             catch( uno::Exception& )
603             {
604                 DBG_UNHANDLED_EXCEPTION();
605             }
606         }
607 
608         throw; // TODO
609     }
610 
611     return xDocument;
612 }
613 
614 //------------------------------------------------------
StoreDocumentToTempStream_Impl(sal_Int32 nStorageFormat,const::rtl::OUString & aBaseURL,const::rtl::OUString & aHierarchName)615 uno::Reference< io::XInputStream > OCommonEmbeddedObject::StoreDocumentToTempStream_Impl(
616                                                                             sal_Int32 nStorageFormat,
617                                                                             const ::rtl::OUString& aBaseURL,
618                                                                             const ::rtl::OUString& aHierarchName )
619 {
620     uno::Reference < io::XOutputStream > xTempOut(
621                 m_xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
622                 uno::UNO_QUERY );
623     uno::Reference< io::XInputStream > aResult( xTempOut, uno::UNO_QUERY );
624 
625     if ( !xTempOut.is() || !aResult.is() )
626         throw uno::RuntimeException(); // TODO:
627 
628     uno::Reference< frame::XStorable > xStorable;
629     {
630         osl::MutexGuard aGuard( m_aMutex );
631         if ( m_pDocHolder )
632             xStorable = uno::Reference< frame::XStorable > ( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
633     }
634 
635     if( !xStorable.is() )
636         throw uno::RuntimeException(); // TODO:
637 
638     ::rtl::OUString aFilterName = GetFilterName( nStorageFormat );
639 
640     OSL_ENSURE( aFilterName.getLength(), "Wrong document service name!" );
641     if ( !aFilterName.getLength() )
642         throw io::IOException(); // TODO:
643 
644     uno::Sequence< beans::PropertyValue > aArgs( 4 );
645     aArgs[0].Name = ::rtl::OUString::createFromAscii( "FilterName" );
646     aArgs[0].Value <<= aFilterName;
647     aArgs[1].Name = ::rtl::OUString::createFromAscii( "OutputStream" );
648     aArgs[1].Value <<= xTempOut;
649     aArgs[2].Name = ::rtl::OUString::createFromAscii( "DocumentBaseURL" );
650     aArgs[2].Value <<= aBaseURL;
651     aArgs[3].Name = ::rtl::OUString::createFromAscii( "HierarchicalDocumentName" );
652     aArgs[3].Value <<= aHierarchName;
653 
654     xStorable->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aArgs );
655     try
656     {
657         xTempOut->closeOutput();
658     }
659     catch( uno::Exception& )
660     {
661         OSL_ENSURE( sal_False, "Looks like stream was closed already" );
662     }
663 
664     return aResult;
665 }
666 
667 //------------------------------------------------------
SaveObject_Impl()668 void OCommonEmbeddedObject::SaveObject_Impl()
669 {
670     if ( m_xClientSite.is() )
671     {
672         try
673         {
674             // check whether the component is modified,
675             // if not there is no need for storing
676             uno::Reference< util::XModifiable > xModifiable( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
677             if ( xModifiable.is() && !xModifiable->isModified() )
678                 return;
679         }
680         catch( uno::Exception& )
681         {}
682 
683         try {
684             m_xClientSite->saveObject();
685         }
686         catch( uno::Exception& )
687         {
688             OSL_ENSURE( sal_False, "The object was not stored!\n" );
689         }
690     }
691 }
692 
693 //------------------------------------------------------
GetBaseURL_Impl() const694 ::rtl::OUString OCommonEmbeddedObject::GetBaseURL_Impl() const
695 {
696     ::rtl::OUString aBaseURL;
697     sal_Int32 nInd = 0;
698 
699     if ( m_xClientSite.is() )
700     {
701         try
702         {
703             uno::Reference< frame::XModel > xParentModel( m_xClientSite->getComponent(), uno::UNO_QUERY_THROW );
704             uno::Sequence< beans::PropertyValue > aModelProps = xParentModel->getArgs();
705             for ( nInd = 0; nInd < aModelProps.getLength(); nInd++ )
706                 if ( aModelProps[nInd].Name.equals(
707                                                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentBaseURL" ) ) ) )
708                 {
709                     aModelProps[nInd].Value >>= aBaseURL;
710                     break;
711                 }
712 
713 
714         }
715         catch( uno::Exception& )
716         {}
717     }
718 
719     if ( !aBaseURL.getLength() )
720     {
721         for ( nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ )
722             if ( m_aDocMediaDescriptor[nInd].Name.equals(
723                                                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentBaseURL" ) ) ) )
724             {
725                 m_aDocMediaDescriptor[nInd].Value >>= aBaseURL;
726                 break;
727             }
728     }
729 
730     if ( !aBaseURL.getLength() )
731         aBaseURL = m_aDefaultParentBaseURL;
732 
733     return aBaseURL;
734 }
735 
736 //------------------------------------------------------
GetBaseURLFrom_Impl(const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)737 ::rtl::OUString OCommonEmbeddedObject::GetBaseURLFrom_Impl(
738                     const uno::Sequence< beans::PropertyValue >& lArguments,
739                     const uno::Sequence< beans::PropertyValue >& lObjArgs )
740 {
741     ::rtl::OUString aBaseURL;
742     sal_Int32 nInd = 0;
743 
744     for ( nInd = 0; nInd < lArguments.getLength(); nInd++ )
745         if ( lArguments[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentBaseURL" ) ) ) )
746         {
747             lArguments[nInd].Value >>= aBaseURL;
748             break;
749         }
750 
751     if ( !aBaseURL.getLength() )
752     {
753         for ( nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
754             if ( lObjArgs[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultParentBaseURL" ) ) ) )
755             {
756                 lObjArgs[nInd].Value >>= aBaseURL;
757                 break;
758             }
759     }
760 
761     return aBaseURL;
762 }
763 
764 
765 //------------------------------------------------------
SwitchDocToStorage_Impl(const uno::Reference<document::XStorageBasedDocument> & xDoc,const uno::Reference<embed::XStorage> & xStorage)766 void OCommonEmbeddedObject::SwitchDocToStorage_Impl( const uno::Reference< document::XStorageBasedDocument >& xDoc, const uno::Reference< embed::XStorage >& xStorage )
767 {
768     xDoc->switchToStorage( xStorage );
769 
770     uno::Reference< util::XModifiable > xModif( xDoc, uno::UNO_QUERY );
771     if ( xModif.is() )
772         xModif->setModified( sal_False );
773 
774     if ( m_xRecoveryStorage.is() )
775         m_xRecoveryStorage.clear();
776 }
777 
778 //------------------------------------------------------
StoreDocToStorage_Impl(const uno::Reference<embed::XStorage> & xStorage,sal_Int32 nStorageFormat,const::rtl::OUString & aBaseURL,const::rtl::OUString & aHierarchName,sal_Bool bAttachToTheStorage)779 void OCommonEmbeddedObject::StoreDocToStorage_Impl( const uno::Reference< embed::XStorage >& xStorage,
780                                                     sal_Int32 nStorageFormat,
781                                                     const ::rtl::OUString& aBaseURL,
782                                                     const ::rtl::OUString& aHierarchName,
783                                                     sal_Bool bAttachToTheStorage )
784 {
785     OSL_ENSURE( xStorage.is(), "No storage is provided for storing!" );
786 
787     if ( !xStorage.is() )
788         throw uno::RuntimeException(); // TODO:
789 
790 #ifdef USE_STORAGEBASED_DOCUMENT
791     uno::Reference< document::XStorageBasedDocument > xDoc;
792     {
793         osl::MutexGuard aGuard( m_aMutex );
794         if ( m_pDocHolder )
795             xDoc = uno::Reference< document::XStorageBasedDocument >( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
796     }
797 
798     if ( xDoc.is() )
799     {
800         ::rtl::OUString aFilterName = GetFilterName( nStorageFormat );
801 
802         OSL_ENSURE( aFilterName.getLength(), "Wrong document service name!" );
803         if ( !aFilterName.getLength() )
804             throw io::IOException(); // TODO:
805 
806         uno::Sequence< beans::PropertyValue > aArgs( 3 );
807         aArgs[0].Name = ::rtl::OUString::createFromAscii( "FilterName" );
808         aArgs[0].Value <<= aFilterName;
809         aArgs[2].Name = ::rtl::OUString::createFromAscii( "DocumentBaseURL" );
810         aArgs[2].Value <<= aBaseURL;
811         aArgs[1].Name = ::rtl::OUString::createFromAscii( "HierarchicalDocumentName" );
812         aArgs[1].Value <<= aHierarchName;
813 
814         xDoc->storeToStorage( xStorage, aArgs );
815         if ( bAttachToTheStorage )
816             SwitchDocToStorage_Impl( xDoc, xStorage );
817     }
818     else
819 #endif
820     {
821         // store document to temporary stream based on temporary file
822         uno::Reference < io::XInputStream > xTempIn = StoreDocumentToTempStream_Impl( nStorageFormat, aBaseURL, aHierarchName );
823 
824         OSL_ENSURE( xTempIn.is(), "The stream reference can not be empty!\n" );
825 
826         // open storage based on document temporary file for reading
827         uno::Reference < lang::XSingleServiceFactory > xStorageFactory(
828                     m_xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.embed.StorageFactory" ) ),
829                     uno::UNO_QUERY );
830 
831         uno::Sequence< uno::Any > aArgs(1);
832         aArgs[0] <<= xTempIn;
833         uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArgs ),
834                                                             uno::UNO_QUERY );
835         if ( !xTempStorage.is() )
836             throw uno::RuntimeException(); // TODO:
837 
838         // object storage must be committed automatically
839         xTempStorage->copyToStorage( xStorage );
840     }
841 }
842 
843 //------------------------------------------------------
CreateDocFromMediaDescr_Impl(const uno::Sequence<beans::PropertyValue> & aMedDescr)844 uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateDocFromMediaDescr_Impl(
845                                         const uno::Sequence< beans::PropertyValue >& aMedDescr )
846 {
847     uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(),
848                                                 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
849 
850     uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY );
851     if ( !xLoadable.is() )
852         throw uno::RuntimeException();
853 
854     try
855     {
856         // set the document mode to embedded as the first action on the document!!!
857         EmbedAndReparentDoc_Impl( xDocument );
858 
859         xLoadable->load( addAsTemplate( aMedDescr ) );
860     }
861     catch( uno::Exception& )
862     {
863         uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
864         if ( xCloseable.is() )
865         {
866             try
867             {
868                 xCloseable->close( sal_True );
869             }
870             catch( uno::Exception& )
871             {
872             }
873         }
874 
875         throw; // TODO
876     }
877 
878     return xDocument;
879 }
880 
881 //------------------------------------------------------
CreateTempDocFromLink_Impl()882 uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateTempDocFromLink_Impl()
883 {
884     uno::Reference< util::XCloseable > xResult;
885 
886     OSL_ENSURE( m_bIsLink, "The object is not a linked one!\n" );
887 
888     uno::Sequence< beans::PropertyValue > aTempMediaDescr;
889 
890     sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
891     try {
892         nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
893     }
894     catch ( beans::IllegalTypeException& )
895     {
896         // the container just has an unknown type, use current file format
897     }
898     catch ( uno::Exception& )
899     {
900         OSL_ENSURE( sal_False, "Can not retrieve storage media type!\n" );
901     }
902 
903     if ( m_pDocHolder->GetComponent().is() )
904     {
905         aTempMediaDescr.realloc( 4 );
906 
907         // TODO/LATER: may be private:stream should be used as target URL
908         ::rtl::OUString aTempFileURL;
909         uno::Reference< io::XInputStream > xTempStream = StoreDocumentToTempStream_Impl( SOFFICE_FILEFORMAT_CURRENT,
910                                                                                          ::rtl::OUString(),
911                                                                                          ::rtl::OUString() );
912         try
913         {
914             // no need to let the file stay after the stream is removed since the embedded document
915             // can not be stored directly
916             uno::Reference< beans::XPropertySet > xTempStreamProps( xTempStream, uno::UNO_QUERY_THROW );
917             xTempStreamProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ) >>= aTempFileURL;
918         }
919         catch( uno::Exception& )
920         {
921         }
922 
923         OSL_ENSURE( aTempFileURL.getLength(), "Couldn't retrieve temporary file URL!\n" );
924 
925         aTempMediaDescr[0].Name = ::rtl::OUString::createFromAscii( "URL" );
926         aTempMediaDescr[0].Value <<= aTempFileURL;
927         aTempMediaDescr[1].Name = ::rtl::OUString::createFromAscii( "InputStream" );
928         aTempMediaDescr[1].Value <<= xTempStream;
929         aTempMediaDescr[2].Name = ::rtl::OUString::createFromAscii( "FilterName" );
930         aTempMediaDescr[2].Value <<= GetFilterName( nStorageFormat );
931         aTempMediaDescr[3].Name = ::rtl::OUString::createFromAscii( "AsTemplate" );
932         aTempMediaDescr[3].Value <<= sal_True;
933     }
934     else
935     {
936         aTempMediaDescr.realloc( 2 );
937         aTempMediaDescr[0].Name = ::rtl::OUString::createFromAscii( "URL" );
938         aTempMediaDescr[0].Value <<= m_aLinkURL;
939         aTempMediaDescr[1].Name = ::rtl::OUString::createFromAscii( "FilterName" );
940         aTempMediaDescr[1].Value <<= m_aLinkFilterName;
941         // aTempMediaDescr[2].Name = ::rtl::OUString::createFromAscii( "AsTemplate" );
942         // aTempMediaDescr[2].Value <<= sal_True;
943     }
944 
945     xResult = CreateDocFromMediaDescr_Impl( aTempMediaDescr );
946 
947     return xResult;
948 }
949 
950 //------------------------------------------------------
setPersistentEntry(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName,sal_Int32 nEntryConnectionMode,const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)951 void SAL_CALL OCommonEmbeddedObject::setPersistentEntry(
952                     const uno::Reference< embed::XStorage >& xStorage,
953                     const ::rtl::OUString& sEntName,
954                     sal_Int32 nEntryConnectionMode,
955                     const uno::Sequence< beans::PropertyValue >& lArguments,
956                     const uno::Sequence< beans::PropertyValue >& lObjArgs )
957 {
958     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::setPersistentEntry" );
959 
960     // the type of the object must be already set
961     // a kind of typedetection should be done in the factory
962 
963     ::osl::MutexGuard aGuard( m_aMutex );
964     if ( m_bDisposed )
965         throw lang::DisposedException(); // TODO
966 
967     if ( !xStorage.is() )
968         throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
969                                             uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
970                                             1 );
971 
972     if ( !sEntName.getLength() )
973         throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
974                                             uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
975                                             2 );
976 
977     // May be LOADED should be forbidden here ???
978     if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
979       && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) )
980     {
981         // if the object is not loaded
982         // it can not get persistent representation without initialization
983 
984         // if the object is loaded
985         // it can switch persistent representation only without initialization
986 
987         throw embed::WrongStateException(
988                     ::rtl::OUString::createFromAscii( "Can't change persistent representation of activated object!\n" ),
989                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
990     }
991 
992     if ( m_bWaitSaveCompleted )
993     {
994         if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
995         {
996             // saveCompleted is expected, handle it accordingly
997             if ( m_xNewParentStorage == xStorage && m_aNewEntryName.equals( sEntName ) )
998             {
999                 saveCompleted( sal_True );
1000                 return;
1001             }
1002 
1003             // if a completely different entry is provided, switch first back to the old persistence in saveCompleted
1004             // and then switch to the target persistence
1005             sal_Bool bSwitchFurther = ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) );
1006             saveCompleted( sal_False );
1007             if ( !bSwitchFurther )
1008                 return;
1009         }
1010         else
1011             throw embed::WrongStateException(
1012                         ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1013                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1014     }
1015 
1016     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1017     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1018     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1019     if ( m_bIsLink )
1020     {
1021         m_aEntryName = sEntName;
1022         return;
1023     }
1024 
1025     uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
1026     if ( !xNameAccess.is() )
1027         throw uno::RuntimeException(); //TODO
1028 
1029     // detect entry existence
1030     sal_Bool bElExists = xNameAccess->hasByName( sEntName );
1031 
1032     m_aDocMediaDescriptor = GetValuableArgs_Impl( lArguments,
1033                                                   nEntryConnectionMode != embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT );
1034 
1035     m_bReadOnly = sal_False;
1036     for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1037         if ( lArguments[nInd].Name.equalsAscii( "ReadOnly" ) )
1038             lArguments[nInd].Value >>= m_bReadOnly;
1039 
1040     // TODO: use lObjArgs for StoreVisualReplacement
1041     for ( sal_Int32 nObjInd = 0; nObjInd < lObjArgs.getLength(); nObjInd++ )
1042         if ( lObjArgs[nObjInd].Name.equalsAscii( "OutplaceDispatchInterceptor" ) )
1043         {
1044             uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor;
1045             if ( lObjArgs[nObjInd].Value >>= xDispatchInterceptor )
1046                 m_pDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor );
1047         }
1048         else if ( lObjArgs[nObjInd].Name.equalsAscii( "DefaultParentBaseURL" ) )
1049         {
1050             lObjArgs[nObjInd].Value >>= m_aDefaultParentBaseURL;
1051         }
1052         else if ( lObjArgs[nObjInd].Name.equalsAscii( "Parent" ) )
1053         {
1054             lObjArgs[nObjInd].Value >>= m_xParent;
1055         }
1056         else if ( lObjArgs[nObjInd].Name.equalsAscii( "IndividualMiscStatus" ) )
1057         {
1058             sal_Int64 nMiscStatus=0;
1059             lObjArgs[nObjInd].Value >>= nMiscStatus;
1060             m_nMiscStatus |= nMiscStatus;
1061         }
1062         else if ( lObjArgs[nObjInd].Name.equalsAscii( "CloneFrom" ) )
1063         {
1064             uno::Reference < embed::XEmbeddedObject > xObj;
1065             lObjArgs[nObjInd].Value >>= xObj;
1066             if ( xObj.is() )
1067             {
1068                 m_bHasClonedSize = sal_True;
1069                 m_aClonedSize = xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1070                 m_nClonedMapUnit = xObj->getMapUnit( embed::Aspects::MSOLE_CONTENT );
1071             }
1072         }
1073         else if ( lObjArgs[nObjInd].Name.equalsAscii( "OutplaceFrameProperties" ) )
1074         {
1075             uno::Sequence< uno::Any > aOutFrameProps;
1076             uno::Sequence< beans::NamedValue > aOutFramePropsTyped;
1077             if ( lObjArgs[nObjInd].Value >>= aOutFrameProps )
1078             {
1079                 m_pDocHolder->SetOutplaceFrameProperties( aOutFrameProps );
1080             }
1081             else if ( lObjArgs[nObjInd].Value >>= aOutFramePropsTyped )
1082             {
1083                 aOutFrameProps.realloc( aOutFramePropsTyped.getLength() );
1084                 uno::Any* pProp = aOutFrameProps.getArray();
1085                 for (   const beans::NamedValue* pTypedProp = aOutFramePropsTyped.getConstArray();
1086                         pTypedProp != aOutFramePropsTyped.getConstArray() + aOutFramePropsTyped.getLength();
1087                         ++pTypedProp, ++pProp
1088                     )
1089                 {
1090                     *pProp <<= *pTypedProp;
1091                 }
1092                 m_pDocHolder->SetOutplaceFrameProperties( aOutFrameProps );
1093             }
1094             else
1095                 OSL_ENSURE( false, "OCommonEmbeddedObject::setPersistentEntry: illegal type for argument 'OutplaceFrameProperties'!" );
1096         }
1097         else if ( lObjArgs[nObjInd].Name.equalsAscii( "ModuleName" ) )
1098         {
1099             lObjArgs[nObjInd].Value >>= m_aModuleName;
1100         }
1101         else if ( lObjArgs[nObjInd].Name.equalsAscii( "EmbeddedScriptSupport" ) )
1102         {
1103             OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_bEmbeddedScriptSupport );
1104         }
1105         else if ( lObjArgs[nObjInd].Name.equalsAscii( "DocumentRecoverySupport" ) )
1106         {
1107             OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_bDocumentRecoverySupport );
1108         }
1109         else if ( lObjArgs[nObjInd].Name.equalsAscii( "RecoveryStorage" ) )
1110         {
1111             OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_xRecoveryStorage );
1112         }
1113 
1114 
1115     sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
1116 
1117     SwitchOwnPersistence( xStorage, sEntName );
1118 
1119     if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT )
1120     {
1121         if ( bElExists )
1122         {
1123             // the initialization from existing storage allows to leave object in loaded state
1124             m_nObjectState = embed::EmbedStates::LOADED;
1125         }
1126         else
1127         {
1128             m_pDocHolder->SetComponent( InitNewDocument_Impl(), m_bReadOnly );
1129             if ( !m_pDocHolder->GetComponent().is() )
1130                 throw io::IOException(); // TODO: can not create document
1131 
1132             m_nObjectState = embed::EmbedStates::RUNNING;
1133         }
1134     }
1135     else
1136     {
1137         if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE )
1138             throw io::IOException();
1139 
1140         if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1141         {
1142             // the document just already changed its storage to store to
1143             // the links to OOo documents for now ignore this call
1144             // TODO: OOo links will have persistence so it will be switched here
1145         }
1146         else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT )
1147         {
1148             if ( m_xRecoveryStorage.is() )
1149                 TransferMediaType( m_xRecoveryStorage, m_xObjectStorage );
1150 
1151             // TODO:
1152             m_pDocHolder->SetComponent( InitNewDocument_Impl(), m_bReadOnly );
1153 
1154             if ( !m_pDocHolder->GetComponent().is() )
1155                 throw io::IOException(); // TODO: can not create document
1156 
1157             m_nObjectState = embed::EmbedStates::RUNNING;
1158         }
1159         else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT )
1160         {
1161             m_pDocHolder->SetComponent( CreateDocFromMediaDescr_Impl( lArguments ), m_bReadOnly );
1162             m_nObjectState = embed::EmbedStates::RUNNING;
1163         }
1164         //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1165         //{
1166             //TODO:
1167         //}
1168         else
1169             throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong connection mode is provided!\n" ),
1170                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1171                                         3 );
1172     }
1173 }
1174 
1175 //------------------------------------------------------
storeToEntry(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName,const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1176 void SAL_CALL OCommonEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage,
1177                             const ::rtl::OUString& sEntName,
1178                             const uno::Sequence< beans::PropertyValue >& lArguments,
1179                             const uno::Sequence< beans::PropertyValue >& lObjArgs )
1180 {
1181     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::storeToEntry" );
1182 
1183     ::osl::ResettableMutexGuard aGuard( m_aMutex );
1184     if ( m_bDisposed )
1185         throw lang::DisposedException(); // TODO
1186 
1187     if ( m_nObjectState == -1 )
1188     {
1189         // the object is still not loaded
1190         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1191                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1192     }
1193 
1194     if ( m_bWaitSaveCompleted )
1195         throw embed::WrongStateException(
1196                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1197                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1198 
1199     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1200     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1201     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1202     if ( m_bIsLink )
1203         return;
1204 
1205     OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" );
1206 
1207     sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1208     sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1209     try {
1210         nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage );
1211     }
1212     catch ( beans::IllegalTypeException& )
1213     {
1214         // the container just has an unknown type, use current file format
1215     }
1216     catch ( uno::Exception& )
1217     {
1218         OSL_ENSURE( sal_False, "Can not retrieve target storage media type!\n" );
1219     }
1220 
1221     try
1222     {
1223         nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
1224     }
1225     catch ( beans::IllegalTypeException& )
1226     {
1227         // the container just has an unknown type, use current file format
1228     }
1229     catch ( uno::Exception& )
1230     {
1231         OSL_ENSURE( sal_False, "Can not retrieve own storage media type!\n" );
1232     }
1233 
1234     sal_Bool bTryOptimization = sal_False;
1235     for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1236     {
1237         // StoreVisualReplacement and VisualReplacement args have no sense here
1238         if ( lObjArgs[nInd].Name.equalsAscii( "CanTryOptimization" ) )
1239             lObjArgs[nInd].Value >>= bTryOptimization;
1240     }
1241 
1242     sal_Bool bSwitchBackToLoaded = sal_False;
1243 
1244     // strict ODF 1.2: write the object anew instead of copying a stream that may not be strict;
1245     // if the object can not be started the stream is copied as before
1246     if ( m_nObjectState == embed::EmbedStates::LOADED && IsStrictODF12_Impl( m_xFactory ) )
1247     {
1248         try
1249         {
1250             changeState( embed::EmbedStates::RUNNING );
1251             bSwitchBackToLoaded = sal_True;
1252         }
1253         catch ( uno::Exception& )
1254         {
1255         }
1256     }
1257 
1258     // Storing to different format can be done only in running state.
1259     if ( m_nObjectState == embed::EmbedStates::LOADED )
1260     {
1261         // TODO/LATER: copying is not legal for documents with relative links.
1262         if ( nTargetStorageFormat == nOriginalStorageFormat )
1263         {
1264             sal_Bool bOptimizationWorks = sal_False;
1265             if ( bTryOptimization )
1266             {
1267                 try
1268                 {
1269                     // try to use optimized copying
1270                     uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW );
1271                     uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW );
1272                     xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName );
1273                     bOptimizationWorks = sal_True;
1274                 }
1275                 catch( uno::Exception& )
1276                 {
1277                 }
1278             }
1279 
1280             if ( !bOptimizationWorks )
1281                 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
1282         }
1283         else
1284         {
1285             changeState( embed::EmbedStates::RUNNING );
1286             bSwitchBackToLoaded = sal_True;
1287         }
1288     }
1289 
1290     if ( m_nObjectState != embed::EmbedStates::LOADED )
1291     {
1292         uno::Reference< embed::XStorage > xSubStorage =
1293                     xStorage->openStorageElement( sEntName, embed::ElementModes::READWRITE );
1294 
1295         if ( !xSubStorage.is() )
1296             throw uno::RuntimeException(); //TODO
1297 
1298         aGuard.clear();
1299         // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1300         StoreDocToStorage_Impl( xSubStorage, nTargetStorageFormat, GetBaseURLFrom_Impl( lArguments, lObjArgs ), sEntName, sal_False );
1301         aGuard.reset();
1302 
1303         if ( bSwitchBackToLoaded )
1304             changeState( embed::EmbedStates::LOADED );
1305     }
1306 
1307     // TODO: should the listener notification be done?
1308 }
1309 
1310 //------------------------------------------------------
storeAsEntry(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName,const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1311 void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage,
1312                             const ::rtl::OUString& sEntName,
1313                             const uno::Sequence< beans::PropertyValue >& lArguments,
1314                             const uno::Sequence< beans::PropertyValue >& lObjArgs )
1315 {
1316     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::storeAsEntry" );
1317 
1318     // TODO: use lObjArgs
1319 
1320     ::osl::ResettableMutexGuard aGuard( m_aMutex );
1321     if ( m_bDisposed )
1322         throw lang::DisposedException(); // TODO
1323 
1324     if ( m_nObjectState == -1 )
1325     {
1326         // the object is still not loaded
1327         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1328                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1329     }
1330 
1331     if ( m_bWaitSaveCompleted )
1332         throw embed::WrongStateException(
1333                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1334                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1335 
1336     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1337     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1338     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1339     if ( m_bIsLink )
1340     {
1341         m_aNewEntryName = sEntName;
1342         return;
1343     }
1344 
1345     OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" );
1346 
1347     sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1348     sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1349     try {
1350         nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage );
1351     }
1352     catch ( beans::IllegalTypeException& )
1353     {
1354         // the container just has an unknown type, use current file format
1355     }
1356     catch ( uno::Exception& )
1357     {
1358         OSL_ENSURE( sal_False, "Can not retrieve target storage media type!\n" );
1359     }
1360 
1361     try
1362     {
1363         nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
1364     }
1365     catch ( beans::IllegalTypeException& )
1366     {
1367         // the container just has an unknown type, use current file format
1368     }
1369     catch ( uno::Exception& )
1370     {
1371         OSL_ENSURE( sal_False, "Can not retrieve own storage media type!\n" );
1372     }
1373 
1374     PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSaveAs" ) );
1375 
1376     sal_Bool bTryOptimization = sal_False;
1377     for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1378     {
1379         // StoreVisualReplacement and VisualReplacement args have no sense here
1380         if ( lObjArgs[nInd].Name.equalsAscii( "CanTryOptimization" ) )
1381             lObjArgs[nInd].Value >>= bTryOptimization;
1382     }
1383 
1384     sal_Bool bSwitchBackToLoaded = sal_False;
1385 
1386     // strict ODF 1.2: write the object anew instead of copying a stream that may not be strict;
1387     // if the object can not be started the stream is copied as before
1388     if ( m_nObjectState == embed::EmbedStates::LOADED && IsStrictODF12_Impl( m_xFactory ) )
1389     {
1390         try
1391         {
1392             changeState( embed::EmbedStates::RUNNING );
1393             bSwitchBackToLoaded = sal_True;
1394         }
1395         catch ( uno::Exception& )
1396         {
1397         }
1398     }
1399 
1400     // Storing to different format can be done only in running state.
1401     if ( m_nObjectState == embed::EmbedStates::LOADED )
1402     {
1403         // TODO/LATER: copying is not legal for documents with relative links.
1404         if ( nTargetStorageFormat == nOriginalStorageFormat )
1405         {
1406             sal_Bool bOptimizationWorks = sal_False;
1407             if ( bTryOptimization )
1408             {
1409                 try
1410                 {
1411                     // try to use optimized copying
1412                     uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW );
1413                     uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW );
1414                     xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName );
1415                     bOptimizationWorks = sal_True;
1416                 }
1417                 catch( uno::Exception& )
1418                 {
1419                 }
1420             }
1421 
1422             if ( !bOptimizationWorks )
1423                 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
1424         }
1425         else
1426         {
1427             changeState( embed::EmbedStates::RUNNING );
1428             bSwitchBackToLoaded = sal_True;
1429         }
1430     }
1431 
1432     uno::Reference< embed::XStorage > xSubStorage =
1433                 xStorage->openStorageElement( sEntName, embed::ElementModes::READWRITE );
1434 
1435     if ( !xSubStorage.is() )
1436         throw uno::RuntimeException(); //TODO
1437 
1438     if ( m_nObjectState != embed::EmbedStates::LOADED )
1439     {
1440         aGuard.clear();
1441         // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1442         StoreDocToStorage_Impl( xSubStorage, nTargetStorageFormat, GetBaseURLFrom_Impl( lArguments, lObjArgs ), sEntName, sal_False );
1443         aGuard.reset();
1444 
1445         if ( bSwitchBackToLoaded )
1446             changeState( embed::EmbedStates::LOADED );
1447     }
1448 
1449     m_bWaitSaveCompleted = sal_True;
1450     m_xNewObjectStorage = xSubStorage;
1451     m_xNewParentStorage = xStorage;
1452     m_aNewEntryName = sEntName;
1453     m_aNewDocMediaDescriptor = GetValuableArgs_Impl( lArguments, sal_True );
1454 
1455     // TODO: register listeners for storages above, in case thay are disposed
1456     //       an exception will be thrown on saveCompleted( true )
1457 
1458     // TODO: should the listener notification be done here or in saveCompleted?
1459 }
1460 
1461 //------------------------------------------------------
saveCompleted(sal_Bool bUseNew)1462 void SAL_CALL OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew )
1463 {
1464     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::saveCompleted" );
1465 
1466     ::osl::MutexGuard aGuard( m_aMutex );
1467     if ( m_bDisposed )
1468         throw lang::DisposedException(); // TODO
1469 
1470     if ( m_nObjectState == -1 )
1471     {
1472         // the object is still not loaded
1473         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1474                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1475     }
1476 
1477     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1478     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1479     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1480     if ( m_bIsLink )
1481     {
1482         if ( bUseNew )
1483             m_aEntryName = m_aNewEntryName;
1484         m_aNewEntryName = ::rtl::OUString();
1485         return;
1486     }
1487 
1488     // it is allowed to call saveCompleted( false ) for nonstored objects
1489     if ( !m_bWaitSaveCompleted && !bUseNew )
1490         return;
1491 
1492     OSL_ENSURE( m_bWaitSaveCompleted, "Unexpected saveCompleted() call!\n" );
1493     if ( !m_bWaitSaveCompleted )
1494         throw io::IOException(); // TODO: illegal call
1495 
1496     OSL_ENSURE( m_xNewObjectStorage.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" );
1497     if ( !m_xNewObjectStorage.is() || !m_xNewParentStorage.is() )
1498         throw uno::RuntimeException(); // TODO: broken internal information
1499 
1500     if ( bUseNew )
1501     {
1502         SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStorage, m_aNewEntryName );
1503         m_aDocMediaDescriptor = m_aNewDocMediaDescriptor;
1504 
1505         uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
1506         if ( xModif.is() )
1507             xModif->setModified( sal_False );
1508 
1509         PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSaveAsDone" ) );
1510     }
1511     else
1512     {
1513         try {
1514             uno::Reference< lang::XComponent > xComponent( m_xNewObjectStorage, uno::UNO_QUERY );
1515             OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" );
1516             if ( xComponent.is() )
1517                 xComponent->dispose();
1518         }
1519         catch ( uno::Exception& )
1520         {
1521         }
1522     }
1523 
1524     m_xNewObjectStorage = uno::Reference< embed::XStorage >();
1525     m_xNewParentStorage = uno::Reference< embed::XStorage >();
1526     m_aNewEntryName = ::rtl::OUString();
1527     m_aNewDocMediaDescriptor.realloc( 0 );
1528     m_bWaitSaveCompleted = sal_False;
1529 
1530     if ( bUseNew )
1531     {
1532         // TODO: notify listeners
1533 
1534         if ( m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE )
1535         {
1536             // TODO: update visual representation
1537         }
1538     }
1539 }
1540 
1541 //------------------------------------------------------
hasEntry()1542 sal_Bool SAL_CALL OCommonEmbeddedObject::hasEntry()
1543 {
1544     ::osl::MutexGuard aGuard( m_aMutex );
1545     if ( m_bDisposed )
1546         throw lang::DisposedException(); // TODO
1547 
1548     if ( m_bWaitSaveCompleted )
1549         throw embed::WrongStateException(
1550                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1551                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1552 
1553     if ( m_xObjectStorage.is() )
1554         return sal_True;
1555 
1556     return sal_False;
1557 }
1558 
1559 //------------------------------------------------------
getEntryName()1560 ::rtl::OUString SAL_CALL OCommonEmbeddedObject::getEntryName()
1561 {
1562     ::osl::MutexGuard aGuard( m_aMutex );
1563     if ( m_bDisposed )
1564         throw lang::DisposedException(); // TODO
1565 
1566     if ( m_nObjectState == -1 )
1567     {
1568         // the object is still not loaded
1569         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ),
1570                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1571     }
1572 
1573     if ( m_bWaitSaveCompleted )
1574         throw embed::WrongStateException(
1575                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1576                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1577 
1578     return m_aEntryName;
1579 }
1580 
1581 //------------------------------------------------------
storeOwn()1582 void SAL_CALL OCommonEmbeddedObject::storeOwn()
1583 {
1584     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::storeOwn" );
1585 
1586     // during switching from Activated to Running and from Running to Loaded states the object will
1587     // ask container to store the object, the container has to make decision
1588     // to do so or not
1589 
1590     ::osl::ResettableMutexGuard aGuard( m_aMutex );
1591     if ( m_bDisposed )
1592         throw lang::DisposedException(); // TODO
1593 
1594     if ( m_nObjectState == -1 )
1595     {
1596         // the object is still not loaded
1597         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1598                                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1599     }
1600 
1601     if ( m_bWaitSaveCompleted )
1602         throw embed::WrongStateException(
1603                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1604                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1605 
1606     if ( m_bReadOnly )
1607         throw io::IOException(); // TODO: access denied
1608 
1609     // nothing to do, if the object is in loaded state
1610     if ( m_nObjectState == embed::EmbedStates::LOADED )
1611         return;
1612 
1613     PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSave" ) );
1614 
1615     OSL_ENSURE( m_pDocHolder->GetComponent().is(), "If an object is activated or in running state it must have a document!\n" );
1616     if ( !m_pDocHolder->GetComponent().is() )
1617         throw uno::RuntimeException();
1618 
1619     if ( m_bIsLink )
1620     {
1621         // TODO: just store the document to it's location
1622         uno::Reference< frame::XStorable > xStorable( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
1623         if ( !xStorable.is() )
1624             throw uno::RuntimeException(); // TODO
1625 
1626         // free the main mutex for the storing time
1627         aGuard.clear();
1628 
1629         xStorable->store();
1630 
1631         aGuard.reset();
1632     }
1633     else
1634     {
1635         OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" );
1636 
1637         if ( !m_xObjectStorage.is() )
1638             throw io::IOException(); //TODO: access denied
1639 
1640         sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1641         try {
1642             nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
1643         }
1644         catch ( beans::IllegalTypeException& )
1645         {
1646             // the container just has an unknown type, use current file format
1647         }
1648         catch ( uno::Exception& )
1649         {
1650             OSL_ENSURE( sal_False, "Can not retrieve storage media type!\n" );
1651         }
1652 
1653         aGuard.clear();
1654         StoreDocToStorage_Impl( m_xObjectStorage, nStorageFormat, GetBaseURL_Impl(), m_aEntryName, sal_True );
1655         aGuard.reset();
1656     }
1657 
1658     uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
1659     if ( xModif.is() )
1660         xModif->setModified( sal_False );
1661 
1662     PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSaveDone" ) );
1663 }
1664 
1665 //------------------------------------------------------
isReadonly()1666 sal_Bool SAL_CALL OCommonEmbeddedObject::isReadonly()
1667 {
1668     ::osl::MutexGuard aGuard( m_aMutex );
1669     if ( m_bDisposed )
1670         throw lang::DisposedException(); // TODO
1671 
1672     if ( m_nObjectState == -1 )
1673     {
1674         // the object is still not loaded
1675         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ),
1676                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1677     }
1678 
1679     if ( m_bWaitSaveCompleted )
1680         throw embed::WrongStateException(
1681                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1682                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1683 
1684     return m_bReadOnly;
1685 }
1686 
1687 //------------------------------------------------------
reload(const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1688 void SAL_CALL OCommonEmbeddedObject::reload(
1689                 const uno::Sequence< beans::PropertyValue >& lArguments,
1690                 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1691 {
1692     // TODO: use lObjArgs
1693     // for now this method is used only to switch readonly state
1694 
1695     ::osl::MutexGuard aGuard( m_aMutex );
1696     if ( m_bDisposed )
1697         throw lang::DisposedException(); // TODO
1698 
1699     if ( m_nObjectState == -1 )
1700     {
1701         // the object is still not loaded
1702         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ),
1703                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1704     }
1705 
1706     if ( m_nObjectState != embed::EmbedStates::LOADED )
1707     {
1708         // the object is still not loaded
1709         throw embed::WrongStateException(
1710                                 ::rtl::OUString::createFromAscii( "The object must be in loaded state to be reloaded!\n" ),
1711                                 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1712     }
1713 
1714     if ( m_bWaitSaveCompleted )
1715         throw embed::WrongStateException(
1716                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1717                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1718 
1719     if ( m_bIsLink )
1720     {
1721         // reload of the link
1722         ::rtl::OUString aOldLinkFilter = m_aLinkFilterName;
1723 
1724         ::rtl::OUString aNewLinkFilter;
1725         for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1726         {
1727             if ( lArguments[nInd].Name.equalsAscii( "URL" ) )
1728             {
1729                 // the new URL
1730                 lArguments[nInd].Value >>= m_aLinkURL;
1731                 m_aLinkFilterName = ::rtl::OUString();
1732             }
1733             else if ( lArguments[nInd].Name.equalsAscii( "FilterName" ) )
1734             {
1735                 lArguments[nInd].Value >>= aNewLinkFilter;
1736                 m_aLinkFilterName = ::rtl::OUString();
1737             }
1738         }
1739 
1740         ::comphelper::MimeConfigurationHelper aHelper( m_xFactory );
1741         if ( !m_aLinkFilterName.getLength() )
1742         {
1743             if ( aNewLinkFilter.getLength() )
1744                 m_aLinkFilterName = aNewLinkFilter;
1745             else
1746             {
1747                 uno::Sequence< beans::PropertyValue > aArgs( 1 );
1748                 aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
1749                 aArgs[0].Value <<= m_aLinkURL;
1750                 m_aLinkFilterName = aHelper.UpdateMediaDescriptorWithFilterName( aArgs, sal_False );
1751             }
1752         }
1753 
1754         if ( !aOldLinkFilter.equals( m_aLinkFilterName ) )
1755         {
1756             uno::Sequence< beans::NamedValue > aObject = aHelper.GetObjectPropsByFilter( m_aLinkFilterName );
1757 
1758             // TODO/LATER: probably the document holder could be cleaned explicitly as in the destructor
1759             m_pDocHolder->release();
1760             m_pDocHolder = NULL;
1761 
1762             LinkInit_Impl( aObject, lArguments, lObjArgs );
1763         }
1764     }
1765 
1766     m_aDocMediaDescriptor = GetValuableArgs_Impl( lArguments, sal_True );
1767 
1768     // TODO: use lObjArgs for StoreVisualReplacement
1769     for ( sal_Int32 nObjInd = 0; nObjInd < lObjArgs.getLength(); nObjInd++ )
1770         if ( lObjArgs[nObjInd].Name.equalsAscii( "OutplaceDispatchInterceptor" ) )
1771         {
1772             uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor;
1773             if ( lObjArgs[nObjInd].Value >>= xDispatchInterceptor )
1774                 m_pDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor );
1775 
1776             break;
1777         }
1778 
1779     // TODO:
1780     // when document allows reloading through API the object can be reloaded not only in loaded state
1781 
1782     sal_Bool bOldReadOnlyValue = m_bReadOnly;
1783 
1784     m_bReadOnly = sal_False;
1785     for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1786         if ( lArguments[nInd].Name.equalsAscii( "ReadOnly" ) )
1787             lArguments[nInd].Value >>= m_bReadOnly;
1788 
1789     if ( bOldReadOnlyValue != m_bReadOnly && !m_bIsLink )
1790     {
1791         // close own storage
1792         try {
1793             uno::Reference< lang::XComponent > xComponent( m_xObjectStorage, uno::UNO_QUERY );
1794             OSL_ENSURE( !m_xObjectStorage.is() || xComponent.is(), "Wrong storage implementation!" );
1795             if ( xComponent.is() )
1796                 xComponent->dispose();
1797         }
1798         catch ( uno::Exception& )
1799         {
1800         }
1801 
1802         sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
1803         m_xObjectStorage = m_xParentStorage->openStorageElement( m_aEntryName, nStorageMode );
1804     }
1805 }
1806 
1807 //------------------------------------------------------
breakLink(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName)1808 void SAL_CALL OCommonEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage,
1809                                                 const ::rtl::OUString& sEntName )
1810 {
1811     ::osl::ResettableMutexGuard aGuard( m_aMutex );
1812     if ( m_bDisposed )
1813         throw lang::DisposedException(); // TODO
1814 
1815     if ( !m_bIsLink )
1816     {
1817         // it must be a linked initialized object
1818         throw embed::WrongStateException(
1819                     ::rtl::OUString::createFromAscii( "The object is not a valid linked object!\n" ),
1820                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1821     }
1822 #if 0
1823     else
1824     {
1825         // the current implementation of OOo links does not implement this method since it does not implement
1826         // all the set of interfaces required for OOo embedded object ( XEmbedPersist is not supported ).
1827         throw io::IOException(); // TODO:
1828     }
1829 #endif
1830 
1831     if ( !xStorage.is() )
1832         throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
1833                                             uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1834                                             1 );
1835 
1836     if ( !sEntName.getLength() )
1837         throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
1838                                             uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1839                                             2 );
1840 
1841     if ( !m_bIsLink || m_nObjectState == -1 )
1842     {
1843         // it must be a linked initialized object
1844         throw embed::WrongStateException(
1845                     ::rtl::OUString::createFromAscii( "The object is not a valid linked object!\n" ),
1846                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1847     }
1848 
1849     if ( m_bWaitSaveCompleted )
1850         throw embed::WrongStateException(
1851                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1852                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1853 
1854     uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
1855     if ( !xNameAccess.is() )
1856         throw uno::RuntimeException(); //TODO
1857 
1858     // detect entry existence
1859     /*sal_Bool bElExists =*/ xNameAccess->hasByName( sEntName );
1860 
1861     m_bReadOnly = sal_False;
1862 //  sal_Int32 nStorageMode = embed::ElementModes::READWRITE;
1863 
1864     if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) )
1865         SwitchOwnPersistence( xStorage, sEntName );
1866 
1867     // for linked object it means that it becomes embedded object
1868     // the document must switch it's persistence also
1869 
1870     // TODO/LATER: handle the case when temp doc can not be created
1871     // the document is a new embedded object so it must be marked as modified
1872     uno::Reference< util::XCloseable > xDocument = CreateTempDocFromLink_Impl();
1873     uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
1874     if ( !xModif.is() )
1875         throw uno::RuntimeException();
1876     try
1877     {
1878         xModif->setModified( sal_True );
1879     }
1880     catch( uno::Exception& )
1881     {}
1882 
1883     m_pDocHolder->SetComponent( xDocument, m_bReadOnly );
1884     OSL_ENSURE( m_pDocHolder->GetComponent().is(), "If document can't be created, an exception must be thrown!\n" );
1885 
1886     if ( m_nObjectState == embed::EmbedStates::LOADED )
1887     {
1888         // the state is changed and can not be switched to loaded state back without saving
1889         m_nObjectState = embed::EmbedStates::RUNNING;
1890         StateChangeNotification_Impl( sal_False, embed::EmbedStates::LOADED, m_nObjectState, aGuard );
1891     }
1892     else if ( m_nObjectState == embed::EmbedStates::ACTIVE )
1893         m_pDocHolder->Show();
1894 
1895     m_bIsLink = sal_False;
1896     m_aLinkFilterName = ::rtl::OUString();
1897     m_aLinkURL = ::rtl::OUString();
1898 }
1899 
1900 //------------------------------------------------------
isLink()1901 sal_Bool SAL_CALL  OCommonEmbeddedObject::isLink()
1902 {
1903     ::osl::MutexGuard aGuard( m_aMutex );
1904     if ( m_bDisposed )
1905         throw lang::DisposedException(); // TODO
1906 
1907     // Actually this information is clear even in case object is wayting for saveCompleted
1908     // if ( m_bWaitSaveCompleted )
1909     //  throw embed::WrongStateException(
1910     //              ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1911     //              uno::Reference< uno::XInterface >( reinterpret_cast< ::cppu::OWeakObject* >(this) ) );
1912 
1913     return m_bIsLink;
1914 }
1915 
1916 //------------------------------------------------------
getLinkURL()1917 ::rtl::OUString SAL_CALL OCommonEmbeddedObject::getLinkURL()
1918 {
1919     ::osl::MutexGuard aGuard( m_aMutex );
1920     if ( m_bDisposed )
1921         throw lang::DisposedException(); // TODO
1922 
1923     // Actually this information is clear even in case object is wayting for saveCompleted
1924     // if ( m_bWaitSaveCompleted )
1925     //  throw embed::WrongStateException(
1926     //              ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1927     //              uno::Reference< uno::XInterface >( reinterpret_cast< ::cppu::OWeakObject* >(this) ) );
1928 
1929     if ( !m_bIsLink )
1930         throw embed::WrongStateException(
1931                     ::rtl::OUString::createFromAscii( "The object is not a link object!\n" ),
1932                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1933 
1934     return m_aLinkURL;
1935 }
1936