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