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