1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_embeddedobj.hxx"
26
27 #include <commonembobj.hxx>
28 #include <com/sun/star/embed/Aspects.hpp>
29 #include <com/sun/star/document/XStorageBasedDocument.hpp>
30 #include <com/sun/star/embed/EmbedStates.hpp>
31 #include <com/sun/star/embed/EmbedVerbs.hpp>
32 #include <com/sun/star/embed/EntryInitModes.hpp>
33 #include <com/sun/star/embed/XStorage.hpp>
34 #include <com/sun/star/embed/XOptimizedStorage.hpp>
35 #include <com/sun/star/embed/ElementModes.hpp>
36 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/frame/XStorable.hpp>
39 #include <com/sun/star/frame/XLoadable.hpp>
40 #include <com/sun/star/frame/XComponentLoader.hpp>
41 #include <com/sun/star/frame/XModule.hpp>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
44 #include <com/sun/star/lang/DisposedException.hpp>
45 #include <com/sun/star/util/XModifiable.hpp>
46
47 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCEESS_HPP_
48 #include <com/sun/star/container/XNameAccess.hpp>
49 #endif
50 #include <com/sun/star/container/XChild.hpp>
51 #include <com/sun/star/util/XCloseable.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/beans/IllegalTypeException.hpp>
54 #include <com/sun/star/chart2/XChartDocument.hpp>
55
56 #include <comphelper/fileformat.h>
57 #include <comphelper/storagehelper.hxx>
58 #include <comphelper/mimeconfighelper.hxx>
59 #include <comphelper/namedvaluecollection.hxx>
60
61 #include <rtl/logfile.hxx>
62
63 #include <tools/diagnose_ex.h>
64
65 #define USE_STORAGEBASED_DOCUMENT
66
67 using namespace ::com::sun::star;
68
69
70 //------------------------------------------------------
GetValuableArgs_Impl(const uno::Sequence<beans::PropertyValue> & aMedDescr,sal_Bool bCanUseDocumentBaseURL)71 uno::Sequence< beans::PropertyValue > GetValuableArgs_Impl( const uno::Sequence< beans::PropertyValue >& aMedDescr,
72 sal_Bool bCanUseDocumentBaseURL )
73 {
74 uno::Sequence< beans::PropertyValue > aResult;
75 sal_Int32 nResLen = 0;
76
77 for ( sal_Int32 nInd = 0; nInd < aMedDescr.getLength(); nInd++ )
78 {
79 if ( aMedDescr[nInd].Name.equalsAscii( "ComponentData" )
80 || aMedDescr[nInd].Name.equalsAscii( "DocumentTitle" )
81 || aMedDescr[nInd].Name.equalsAscii( "InteractionHandler" )
82 || aMedDescr[nInd].Name.equalsAscii( "JumpMark" )
83 // || aMedDescr[nInd].Name.equalsAscii( "Password" ) makes no sense for embedded objects
84 || aMedDescr[nInd].Name.equalsAscii( "Preview" )
85 || aMedDescr[nInd].Name.equalsAscii( "ReadOnly" )
86 || aMedDescr[nInd].Name.equalsAscii( "StartPresentation" )
87 || aMedDescr[nInd].Name.equalsAscii( "RepairPackage" )
88 || aMedDescr[nInd].Name.equalsAscii( "StatusIndicator" )
89 || aMedDescr[nInd].Name.equalsAscii( "ViewData" )
90 || aMedDescr[nInd].Name.equalsAscii( "ViewId" )
91 || aMedDescr[nInd].Name.equalsAscii( "MacroExecutionMode" )
92 || aMedDescr[nInd].Name.equalsAscii( "UpdateDocMode" )
93 || (aMedDescr[nInd].Name.equalsAscii( "DocumentBaseURL" ) && bCanUseDocumentBaseURL) )
94 {
95 aResult.realloc( ++nResLen );
96 aResult[nResLen-1] = aMedDescr[nInd];
97 }
98 }
99
100 return aResult;
101 }
102
103 //------------------------------------------------------
addAsTemplate(const uno::Sequence<beans::PropertyValue> & aOrig)104 uno::Sequence< beans::PropertyValue > addAsTemplate( const uno::Sequence< beans::PropertyValue >& aOrig )
105 {
106 sal_Bool bAsTemplateSet = sal_False;
107 sal_Int32 nLength = aOrig.getLength();
108 uno::Sequence< beans::PropertyValue > aResult( nLength );
109
110 for ( sal_Int32 nInd = 0; nInd < nLength; nInd++ )
111 {
112 aResult[nInd].Name = aOrig[nInd].Name;
113 if ( aResult[nInd].Name.equalsAscii( "AsTemplate" ) )
114 {
115 aResult[nInd].Value <<= sal_True;
116 bAsTemplateSet = sal_True;
117 }
118 else
119 aResult[nInd].Value = aOrig[nInd].Value;
120 }
121
122 if ( !bAsTemplateSet )
123 {
124 aResult.realloc( nLength + 1 );
125 aResult[nLength].Name = ::rtl::OUString::createFromAscii( "AsTemplate" );
126 aResult[nLength].Value <<= sal_True;
127 }
128
129 return aResult;
130 }
131
132 //------------------------------------------------------
createTempInpStreamFromStor(const uno::Reference<embed::XStorage> & xStorage,const uno::Reference<lang::XMultiServiceFactory> & xFactory)133 uno::Reference< io::XInputStream > createTempInpStreamFromStor(
134 const uno::Reference< embed::XStorage >& xStorage,
135 const uno::Reference< lang::XMultiServiceFactory >& xFactory )
136 {
137 OSL_ENSURE( xStorage.is(), "The storage can not be empty!" );
138
139 uno::Reference< io::XInputStream > xResult;
140
141 const ::rtl::OUString aServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
142 uno::Reference < io::XStream > xTempStream = uno::Reference < io::XStream > (
143 xFactory->createInstance ( aServiceName ),
144 uno::UNO_QUERY );
145 if ( xTempStream.is() )
146 {
147 uno::Reference < lang::XSingleServiceFactory > xStorageFactory(
148 xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.embed.StorageFactory" ) ),
149 uno::UNO_QUERY );
150
151 uno::Sequence< uno::Any > aArgs( 2 );
152 aArgs[0] <<= xTempStream;
153 aArgs[1] <<= embed::ElementModes::READWRITE;
154 uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArgs ),
155 uno::UNO_QUERY );
156 if ( !xTempStorage.is() )
157 throw uno::RuntimeException(); // TODO:
158
159 try
160 {
161 xStorage->copyToStorage( xTempStorage );
162 } catch( uno::Exception& e )
163 {
164 throw embed::StorageWrappedTargetException(
165 ::rtl::OUString::createFromAscii( "Can't copy storage!" ),
166 uno::Reference< uno::XInterface >(),
167 uno::makeAny( e ) );
168 }
169
170 try {
171 uno::Reference< lang::XComponent > xComponent( xTempStorage, uno::UNO_QUERY );
172 OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" );
173 if ( xComponent.is() )
174 xComponent->dispose();
175 }
176 catch ( uno::Exception& )
177 {
178 }
179
180 try {
181 uno::Reference< io::XOutputStream > xTempOut = xTempStream->getOutputStream();
182 if ( xTempOut.is() )
183 xTempOut->closeOutput();
184 }
185 catch ( uno::Exception& )
186 {
187 }
188
189 xResult = xTempStream->getInputStream();
190 }
191
192 return xResult;
193
194 }
195
196 //------------------------------------------------------
TransferMediaType(const uno::Reference<embed::XStorage> & i_rSource,const uno::Reference<embed::XStorage> & i_rTarget)197 static void TransferMediaType( const uno::Reference< embed::XStorage >& i_rSource, const uno::Reference< embed::XStorage >& i_rTarget )
198 {
199 try
200 {
201 const uno::Reference< beans::XPropertySet > xSourceProps( i_rSource, uno::UNO_QUERY_THROW );
202 const uno::Reference< beans::XPropertySet > xTargetProps( i_rTarget, uno::UNO_QUERY_THROW );
203 const ::rtl::OUString sMediaTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
204 xTargetProps->setPropertyValue( sMediaTypePropName, xSourceProps->getPropertyValue( sMediaTypePropName ) );
205 }
206 catch( const uno::Exception& )
207 {
208 DBG_UNHANDLED_EXCEPTION();
209 }
210 }
211
212 //------------------------------------------------------
CreateDocument(const uno::Reference<lang::XMultiServiceFactory> & _rxFactory,const::rtl::OUString & _rDocumentServiceName,bool _bEmbeddedScriptSupport,const bool i_bDocumentRecoverySupport)213 static uno::Reference< util::XCloseable > CreateDocument( const uno::Reference< lang::XMultiServiceFactory >& _rxFactory,
214 const ::rtl::OUString& _rDocumentServiceName, bool _bEmbeddedScriptSupport, const bool i_bDocumentRecoverySupport )
215 {
216 ::comphelper::NamedValueCollection aArguments;
217 aArguments.put( "EmbeddedObject", (sal_Bool)sal_True );
218 aArguments.put( "EmbeddedScriptSupport", (sal_Bool)_bEmbeddedScriptSupport );
219 aArguments.put( "DocumentRecoverySupport", (sal_Bool)i_bDocumentRecoverySupport );
220
221 uno::Reference< uno::XInterface > xDocument;
222 try
223 {
224 xDocument = _rxFactory->createInstanceWithArguments( _rDocumentServiceName, aArguments.getWrappedPropertyValues() );
225 }
226 catch( const uno::Exception& )
227 {
228 // if an embedded object implementation does not support XInitialization,
229 // the default factory from cppuhelper will throw an
230 // IllegalArgumentException when we try to create the instance with arguments.
231 // Okay, so we fall back to creating the instance without any arguments.
232 OSL_ASSERT("Consider implementing interface XInitialization to avoid duplicate construction");
233 xDocument = _rxFactory->createInstance( _rDocumentServiceName );
234 }
235
236 return uno::Reference< util::XCloseable >( xDocument, uno::UNO_QUERY );
237 }
238
239 //------------------------------------------------------
SetDocToEmbedded(const uno::Reference<frame::XModel> xDocument,const::rtl::OUString & aModuleName)240 static void SetDocToEmbedded( const uno::Reference< frame::XModel > xDocument, const ::rtl::OUString& aModuleName )
241 {
242 if ( xDocument.is() )
243 {
244 uno::Sequence< beans::PropertyValue > aSeq( 1 );
245 aSeq[0].Name = ::rtl::OUString::createFromAscii( "SetEmbedded" );
246 aSeq[0].Value <<= sal_True;
247 xDocument->attachResource( ::rtl::OUString(), aSeq );
248
249 if ( aModuleName.getLength() )
250 {
251 try
252 {
253 uno::Reference< frame::XModule > xModule( xDocument, uno::UNO_QUERY_THROW );
254 xModule->setIdentifier( aModuleName );
255 }
256 catch( uno::Exception& )
257 {}
258 }
259 }
260 }
261
262 //------------------------------------------------------
SwitchOwnPersistence(const uno::Reference<embed::XStorage> & xNewParentStorage,const uno::Reference<embed::XStorage> & xNewObjectStorage,const::rtl::OUString & aNewName)263 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
264 const uno::Reference< embed::XStorage >& xNewObjectStorage,
265 const ::rtl::OUString& aNewName )
266 {
267 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
268 {
269 OSL_ENSURE( xNewObjectStorage == m_xObjectStorage, "The storage must be the same!\n" );
270 return;
271 }
272
273 uno::Reference< lang::XComponent > xComponent( m_xObjectStorage, uno::UNO_QUERY );
274 OSL_ENSURE( !m_xObjectStorage.is() || xComponent.is(), "Wrong storage implementation!" );
275
276 m_xObjectStorage = xNewObjectStorage;
277 m_xParentStorage = xNewParentStorage;
278 m_aEntryName = aNewName;
279
280 #ifdef USE_STORAGEBASED_DOCUMENT
281 // the linked document should not be switched
282 if ( !m_bIsLink )
283 {
284 uno::Reference< document::XStorageBasedDocument > xDoc( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
285 if ( xDoc.is() )
286 SwitchDocToStorage_Impl( xDoc, m_xObjectStorage );
287 }
288 #endif
289
290 try {
291 if ( xComponent.is() )
292 xComponent->dispose();
293 }
294 catch ( uno::Exception& )
295 {
296 }
297 }
298
299 //------------------------------------------------------
SwitchOwnPersistence(const uno::Reference<embed::XStorage> & xNewParentStorage,const::rtl::OUString & aNewName)300 void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
301 const ::rtl::OUString& aNewName )
302 {
303 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
304 return;
305
306 sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
307
308 uno::Reference< embed::XStorage > xNewOwnStorage = xNewParentStorage->openStorageElement( aNewName, nStorageMode );
309 OSL_ENSURE( xNewOwnStorage.is(), "The method can not return empty reference!" );
310
311 SwitchOwnPersistence( xNewParentStorage, xNewOwnStorage, aNewName );
312 }
313
314 //------------------------------------------------------
EmbedAndReparentDoc_Impl(const uno::Reference<util::XCloseable> & i_rxDocument) const315 void OCommonEmbeddedObject::EmbedAndReparentDoc_Impl( const uno::Reference< util::XCloseable >& i_rxDocument ) const
316 {
317 SetDocToEmbedded( uno::Reference< frame::XModel >( i_rxDocument, uno::UNO_QUERY ), m_aModuleName );
318
319 try
320 {
321 uno::Reference < container::XChild > xChild( i_rxDocument, uno::UNO_QUERY );
322 if ( xChild.is() )
323 xChild->setParent( m_xParent );
324 }
325 catch( const lang::NoSupportException & )
326 {
327 OSL_ENSURE( false, "OCommonEmbeddedObject::EmbedAndReparentDoc: cannot set parent at document!" );
328 }
329 }
330
331 //------------------------------------------------------
InitNewDocument_Impl()332 uno::Reference< util::XCloseable > OCommonEmbeddedObject::InitNewDocument_Impl()
333 {
334 uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(),
335 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
336
337 uno::Reference< frame::XModel > xModel( xDocument, uno::UNO_QUERY );
338 uno::Reference< frame::XLoadable > xLoadable( xModel, uno::UNO_QUERY );
339 if ( !xLoadable.is() )
340 throw uno::RuntimeException();
341
342 try
343 {
344 // set the document mode to embedded as the first action on document!!!
345 EmbedAndReparentDoc_Impl( xDocument );
346
347 // if we have a storage to recover the document from, do not use initNew, but instead load from that storage
348 bool bInitNew = true;
349 if ( m_xRecoveryStorage.is() )
350 {
351 uno::Reference< document::XStorageBasedDocument > xDoc( xLoadable, uno::UNO_QUERY );
352 OSL_ENSURE( xDoc.is(), "OCommonEmbeddedObject::InitNewDocument_Impl: cannot recover from a storage when the document is not storage based!" );
353 if ( xDoc.is() )
354 {
355 ::comphelper::NamedValueCollection aLoadArgs;
356 FillDefaultLoadArgs_Impl( m_xRecoveryStorage, aLoadArgs );
357
358 xDoc->loadFromStorage( m_xRecoveryStorage, aLoadArgs.getPropertyValues() );
359 SwitchDocToStorage_Impl( xDoc, m_xObjectStorage );
360 bInitNew = false;
361 }
362 }
363
364 if ( bInitNew )
365 {
366 // init document as a new
367 xLoadable->initNew();
368 }
369 xModel->attachResource( xModel->getURL(), m_aDocMediaDescriptor );
370 }
371 catch( uno::Exception& )
372 {
373 uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
374 if ( xCloseable.is() )
375 {
376 try
377 {
378 xCloseable->close( sal_True );
379 }
380 catch( uno::Exception& )
381 {
382 }
383 }
384
385 throw; // TODO
386 }
387
388 return xDocument;
389 }
390
391 //------------------------------------------------------
LoadLink_Impl()392 uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl()
393 {
394 uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(),
395 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
396
397 uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY );
398 if ( !xLoadable.is() )
399 throw uno::RuntimeException();
400
401 sal_Int32 nLen = 2;
402 uno::Sequence< beans::PropertyValue > aArgs( nLen );
403 aArgs[0].Name = ::rtl::OUString::createFromAscii( "URL" );
404 aArgs[0].Value <<= m_aLinkURL;
405 aArgs[1].Name = ::rtl::OUString::createFromAscii( "FilterName" );
406 aArgs[1].Value <<= m_aLinkFilterName;
407 if ( m_bLinkHasPassword )
408 {
409 aArgs.realloc( ++nLen );
410 aArgs[nLen-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Password" ) );
411 aArgs[nLen-1].Value <<= m_aLinkPassword;
412 }
413
414 aArgs.realloc( m_aDocMediaDescriptor.getLength() + nLen );
415 for ( sal_Int32 nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ )
416 {
417 aArgs[nInd+nLen].Name = m_aDocMediaDescriptor[nInd].Name;
418 aArgs[nInd+nLen].Value = m_aDocMediaDescriptor[nInd].Value;
419 }
420
421 try
422 {
423 // the document is not really an embedded one, it is a link
424 EmbedAndReparentDoc_Impl( xDocument );
425
426 // load the document
427 xLoadable->load( aArgs );
428
429 if ( !m_bLinkHasPassword )
430 {
431 // check if there is a password to cache
432 uno::Reference< frame::XModel > xModel( xLoadable, uno::UNO_QUERY_THROW );
433 uno::Sequence< beans::PropertyValue > aProps = xModel->getArgs();
434 for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ )
435 if ( aProps[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Password" ) ) )
436 && ( aProps[nInd].Value >>= m_aLinkPassword ) )
437 {
438 m_bLinkHasPassword = sal_True;
439 break;
440 }
441 }
442 }
443 catch( uno::Exception& )
444 {
445 uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
446 if ( xCloseable.is() )
447 {
448 try
449 {
450 xCloseable->close( sal_True );
451 }
452 catch( uno::Exception& )
453 {
454 }
455 }
456
457 throw; // TODO
458 }
459
460 return xDocument;
461
462 }
463
464 //------------------------------------------------------
GetFilterName(sal_Int32 nVersion) const465 ::rtl::OUString OCommonEmbeddedObject::GetFilterName( sal_Int32 nVersion ) const
466 {
467 ::rtl::OUString aFilterName = GetPresetFilterName();
468 if ( !aFilterName.getLength() )
469 {
470 try {
471 ::comphelper::MimeConfigurationHelper aHelper( m_xFactory );
472 aFilterName = aHelper.GetDefaultFilterFromServiceName( GetDocumentServiceName(), nVersion );
473 } catch( uno::Exception& )
474 {}
475 }
476
477 return aFilterName;
478 }
479
480 //------------------------------------------------------
FillDefaultLoadArgs_Impl(const uno::Reference<embed::XStorage> & i_rxStorage,::comphelper::NamedValueCollection & o_rLoadArgs) const481 void OCommonEmbeddedObject::FillDefaultLoadArgs_Impl( const uno::Reference< embed::XStorage >& i_rxStorage,
482 ::comphelper::NamedValueCollection& o_rLoadArgs ) const
483 {
484 o_rLoadArgs.put( "DocumentBaseURL", GetBaseURL_Impl() );
485 o_rLoadArgs.put( "HierarchicalDocumentName", m_aEntryName );
486 o_rLoadArgs.put( "ReadOnly", m_bReadOnly );
487
488 ::rtl::OUString aFilterName = GetFilterName( ::comphelper::OStorageHelper::GetXStorageFormat( i_rxStorage ) );
489 OSL_ENSURE( aFilterName.getLength(), "OCommonEmbeddedObject::FillDefaultLoadArgs_Impl: Wrong document service name!" );
490 if ( !aFilterName.getLength() )
491 throw io::IOException(); // TODO: error message/code
492
493 o_rLoadArgs.put( "FilterName", aFilterName );
494 }
495
496 //------------------------------------------------------
LoadDocumentFromStorage_Impl()497 uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadDocumentFromStorage_Impl()
498 {
499 ENSURE_OR_THROW( m_xObjectStorage.is(), "no object storage" );
500
501 const uno::Reference< embed::XStorage > xSourceStorage( m_xRecoveryStorage.is() ? m_xRecoveryStorage : m_xObjectStorage );
502
503 uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(),
504 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
505
506 //#i103460# ODF: take the size given from the parent frame as default
507 uno::Reference< chart2::XChartDocument > xChart( xDocument, uno::UNO_QUERY );
508 if( xChart.is() )
509 {
510 uno::Reference< embed::XVisualObject > xChartVisualObject( xChart, uno::UNO_QUERY );
511 if( xChartVisualObject.is() )
512 xChartVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, m_aDefaultSizeForChart_In_100TH_MM );
513 }
514
515 uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY );
516 uno::Reference< document::XStorageBasedDocument > xDoc
517 #ifdef USE_STORAGEBASED_DOCUMENT
518 ( xDocument, uno::UNO_QUERY )
519 #endif
520 ;
521 if ( !xDoc.is() && !xLoadable.is() ) ///BUG: This should be || instead of && ?
522 throw uno::RuntimeException();
523
524 ::comphelper::NamedValueCollection aLoadArgs;
525 FillDefaultLoadArgs_Impl( xSourceStorage, aLoadArgs );
526
527 uno::Reference< io::XInputStream > xTempInpStream;
528 if ( !xDoc.is() )
529 {
530 xTempInpStream = createTempInpStreamFromStor( xSourceStorage, m_xFactory );
531 if ( !xTempInpStream.is() )
532 throw uno::RuntimeException();
533
534 ::rtl::OUString aTempFileURL;
535 try
536 {
537 // no need to let the file stay after the stream is removed since the embedded document
538 // can not be stored directly
539 uno::Reference< beans::XPropertySet > xTempStreamProps( xTempInpStream, uno::UNO_QUERY_THROW );
540 xTempStreamProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ) >>= aTempFileURL;
541 }
542 catch( uno::Exception& )
543 {
544 }
545
546 OSL_ENSURE( aTempFileURL.getLength(), "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 committed automatically
816 xTempStorage->copyToStorage( xStorage );
817 }
818 }
819
820 //------------------------------------------------------
CreateDocFromMediaDescr_Impl(const uno::Sequence<beans::PropertyValue> & aMedDescr)821 uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateDocFromMediaDescr_Impl(
822 const uno::Sequence< beans::PropertyValue >& aMedDescr )
823 {
824 uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xFactory, GetDocumentServiceName(),
825 m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) );
826
827 uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY );
828 if ( !xLoadable.is() )
829 throw uno::RuntimeException();
830
831 try
832 {
833 // set the document mode to embedded as the first action on the document!!!
834 EmbedAndReparentDoc_Impl( xDocument );
835
836 xLoadable->load( addAsTemplate( aMedDescr ) );
837 }
838 catch( uno::Exception& )
839 {
840 uno::Reference< util::XCloseable > xCloseable( xDocument, uno::UNO_QUERY );
841 if ( xCloseable.is() )
842 {
843 try
844 {
845 xCloseable->close( sal_True );
846 }
847 catch( uno::Exception& )
848 {
849 }
850 }
851
852 throw; // TODO
853 }
854
855 return xDocument;
856 }
857
858 //------------------------------------------------------
CreateTempDocFromLink_Impl()859 uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateTempDocFromLink_Impl()
860 {
861 uno::Reference< util::XCloseable > xResult;
862
863 OSL_ENSURE( m_bIsLink, "The object is not a linked one!\n" );
864
865 uno::Sequence< beans::PropertyValue > aTempMediaDescr;
866
867 sal_Int32 nStorageFormat = SOFFICE_FILEFORMAT_CURRENT;
868 try {
869 nStorageFormat = ::comphelper::OStorageHelper::GetXStorageFormat( m_xParentStorage );
870 }
871 catch ( beans::IllegalTypeException& )
872 {
873 // the container just has an unknown type, use current file format
874 }
875 catch ( uno::Exception& )
876 {
877 OSL_ENSURE( sal_False, "Can not retrieve storage media type!\n" );
878 }
879
880 if ( m_pDocHolder->GetComponent().is() )
881 {
882 aTempMediaDescr.realloc( 4 );
883
884 // TODO/LATER: may be private:stream should be used as target URL
885 ::rtl::OUString aTempFileURL;
886 uno::Reference< io::XInputStream > xTempStream = StoreDocumentToTempStream_Impl( SOFFICE_FILEFORMAT_CURRENT,
887 ::rtl::OUString(),
888 ::rtl::OUString() );
889 try
890 {
891 // no need to let the file stay after the stream is removed since the embedded document
892 // can not be stored directly
893 uno::Reference< beans::XPropertySet > xTempStreamProps( xTempStream, uno::UNO_QUERY_THROW );
894 xTempStreamProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ) >>= aTempFileURL;
895 }
896 catch( uno::Exception& )
897 {
898 }
899
900 OSL_ENSURE( aTempFileURL.getLength(), "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 persistent representation without initialization
965
966 // if the object is loaded
967 // it can switch persistent representation only without initialization
968
969 throw embed::WrongStateException(
970 ::rtl::OUString::createFromAscii( "Can't change persistent 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 sense 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 sense 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 can't 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