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