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