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