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