xref: /AOO41X/main/embeddedobj/source/commonembedding/persistence.cxx (revision bfd08df8d53be340829eb05b5154718deb4e1b3d)
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 sence 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(), "Coudn'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 commited 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(), "Coudn'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         throw ( lang::IllegalArgumentException,
935                 embed::WrongStateException,
936                 io::IOException,
937                 uno::Exception,
938                 uno::RuntimeException )
939 {
940     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::setPersistentEntry" );
941 
942     // the type of the object must be already set
943     // a kind of typedetection should be done in the factory
944 
945     ::osl::MutexGuard aGuard( m_aMutex );
946     if ( m_bDisposed )
947         throw lang::DisposedException(); // TODO
948 
949     if ( !xStorage.is() )
950         throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
951                                             uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
952                                             1 );
953 
954     if ( !sEntName.getLength() )
955         throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
956                                             uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
957                                             2 );
958 
959     // May be LOADED should be forbidden here ???
960     if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
961       && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) )
962     {
963         // if the object is not loaded
964         // it can not get persistant representation without initialization
965 
966         // if the object is loaded
967         // it can switch persistant representation only without initialization
968 
969         throw embed::WrongStateException(
970                     ::rtl::OUString::createFromAscii( "Can't change persistant representation of activated object!\n" ),
971                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
972     }
973 
974     if ( m_bWaitSaveCompleted )
975     {
976         if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
977         {
978             // saveCompleted is expected, handle it accordingly
979             if ( m_xNewParentStorage == xStorage && m_aNewEntryName.equals( sEntName ) )
980             {
981                 saveCompleted( sal_True );
982                 return;
983             }
984 
985             // if a completely different entry is provided, switch first back to the old persistence in saveCompleted
986             // and then switch to the target persistence
987             sal_Bool bSwitchFurther = ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) );
988             saveCompleted( sal_False );
989             if ( !bSwitchFurther )
990                 return;
991         }
992         else
993             throw embed::WrongStateException(
994                         ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
995                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
996     }
997 
998     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
999     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1000     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1001     if ( m_bIsLink )
1002     {
1003         m_aEntryName = sEntName;
1004         return;
1005     }
1006 
1007     uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
1008     if ( !xNameAccess.is() )
1009         throw uno::RuntimeException(); //TODO
1010 
1011     // detect entry existence
1012     sal_Bool bElExists = xNameAccess->hasByName( sEntName );
1013 
1014     m_aDocMediaDescriptor = GetValuableArgs_Impl( lArguments,
1015                                                   nEntryConnectionMode != embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT );
1016 
1017     m_bReadOnly = sal_False;
1018     for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1019         if ( lArguments[nInd].Name.equalsAscii( "ReadOnly" ) )
1020             lArguments[nInd].Value >>= m_bReadOnly;
1021 
1022     // TODO: use lObjArgs for StoreVisualReplacement
1023     for ( sal_Int32 nObjInd = 0; nObjInd < lObjArgs.getLength(); nObjInd++ )
1024         if ( lObjArgs[nObjInd].Name.equalsAscii( "OutplaceDispatchInterceptor" ) )
1025         {
1026             uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor;
1027             if ( lObjArgs[nObjInd].Value >>= xDispatchInterceptor )
1028                 m_pDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor );
1029         }
1030         else if ( lObjArgs[nObjInd].Name.equalsAscii( "DefaultParentBaseURL" ) )
1031         {
1032             lObjArgs[nObjInd].Value >>= m_aDefaultParentBaseURL;
1033         }
1034         else if ( lObjArgs[nObjInd].Name.equalsAscii( "Parent" ) )
1035         {
1036             lObjArgs[nObjInd].Value >>= m_xParent;
1037         }
1038         else if ( lObjArgs[nObjInd].Name.equalsAscii( "IndividualMiscStatus" ) )
1039         {
1040             sal_Int64 nMiscStatus=0;
1041             lObjArgs[nObjInd].Value >>= nMiscStatus;
1042             m_nMiscStatus |= nMiscStatus;
1043         }
1044         else if ( lObjArgs[nObjInd].Name.equalsAscii( "CloneFrom" ) )
1045         {
1046             uno::Reference < embed::XEmbeddedObject > xObj;
1047             lObjArgs[nObjInd].Value >>= xObj;
1048             if ( xObj.is() )
1049             {
1050                 m_bHasClonedSize = sal_True;
1051                 m_aClonedSize = xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1052                 m_nClonedMapUnit = xObj->getMapUnit( embed::Aspects::MSOLE_CONTENT );
1053             }
1054         }
1055         else if ( lObjArgs[nObjInd].Name.equalsAscii( "OutplaceFrameProperties" ) )
1056         {
1057             uno::Sequence< uno::Any > aOutFrameProps;
1058             uno::Sequence< beans::NamedValue > aOutFramePropsTyped;
1059             if ( lObjArgs[nObjInd].Value >>= aOutFrameProps )
1060             {
1061                 m_pDocHolder->SetOutplaceFrameProperties( aOutFrameProps );
1062             }
1063             else if ( lObjArgs[nObjInd].Value >>= aOutFramePropsTyped )
1064             {
1065                 aOutFrameProps.realloc( aOutFramePropsTyped.getLength() );
1066                 uno::Any* pProp = aOutFrameProps.getArray();
1067                 for (   const beans::NamedValue* pTypedProp = aOutFramePropsTyped.getConstArray();
1068                         pTypedProp != aOutFramePropsTyped.getConstArray() + aOutFramePropsTyped.getLength();
1069                         ++pTypedProp, ++pProp
1070                     )
1071                 {
1072                     *pProp <<= *pTypedProp;
1073                 }
1074                 m_pDocHolder->SetOutplaceFrameProperties( aOutFrameProps );
1075             }
1076             else
1077                 OSL_ENSURE( false, "OCommonEmbeddedObject::setPersistentEntry: illegal type for argument 'OutplaceFrameProperties'!" );
1078         }
1079         else if ( lObjArgs[nObjInd].Name.equalsAscii( "ModuleName" ) )
1080         {
1081             lObjArgs[nObjInd].Value >>= m_aModuleName;
1082         }
1083         else if ( lObjArgs[nObjInd].Name.equalsAscii( "EmbeddedScriptSupport" ) )
1084         {
1085             OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_bEmbeddedScriptSupport );
1086         }
1087         else if ( lObjArgs[nObjInd].Name.equalsAscii( "DocumentRecoverySupport" ) )
1088         {
1089             OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_bDocumentRecoverySupport );
1090         }
1091         else if ( lObjArgs[nObjInd].Name.equalsAscii( "RecoveryStorage" ) )
1092         {
1093             OSL_VERIFY( lObjArgs[nObjInd].Value >>= m_xRecoveryStorage );
1094         }
1095 
1096 
1097     sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
1098 
1099     SwitchOwnPersistence( xStorage, sEntName );
1100 
1101     if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT )
1102     {
1103         if ( bElExists )
1104         {
1105             // the initialization from existing storage allows to leave object in loaded state
1106             m_nObjectState = embed::EmbedStates::LOADED;
1107         }
1108         else
1109         {
1110             m_pDocHolder->SetComponent( InitNewDocument_Impl(), m_bReadOnly );
1111             if ( !m_pDocHolder->GetComponent().is() )
1112                 throw io::IOException(); // TODO: can not create document
1113 
1114             m_nObjectState = embed::EmbedStates::RUNNING;
1115         }
1116     }
1117     else
1118     {
1119         if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE )
1120             throw io::IOException();
1121 
1122         if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1123         {
1124             // the document just already changed its storage to store to
1125             // the links to OOo documents for now ignore this call
1126             // TODO: OOo links will have persistence so it will be switched here
1127         }
1128         else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT )
1129         {
1130             if ( m_xRecoveryStorage.is() )
1131                 TransferMediaType( m_xRecoveryStorage, m_xObjectStorage );
1132 
1133             // TODO:
1134             m_pDocHolder->SetComponent( InitNewDocument_Impl(), m_bReadOnly );
1135 
1136             if ( !m_pDocHolder->GetComponent().is() )
1137                 throw io::IOException(); // TODO: can not create document
1138 
1139             m_nObjectState = embed::EmbedStates::RUNNING;
1140         }
1141         else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT )
1142         {
1143             m_pDocHolder->SetComponent( CreateDocFromMediaDescr_Impl( lArguments ), m_bReadOnly );
1144             m_nObjectState = embed::EmbedStates::RUNNING;
1145         }
1146         //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1147         //{
1148             //TODO:
1149         //}
1150         else
1151             throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong connection mode is provided!\n" ),
1152                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1153                                         3 );
1154     }
1155 }
1156 
1157 //------------------------------------------------------
storeToEntry(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName,const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1158 void SAL_CALL OCommonEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage,
1159                             const ::rtl::OUString& sEntName,
1160                             const uno::Sequence< beans::PropertyValue >& lArguments,
1161                             const uno::Sequence< beans::PropertyValue >& lObjArgs )
1162         throw ( lang::IllegalArgumentException,
1163                 embed::WrongStateException,
1164                 io::IOException,
1165                 uno::Exception,
1166                 uno::RuntimeException )
1167 {
1168     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::storeToEntry" );
1169 
1170     ::osl::ResettableMutexGuard aGuard( m_aMutex );
1171     if ( m_bDisposed )
1172         throw lang::DisposedException(); // TODO
1173 
1174     if ( m_nObjectState == -1 )
1175     {
1176         // the object is still not loaded
1177         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1178                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1179     }
1180 
1181     if ( m_bWaitSaveCompleted )
1182         throw embed::WrongStateException(
1183                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1184                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1185 
1186     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1187     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1188     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1189     if ( m_bIsLink )
1190         return;
1191 
1192     OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" );
1193 
1194     sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1195     sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1196     try {
1197         nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage );
1198     }
1199     catch ( beans::IllegalTypeException& )
1200     {
1201         // the container just has an unknown type, use current file format
1202     }
1203     catch ( uno::Exception& )
1204     {
1205         OSL_ENSURE( sal_False, "Can not retrieve target storage media type!\n" );
1206     }
1207 
1208     try
1209     {
1210         nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
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 own storage media type!\n" );
1219     }
1220 
1221     sal_Bool bTryOptimization = sal_False;
1222     for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1223     {
1224         // StoreVisualReplacement and VisualReplacement args have no sence here
1225         if ( lObjArgs[nInd].Name.equalsAscii( "CanTryOptimization" ) )
1226             lObjArgs[nInd].Value >>= bTryOptimization;
1227     }
1228 
1229     sal_Bool bSwitchBackToLoaded = sal_False;
1230 
1231     // Storing to different format can be done only in running state.
1232     if ( m_nObjectState == embed::EmbedStates::LOADED )
1233     {
1234         // TODO/LATER: copying is not legal for documents with relative links.
1235         if ( nTargetStorageFormat == nOriginalStorageFormat )
1236         {
1237             sal_Bool bOptimizationWorks = sal_False;
1238             if ( bTryOptimization )
1239             {
1240                 try
1241                 {
1242                     // try to use optimized copying
1243                     uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW );
1244                     uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW );
1245                     xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName );
1246                     bOptimizationWorks = sal_True;
1247                 }
1248                 catch( uno::Exception& )
1249                 {
1250                 }
1251             }
1252 
1253             if ( !bOptimizationWorks )
1254                 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
1255         }
1256         else
1257         {
1258             changeState( embed::EmbedStates::RUNNING );
1259             bSwitchBackToLoaded = sal_True;
1260         }
1261     }
1262 
1263     if ( m_nObjectState != embed::EmbedStates::LOADED )
1264     {
1265         uno::Reference< embed::XStorage > xSubStorage =
1266                     xStorage->openStorageElement( sEntName, embed::ElementModes::READWRITE );
1267 
1268         if ( !xSubStorage.is() )
1269             throw uno::RuntimeException(); //TODO
1270 
1271         aGuard.clear();
1272         // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1273         StoreDocToStorage_Impl( xSubStorage, nTargetStorageFormat, GetBaseURLFrom_Impl( lArguments, lObjArgs ), sEntName, sal_False );
1274         aGuard.reset();
1275 
1276         if ( bSwitchBackToLoaded )
1277             changeState( embed::EmbedStates::LOADED );
1278     }
1279 
1280     // TODO: should the listener notification be done?
1281 }
1282 
1283 //------------------------------------------------------
storeAsEntry(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName,const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1284 void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage,
1285                             const ::rtl::OUString& sEntName,
1286                             const uno::Sequence< beans::PropertyValue >& lArguments,
1287                             const uno::Sequence< beans::PropertyValue >& lObjArgs )
1288         throw ( lang::IllegalArgumentException,
1289                 embed::WrongStateException,
1290                 io::IOException,
1291                 uno::Exception,
1292                 uno::RuntimeException )
1293 {
1294     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::storeAsEntry" );
1295 
1296     // TODO: use lObjArgs
1297 
1298     ::osl::ResettableMutexGuard aGuard( m_aMutex );
1299     if ( m_bDisposed )
1300         throw lang::DisposedException(); // TODO
1301 
1302     if ( m_nObjectState == -1 )
1303     {
1304         // the object is still not loaded
1305         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1306                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1307     }
1308 
1309     if ( m_bWaitSaveCompleted )
1310         throw embed::WrongStateException(
1311                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1312                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1313 
1314     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1315     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1316     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1317     if ( m_bIsLink )
1318     {
1319         m_aNewEntryName = sEntName;
1320         return;
1321     }
1322 
1323     OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" );
1324 
1325     sal_Int32 nTargetStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1326     sal_Int32 nOriginalStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1327     try {
1328         nTargetStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( xStorage );
1329     }
1330     catch ( beans::IllegalTypeException& )
1331     {
1332         // the container just has an unknown type, use current file format
1333     }
1334     catch ( uno::Exception& )
1335     {
1336         OSL_ENSURE( sal_False, "Can not retrieve target storage media type!\n" );
1337     }
1338 
1339     try
1340     {
1341         nOriginalStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
1342     }
1343     catch ( beans::IllegalTypeException& )
1344     {
1345         // the container just has an unknown type, use current file format
1346     }
1347     catch ( uno::Exception& )
1348     {
1349         OSL_ENSURE( sal_False, "Can not retrieve own storage media type!\n" );
1350     }
1351 
1352     PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSaveAs" ) );
1353 
1354     sal_Bool bTryOptimization = sal_False;
1355     for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1356     {
1357         // StoreVisualReplacement and VisualReplacement args have no sence here
1358         if ( lObjArgs[nInd].Name.equalsAscii( "CanTryOptimization" ) )
1359             lObjArgs[nInd].Value >>= bTryOptimization;
1360     }
1361 
1362     sal_Bool bSwitchBackToLoaded = sal_False;
1363 
1364     // Storing to different format can be done only in running state.
1365     if ( m_nObjectState == embed::EmbedStates::LOADED )
1366     {
1367         // TODO/LATER: copying is not legal for documents with relative links.
1368         if ( nTargetStorageFormat == nOriginalStorageFormat )
1369         {
1370             sal_Bool bOptimizationWorks = sal_False;
1371             if ( bTryOptimization )
1372             {
1373                 try
1374                 {
1375                     // try to use optimized copying
1376                     uno::Reference< embed::XOptimizedStorage > xSource( m_xParentStorage, uno::UNO_QUERY_THROW );
1377                     uno::Reference< embed::XOptimizedStorage > xTarget( xStorage, uno::UNO_QUERY_THROW );
1378                     xSource->copyElementDirectlyTo( m_aEntryName, xTarget, sEntName );
1379                     bOptimizationWorks = sal_True;
1380                 }
1381                 catch( uno::Exception& )
1382                 {
1383                 }
1384             }
1385 
1386             if ( !bOptimizationWorks )
1387                 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
1388         }
1389         else
1390         {
1391             changeState( embed::EmbedStates::RUNNING );
1392             bSwitchBackToLoaded = sal_True;
1393         }
1394     }
1395 
1396     uno::Reference< embed::XStorage > xSubStorage =
1397                 xStorage->openStorageElement( sEntName, embed::ElementModes::READWRITE );
1398 
1399     if ( !xSubStorage.is() )
1400         throw uno::RuntimeException(); //TODO
1401 
1402     if ( m_nObjectState != embed::EmbedStates::LOADED )
1403     {
1404         aGuard.clear();
1405         // TODO/LATER: support hierarchical name for embedded objects in embedded objects
1406         StoreDocToStorage_Impl( xSubStorage, nTargetStorageFormat, GetBaseURLFrom_Impl( lArguments, lObjArgs ), sEntName, sal_False );
1407         aGuard.reset();
1408 
1409         if ( bSwitchBackToLoaded )
1410             changeState( embed::EmbedStates::LOADED );
1411     }
1412 
1413     m_bWaitSaveCompleted = sal_True;
1414     m_xNewObjectStorage = xSubStorage;
1415     m_xNewParentStorage = xStorage;
1416     m_aNewEntryName = sEntName;
1417     m_aNewDocMediaDescriptor = GetValuableArgs_Impl( lArguments, sal_True );
1418 
1419     // TODO: register listeners for storages above, in case thay are disposed
1420     //       an exception will be thrown on saveCompleted( true )
1421 
1422     // TODO: should the listener notification be done here or in saveCompleted?
1423 }
1424 
1425 //------------------------------------------------------
saveCompleted(sal_Bool bUseNew)1426 void SAL_CALL OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew )
1427         throw ( embed::WrongStateException,
1428                 uno::Exception,
1429                 uno::RuntimeException )
1430 {
1431     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::saveCompleted" );
1432 
1433     ::osl::MutexGuard aGuard( m_aMutex );
1434     if ( m_bDisposed )
1435         throw lang::DisposedException(); // TODO
1436 
1437     if ( m_nObjectState == -1 )
1438     {
1439         // the object is still not loaded
1440         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1441                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1442     }
1443 
1444     // for now support of this interface is required to allow breaking of links and converting them to normal embedded
1445     // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used )
1446     // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!\n" );
1447     if ( m_bIsLink )
1448     {
1449         if ( bUseNew )
1450             m_aEntryName = m_aNewEntryName;
1451         m_aNewEntryName = ::rtl::OUString();
1452         return;
1453     }
1454 
1455     // it is allowed to call saveCompleted( false ) for nonstored objects
1456     if ( !m_bWaitSaveCompleted && !bUseNew )
1457         return;
1458 
1459     OSL_ENSURE( m_bWaitSaveCompleted, "Unexpected saveCompleted() call!\n" );
1460     if ( !m_bWaitSaveCompleted )
1461         throw io::IOException(); // TODO: illegal call
1462 
1463     OSL_ENSURE( m_xNewObjectStorage.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" );
1464     if ( !m_xNewObjectStorage.is() || !m_xNewParentStorage.is() )
1465         throw uno::RuntimeException(); // TODO: broken internal information
1466 
1467     if ( bUseNew )
1468     {
1469         SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStorage, m_aNewEntryName );
1470         m_aDocMediaDescriptor = m_aNewDocMediaDescriptor;
1471 
1472         uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
1473         if ( xModif.is() )
1474             xModif->setModified( sal_False );
1475 
1476         PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSaveAsDone" ) );
1477     }
1478     else
1479     {
1480         try {
1481             uno::Reference< lang::XComponent > xComponent( m_xNewObjectStorage, uno::UNO_QUERY );
1482             OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" );
1483             if ( xComponent.is() )
1484                 xComponent->dispose();
1485         }
1486         catch ( uno::Exception& )
1487         {
1488         }
1489     }
1490 
1491     m_xNewObjectStorage = uno::Reference< embed::XStorage >();
1492     m_xNewParentStorage = uno::Reference< embed::XStorage >();
1493     m_aNewEntryName = ::rtl::OUString();
1494     m_aNewDocMediaDescriptor.realloc( 0 );
1495     m_bWaitSaveCompleted = sal_False;
1496 
1497     if ( bUseNew )
1498     {
1499         // TODO: notify listeners
1500 
1501         if ( m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE )
1502         {
1503             // TODO: update visual representation
1504         }
1505     }
1506 }
1507 
1508 //------------------------------------------------------
hasEntry()1509 sal_Bool SAL_CALL OCommonEmbeddedObject::hasEntry()
1510         throw ( embed::WrongStateException,
1511                 uno::RuntimeException )
1512 {
1513     ::osl::MutexGuard aGuard( m_aMutex );
1514     if ( m_bDisposed )
1515         throw lang::DisposedException(); // TODO
1516 
1517     if ( m_bWaitSaveCompleted )
1518         throw embed::WrongStateException(
1519                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1520                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1521 
1522     if ( m_xObjectStorage.is() )
1523         return sal_True;
1524 
1525     return sal_False;
1526 }
1527 
1528 //------------------------------------------------------
getEntryName()1529 ::rtl::OUString SAL_CALL OCommonEmbeddedObject::getEntryName()
1530         throw ( embed::WrongStateException,
1531                 uno::RuntimeException )
1532 {
1533     ::osl::MutexGuard aGuard( m_aMutex );
1534     if ( m_bDisposed )
1535         throw lang::DisposedException(); // TODO
1536 
1537     if ( m_nObjectState == -1 )
1538     {
1539         // the object is still not loaded
1540         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ),
1541                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1542     }
1543 
1544     if ( m_bWaitSaveCompleted )
1545         throw embed::WrongStateException(
1546                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1547                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1548 
1549     return m_aEntryName;
1550 }
1551 
1552 //------------------------------------------------------
storeOwn()1553 void SAL_CALL OCommonEmbeddedObject::storeOwn()
1554         throw ( embed::WrongStateException,
1555                 io::IOException,
1556                 uno::Exception,
1557                 uno::RuntimeException )
1558 {
1559     RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OCommonEmbeddedObject::storeOwn" );
1560 
1561     // during switching from Activated to Running and from Running to Loaded states the object will
1562     // ask container to store the object, the container has to make decision
1563     // to do so or not
1564 
1565     ::osl::ResettableMutexGuard aGuard( m_aMutex );
1566     if ( m_bDisposed )
1567         throw lang::DisposedException(); // TODO
1568 
1569     if ( m_nObjectState == -1 )
1570     {
1571         // the object is still not loaded
1572         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1573                                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1574     }
1575 
1576     if ( m_bWaitSaveCompleted )
1577         throw embed::WrongStateException(
1578                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1579                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1580 
1581     if ( m_bReadOnly )
1582         throw io::IOException(); // TODO: access denied
1583 
1584     // nothing to do, if the object is in loaded state
1585     if ( m_nObjectState == embed::EmbedStates::LOADED )
1586         return;
1587 
1588     PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSave" ) );
1589 
1590     OSL_ENSURE( m_pDocHolder->GetComponent().is(), "If an object is activated or in running state it must have a document!\n" );
1591     if ( !m_pDocHolder->GetComponent().is() )
1592         throw uno::RuntimeException();
1593 
1594     if ( m_bIsLink )
1595     {
1596         // TODO: just store the document to it's location
1597         uno::Reference< frame::XStorable > xStorable( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
1598         if ( !xStorable.is() )
1599             throw uno::RuntimeException(); // TODO
1600 
1601         // free the main mutex for the storing time
1602         aGuard.clear();
1603 
1604         xStorable->store();
1605 
1606         aGuard.reset();
1607     }
1608     else
1609     {
1610         OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!\n" );
1611 
1612         if ( !m_xObjectStorage.is() )
1613             throw io::IOException(); //TODO: access denied
1614 
1615         sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
1616         try {
1617             nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
1618         }
1619         catch ( beans::IllegalTypeException& )
1620         {
1621             // the container just has an unknown type, use current file format
1622         }
1623         catch ( uno::Exception& )
1624         {
1625             OSL_ENSURE( sal_False, "Can not retrieve storage media type!\n" );
1626         }
1627 
1628         aGuard.clear();
1629         StoreDocToStorage_Impl( m_xObjectStorage, nStorageFormat, GetBaseURL_Impl(), m_aEntryName, sal_True );
1630         aGuard.reset();
1631     }
1632 
1633     uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
1634     if ( xModif.is() )
1635         xModif->setModified( sal_False );
1636 
1637     PostEvent_Impl( ::rtl::OUString::createFromAscii( "OnSaveDone" ) );
1638 }
1639 
1640 //------------------------------------------------------
isReadonly()1641 sal_Bool SAL_CALL OCommonEmbeddedObject::isReadonly()
1642         throw ( embed::WrongStateException,
1643                 uno::RuntimeException )
1644 {
1645     ::osl::MutexGuard aGuard( m_aMutex );
1646     if ( m_bDisposed )
1647         throw lang::DisposedException(); // TODO
1648 
1649     if ( m_nObjectState == -1 )
1650     {
1651         // the object is still not loaded
1652         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ),
1653                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1654     }
1655 
1656     if ( m_bWaitSaveCompleted )
1657         throw embed::WrongStateException(
1658                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1659                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1660 
1661     return m_bReadOnly;
1662 }
1663 
1664 //------------------------------------------------------
reload(const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1665 void SAL_CALL OCommonEmbeddedObject::reload(
1666                 const uno::Sequence< beans::PropertyValue >& lArguments,
1667                 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1668         throw ( lang::IllegalArgumentException,
1669                 embed::WrongStateException,
1670                 io::IOException,
1671                 uno::Exception,
1672                 uno::RuntimeException )
1673 {
1674     // TODO: use lObjArgs
1675     // for now this method is used only to switch readonly state
1676 
1677     ::osl::MutexGuard aGuard( m_aMutex );
1678     if ( m_bDisposed )
1679         throw lang::DisposedException(); // TODO
1680 
1681     if ( m_nObjectState == -1 )
1682     {
1683         // the object is still not loaded
1684         throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ),
1685                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1686     }
1687 
1688     if ( m_nObjectState != embed::EmbedStates::LOADED )
1689     {
1690         // the object is still not loaded
1691         throw embed::WrongStateException(
1692                                 ::rtl::OUString::createFromAscii( "The object must be in loaded state to be reloaded!\n" ),
1693                                 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1694     }
1695 
1696     if ( m_bWaitSaveCompleted )
1697         throw embed::WrongStateException(
1698                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1699                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1700 
1701     if ( m_bIsLink )
1702     {
1703         // reload of the link
1704         ::rtl::OUString aOldLinkFilter = m_aLinkFilterName;
1705 
1706         ::rtl::OUString aNewLinkFilter;
1707         for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1708         {
1709             if ( lArguments[nInd].Name.equalsAscii( "URL" ) )
1710             {
1711                 // the new URL
1712                 lArguments[nInd].Value >>= m_aLinkURL;
1713                 m_aLinkFilterName = ::rtl::OUString();
1714             }
1715             else if ( lArguments[nInd].Name.equalsAscii( "FilterName" ) )
1716             {
1717                 lArguments[nInd].Value >>= aNewLinkFilter;
1718                 m_aLinkFilterName = ::rtl::OUString();
1719             }
1720         }
1721 
1722         ::comphelper::MimeConfigurationHelper aHelper( m_xFactory );
1723         if ( !m_aLinkFilterName.getLength() )
1724         {
1725             if ( aNewLinkFilter.getLength() )
1726                 m_aLinkFilterName = aNewLinkFilter;
1727             else
1728             {
1729                 uno::Sequence< beans::PropertyValue > aArgs( 1 );
1730                 aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
1731                 aArgs[0].Value <<= m_aLinkURL;
1732                 m_aLinkFilterName = aHelper.UpdateMediaDescriptorWithFilterName( aArgs, sal_False );
1733             }
1734         }
1735 
1736         if ( !aOldLinkFilter.equals( m_aLinkFilterName ) )
1737         {
1738             uno::Sequence< beans::NamedValue > aObject = aHelper.GetObjectPropsByFilter( m_aLinkFilterName );
1739 
1740             // TODO/LATER: probably the document holder could be cleaned explicitly as in the destructor
1741             m_pDocHolder->release();
1742             m_pDocHolder = NULL;
1743 
1744             LinkInit_Impl( aObject, lArguments, lObjArgs );
1745         }
1746     }
1747 
1748     m_aDocMediaDescriptor = GetValuableArgs_Impl( lArguments, sal_True );
1749 
1750     // TODO: use lObjArgs for StoreVisualReplacement
1751     for ( sal_Int32 nObjInd = 0; nObjInd < lObjArgs.getLength(); nObjInd++ )
1752         if ( lObjArgs[nObjInd].Name.equalsAscii( "OutplaceDispatchInterceptor" ) )
1753         {
1754             uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor;
1755             if ( lObjArgs[nObjInd].Value >>= xDispatchInterceptor )
1756                 m_pDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor );
1757 
1758             break;
1759         }
1760 
1761     // TODO:
1762     // when document allows reloading through API the object can be reloaded not only in loaded state
1763 
1764     sal_Bool bOldReadOnlyValue = m_bReadOnly;
1765 
1766     m_bReadOnly = sal_False;
1767     for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1768         if ( lArguments[nInd].Name.equalsAscii( "ReadOnly" ) )
1769             lArguments[nInd].Value >>= m_bReadOnly;
1770 
1771     if ( bOldReadOnlyValue != m_bReadOnly && !m_bIsLink )
1772     {
1773         // close own storage
1774         try {
1775             uno::Reference< lang::XComponent > xComponent( m_xObjectStorage, uno::UNO_QUERY );
1776             OSL_ENSURE( !m_xObjectStorage.is() || xComponent.is(), "Wrong storage implementation!" );
1777             if ( xComponent.is() )
1778                 xComponent->dispose();
1779         }
1780         catch ( uno::Exception& )
1781         {
1782         }
1783 
1784         sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
1785         m_xObjectStorage = m_xParentStorage->openStorageElement( m_aEntryName, nStorageMode );
1786     }
1787 }
1788 
1789 //------------------------------------------------------
breakLink(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName)1790 void SAL_CALL OCommonEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage,
1791                                                 const ::rtl::OUString& sEntName )
1792         throw ( lang::IllegalArgumentException,
1793                 embed::WrongStateException,
1794                 io::IOException,
1795                 uno::Exception,
1796                 uno::RuntimeException )
1797 {
1798     ::osl::ResettableMutexGuard aGuard( m_aMutex );
1799     if ( m_bDisposed )
1800         throw lang::DisposedException(); // TODO
1801 
1802     if ( !m_bIsLink )
1803     {
1804         // it must be a linked initialized object
1805         throw embed::WrongStateException(
1806                     ::rtl::OUString::createFromAscii( "The object is not a valid linked object!\n" ),
1807                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1808     }
1809 #if 0
1810     else
1811     {
1812         // the current implementation of OOo links does not implement this method since it does not implement
1813         // all the set of interfaces required for OOo embedded object ( XEmbedPersist is not supported ).
1814         throw io::IOException(); // TODO:
1815     }
1816 #endif
1817 
1818     if ( !xStorage.is() )
1819         throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
1820                                             uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1821                                             1 );
1822 
1823     if ( !sEntName.getLength() )
1824         throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
1825                                             uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1826                                             2 );
1827 
1828     if ( !m_bIsLink || m_nObjectState == -1 )
1829     {
1830         // it must be a linked initialized object
1831         throw embed::WrongStateException(
1832                     ::rtl::OUString::createFromAscii( "The object is not a valid linked object!\n" ),
1833                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1834     }
1835 
1836     if ( m_bWaitSaveCompleted )
1837         throw embed::WrongStateException(
1838                     ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1839                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1840 
1841     uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
1842     if ( !xNameAccess.is() )
1843         throw uno::RuntimeException(); //TODO
1844 
1845     // detect entry existence
1846     /*sal_Bool bElExists =*/ xNameAccess->hasByName( sEntName );
1847 
1848     m_bReadOnly = sal_False;
1849 //  sal_Int32 nStorageMode = embed::ElementModes::READWRITE;
1850 
1851     if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) )
1852         SwitchOwnPersistence( xStorage, sEntName );
1853 
1854     // for linked object it means that it becomes embedded object
1855     // the document must switch it's persistence also
1856 
1857     // TODO/LATER: handle the case when temp doc can not be created
1858     // the document is a new embedded object so it must be marked as modified
1859     uno::Reference< util::XCloseable > xDocument = CreateTempDocFromLink_Impl();
1860     uno::Reference< util::XModifiable > xModif( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
1861     if ( !xModif.is() )
1862         throw uno::RuntimeException();
1863     try
1864     {
1865         xModif->setModified( sal_True );
1866     }
1867     catch( uno::Exception& )
1868     {}
1869 
1870     m_pDocHolder->SetComponent( xDocument, m_bReadOnly );
1871     OSL_ENSURE( m_pDocHolder->GetComponent().is(), "If document cant be created, an exception must be thrown!\n" );
1872 
1873     if ( m_nObjectState == embed::EmbedStates::LOADED )
1874     {
1875         // the state is changed and can not be switched to loaded state back without saving
1876         m_nObjectState = embed::EmbedStates::RUNNING;
1877         StateChangeNotification_Impl( sal_False, embed::EmbedStates::LOADED, m_nObjectState, aGuard );
1878     }
1879     else if ( m_nObjectState == embed::EmbedStates::ACTIVE )
1880         m_pDocHolder->Show();
1881 
1882     m_bIsLink = sal_False;
1883     m_aLinkFilterName = ::rtl::OUString();
1884     m_aLinkURL = ::rtl::OUString();
1885 }
1886 
1887 //------------------------------------------------------
isLink()1888 sal_Bool SAL_CALL  OCommonEmbeddedObject::isLink()
1889         throw ( embed::WrongStateException,
1890                 uno::RuntimeException )
1891 {
1892     ::osl::MutexGuard aGuard( m_aMutex );
1893     if ( m_bDisposed )
1894         throw lang::DisposedException(); // TODO
1895 
1896     // Actually this information is clear even in case object is wayting for saveCompleted
1897     // if ( m_bWaitSaveCompleted )
1898     //  throw embed::WrongStateException(
1899     //              ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1900     //              uno::Reference< uno::XInterface >( reinterpret_cast< ::cppu::OWeakObject* >(this) ) );
1901 
1902     return m_bIsLink;
1903 }
1904 
1905 //------------------------------------------------------
getLinkURL()1906 ::rtl::OUString SAL_CALL OCommonEmbeddedObject::getLinkURL()
1907         throw ( embed::WrongStateException,
1908                 uno::Exception,
1909                 uno::RuntimeException )
1910 {
1911     ::osl::MutexGuard aGuard( m_aMutex );
1912     if ( m_bDisposed )
1913         throw lang::DisposedException(); // TODO
1914 
1915     // Actually this information is clear even in case object is wayting for saveCompleted
1916     // if ( m_bWaitSaveCompleted )
1917     //  throw embed::WrongStateException(
1918     //              ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1919     //              uno::Reference< uno::XInterface >( reinterpret_cast< ::cppu::OWeakObject* >(this) ) );
1920 
1921     if ( !m_bIsLink )
1922         throw embed::WrongStateException(
1923                     ::rtl::OUString::createFromAscii( "The object is not a link object!\n" ),
1924                     uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1925 
1926     return m_aLinkURL;
1927 }
1928 
1929