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