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