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