Bump version to 5.0-14
[LibreOffice.git] / dbaccess / source / core / dataaccess / documentdefinition.cxx
blob7aeb5a72dff033622b95e73d614a019e11c1ddc7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "documentdefinition.hxx"
21 #include "dbastrings.hrc"
22 #include "sdbcoretools.hxx"
23 #include <tools/debug.hxx>
24 #include <tools/diagnose_ex.h>
25 #include <osl/diagnose.h>
26 #include <comphelper/property.hxx>
27 #include <comphelper/sequence.hxx>
28 #include <comphelper/namedvaluecollection.hxx>
29 #include <comphelper/classids.hxx>
30 #include <com/sun/star/frame/XUntitledNumbers.hpp>
31 #include <com/sun/star/awt/XTopWindow.hpp>
32 #include <com/sun/star/awt/Size.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/frame/Desktop.hpp>
36 #include <com/sun/star/frame/XModel.hpp>
37 #include <com/sun/star/frame/XTitle.hpp>
38 #include <com/sun/star/frame/XController.hpp>
39 #include <com/sun/star/task/XJobExecutor.hpp>
40 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
41 #include <com/sun/star/frame/XFramesSupplier.hpp>
42 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
43 #include <com/sun/star/report/XReportDefinition.hpp>
44 #include <com/sun/star/report/XReportEngine.hpp>
45 #include <com/sun/star/ucb/OpenMode.hpp>
46 #include <com/sun/star/embed/XEmbedObjectFactory.hpp>
47 #include <com/sun/star/embed/EmbeddedObjectCreator.hpp>
48 #include <com/sun/star/embed/Aspects.hpp>
49 #include <com/sun/star/embed/OOoEmbeddedObjectFactory.hpp>
50 #include <ucbhelper/cancelcommandexecution.hxx>
51 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
52 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
53 #include <com/sun/star/embed/ElementModes.hpp>
54 #include <com/sun/star/embed/XEmbedPersist.hpp>
55 #include <com/sun/star/embed/EmbedStates.hpp>
56 #include <com/sun/star/embed/XComponentSupplier.hpp>
57 #include <com/sun/star/embed/EntryInitModes.hpp>
58 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
59 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
60 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
61 #include <com/sun/star/util/XCloseBroadcaster.hpp>
62 #include <com/sun/star/frame/XModule.hpp>
63 #include <com/sun/star/datatransfer/DataFlavor.hpp>
64 #include <com/sun/star/datatransfer/XTransferable.hpp>
65 #include <com/sun/star/container/XNameContainer.hpp>
66 #include <com/sun/star/embed/XTransactedObject.hpp>
67 #include <com/sun/star/embed/XCommonEmbedPersist.hpp>
68 #include "intercept.hxx"
69 #include <com/sun/star/sdb/ErrorCondition.hpp>
70 #include <com/sun/star/sdb/XInteractionDocumentSave.hpp>
71 #include <com/sun/star/task/InteractionHandler.hpp>
72 #include <com/sun/star/sdb/DocumentSaveRequest.hpp>
73 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
74 #include <com/sun/star/document/MacroExecMode.hpp>
75 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
76 #include <com/sun/star/container/XIndexContainer.hpp>
77 #include <com/sun/star/form/XFormsSupplier.hpp>
78 #include <com/sun/star/form/XForm.hpp>
79 #include <comphelper/interaction.hxx>
80 #include <connectivity/dbtools.hxx>
81 #include <vcl/svapp.hxx>
82 #include <osl/mutex.hxx>
83 #include <sal/macros.h>
84 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
85 #include "core_resource.hxx"
86 #include "core_resource.hrc"
87 #include "datasource.hxx"
88 #include <com/sun/star/embed/XStateChangeBroadcaster.hpp>
89 #include <com/sun/star/task/XInteractionApprove.hpp>
90 #include <com/sun/star/task/XInteractionDisapprove.hpp>
91 #include <com/sun/star/frame/XLayoutManager.hpp>
92 #include <cppuhelper/compbase1.hxx>
93 #include <cppuhelper/exc_hlp.hxx>
94 #include <com/sun/star/frame/FrameSearchFlag.hpp>
95 #include <comphelper/sequenceashashmap.hxx>
96 #include <comphelper/mimeconfighelper.hxx>
97 #include <comphelper/storagehelper.hxx>
98 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
99 #include <com/sun/star/io/WrongFormatException.hpp>
100 #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
101 #include <com/sun/star/sdb/application/DatabaseObject.hpp>
102 #include <com/sun/star/util/XModifiable2.hpp>
104 using namespace ::com::sun::star;
105 using namespace view;
106 using namespace uno;
107 using namespace util;
108 using namespace ucb;
109 using namespace beans;
110 using namespace lang;
111 using namespace awt;
112 using namespace embed;
113 using namespace frame;
114 using namespace document;
115 using namespace sdbc;
116 using namespace sdb;
117 using namespace io;
118 using namespace container;
119 using namespace datatransfer;
120 using namespace task;
121 using namespace form;
122 using namespace drawing;
123 using namespace ::osl;
124 using namespace ::comphelper;
125 using namespace ::cppu;
127 using sdb::application::XDatabaseDocumentUI;
128 namespace DatabaseObject = sdb::application::DatabaseObject;
130 #define DEFAULT_WIDTH 10000
131 #define DEFAULT_HEIGHT 7500
133 namespace dbaccess
136 typedef ::boost::optional< bool > optional_bool;
138 // helper
139 namespace
141 OUString lcl_determineContentType_nothrow( const Reference< XStorage >& _rxContainerStorage,
142 const OUString& _rEntityName )
144 OUString sContentType;
147 ::utl::SharedUNOComponent< XPropertySet > xStorageProps(
148 _rxContainerStorage->openStorageElement( _rEntityName, ElementModes::READ ), UNO_QUERY_THROW );
149 OSL_VERIFY( xStorageProps->getPropertyValue( INFO_MEDIATYPE ) >>= sContentType );
151 catch( const Exception& )
153 DBG_UNHANDLED_EXCEPTION();
155 return sContentType;
159 // OEmbedObjectHolder
160 typedef ::cppu::WeakComponentImplHelper1< embed::XStateChangeListener > TEmbedObjectHolder;
161 class OEmbedObjectHolder : public ::comphelper::OBaseMutex
162 ,public TEmbedObjectHolder
164 Reference< XEmbeddedObject > m_xBroadCaster;
165 ODocumentDefinition* m_pDefinition;
166 bool m_bInStateChange;
167 protected:
168 virtual void SAL_CALL disposing() SAL_OVERRIDE;
169 public:
170 OEmbedObjectHolder(const Reference< XEmbeddedObject >& _xBroadCaster,ODocumentDefinition* _pDefinition)
171 : TEmbedObjectHolder(m_aMutex)
172 ,m_xBroadCaster(_xBroadCaster)
173 ,m_pDefinition(_pDefinition)
174 ,m_bInStateChange(false)
176 osl_atomic_increment( &m_refCount );
178 if ( m_xBroadCaster.is() )
179 m_xBroadCaster->addStateChangeListener(this);
181 osl_atomic_decrement( &m_refCount );
184 virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (embed::WrongStateException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
185 virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
186 virtual void SAL_CALL disposing( const lang::EventObject& Source ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
189 void SAL_CALL OEmbedObjectHolder::disposing()
191 if ( m_xBroadCaster.is() )
192 m_xBroadCaster->removeStateChangeListener(this);
193 m_xBroadCaster = NULL;
194 m_pDefinition = NULL;
197 void SAL_CALL OEmbedObjectHolder::changingState( const lang::EventObject& /*aEvent*/, ::sal_Int32 /*nOldState*/, ::sal_Int32 /*nNewState*/ ) throw (embed::WrongStateException, uno::RuntimeException, std::exception)
201 void SAL_CALL OEmbedObjectHolder::stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException, std::exception)
203 if ( !m_bInStateChange && nNewState == EmbedStates::RUNNING && nOldState == EmbedStates::ACTIVE && m_pDefinition )
205 m_bInStateChange = true;
206 Reference<XInterface> xInt(static_cast< ::cppu::OWeakObject* >(m_pDefinition),UNO_QUERY);
208 Reference<XEmbeddedObject> xEmbeddedObject(aEvent.Source,UNO_QUERY);
209 if ( xEmbeddedObject.is() )
210 xEmbeddedObject->changeState(EmbedStates::LOADED);
212 m_bInStateChange = false;
216 void SAL_CALL OEmbedObjectHolder::disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException, std::exception)
218 m_xBroadCaster = NULL;
221 // OEmbeddedClientHelper
222 typedef ::cppu::WeakImplHelper1 < XEmbeddedClient
223 > EmbeddedClientHelper_BASE;
224 class OEmbeddedClientHelper : public EmbeddedClientHelper_BASE
226 ODocumentDefinition* m_pClient;
227 public:
228 OEmbeddedClientHelper(ODocumentDefinition* _pClient) :m_pClient(_pClient) {}
230 virtual void SAL_CALL saveObject( ) throw (ObjectSaveVetoException, Exception, RuntimeException, std::exception) SAL_OVERRIDE
233 // XComponentSupplier
234 virtual Reference< util::XCloseable > SAL_CALL getComponent( ) throw (RuntimeException, std::exception) SAL_OVERRIDE
236 return Reference< css::util::XCloseable >();
239 // XEmbeddedClient
240 virtual void SAL_CALL visibilityChanged( sal_Bool /*bVisible*/ ) throw (WrongStateException, RuntimeException, std::exception) SAL_OVERRIDE
243 inline void resetClient(ODocumentDefinition* _pClient) { m_pClient = _pClient; }
246 // LockModifiable
247 class LockModifiable
249 public:
250 LockModifiable( const Reference< XInterface >& i_rModifiable )
251 :m_xModifiable( i_rModifiable, UNO_QUERY )
253 OSL_ENSURE( m_xModifiable.is(), "LockModifiable::LockModifiable: invalid component!" );
254 if ( m_xModifiable.is() )
256 if ( !m_xModifiable->isSetModifiedEnabled() )
258 // somebody already locked that, no need to lock it, again, and no need to unlock it later
259 m_xModifiable.clear();
261 else
263 m_xModifiable->disableSetModified();
268 ~LockModifiable()
270 if ( m_xModifiable.is() )
271 m_xModifiable->enableSetModified();
274 private:
275 Reference< XModifiable2 > m_xModifiable;
278 // LifetimeCoupler
279 typedef ::cppu::WeakImplHelper1 < css::lang::XEventListener
280 > LifetimeCoupler_Base;
281 /** helper class which couples the lifetime of a component to the lifetime
282 of another component
284 Instances of this class are constructed with two components. The first is
285 simply held by reference, and thus kept alive. The second one is observed
286 for <code>disposing</code> calls - if they occur, i.e. if the component dies,
287 the reference to the first component is cleared.
289 This way, you can ensure that a certain component is kept alive as long
290 as a second component is not disposed.
292 class LifetimeCoupler : public LifetimeCoupler_Base
294 private:
295 Reference< XInterface > m_xClient;
297 public:
298 inline static void couple( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
300 Reference< css::lang::XEventListener > xEnsureDelete( new LifetimeCoupler( _rxClient, _rxActor ) );
303 private:
304 inline LifetimeCoupler( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
305 :m_xClient( _rxClient )
307 OSL_ENSURE( _rxActor.is(), "LifetimeCoupler::LifetimeCoupler: this will crash!" );
308 osl_atomic_increment( &m_refCount );
310 _rxActor->addEventListener( this );
312 osl_atomic_decrement( &m_refCount );
313 OSL_ENSURE( m_refCount, "LifetimeCoupler::LifetimeCoupler: the actor is not holding us by hard ref - this won't work!" );
316 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
317 protected:
320 void SAL_CALL LifetimeCoupler::disposing( const css::lang::EventObject& /*Source*/ ) throw (RuntimeException, std::exception)
322 m_xClient.clear();
325 // ODocumentSaveContinuation
326 class ODocumentSaveContinuation : public OInteraction< XInteractionDocumentSave >
328 OUString m_sName;
329 Reference<XContent> m_xParentContainer;
331 public:
332 ODocumentSaveContinuation() { }
334 inline Reference<XContent> getContent() const { return m_xParentContainer; }
335 inline OUString getName() const { return m_sName; }
337 // XInteractionDocumentSave
338 virtual void SAL_CALL setName( const OUString& _sName,const Reference<XContent>& _xParent) throw(RuntimeException, std::exception) SAL_OVERRIDE;
341 void SAL_CALL ODocumentSaveContinuation::setName( const OUString& _sName,const Reference<XContent>& _xParent) throw(RuntimeException, std::exception)
343 m_sName = _sName;
344 m_xParentContainer = _xParent;
347 OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const Reference< XStorage >& _rxContainerStorage,
348 const OUString& _rEntityName, const Reference< XComponentContext >& _rContext,
349 Sequence< sal_Int8 >& _rClassId )
351 return GetDocumentServiceFromMediaType(
352 lcl_determineContentType_nothrow( _rxContainerStorage, _rEntityName ),
353 _rContext, _rClassId );
356 OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const OUString& _rMediaType,
357 const Reference< XComponentContext >& _rContext, Sequence< sal_Int8 >& _rClassId )
359 OUString sResult;
362 ::comphelper::MimeConfigurationHelper aConfigHelper( _rContext );
363 sResult = aConfigHelper.GetDocServiceNameFromMediaType( _rMediaType );
364 _rClassId = comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(aConfigHelper.GetExplicitlyRegisteredObjClassID( _rMediaType ));
365 if ( !_rClassId.getLength() && !sResult.isEmpty() )
367 Reference< XNameAccess > xObjConfig = aConfigHelper.GetObjConfiguration();
368 if ( xObjConfig.is() )
370 Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
371 for ( sal_Int32 nInd = 0; nInd < aClassIDs.getLength(); nInd++ )
373 Reference< XNameAccess > xObjectProps;
374 OUString aEntryDocName;
376 if ( ( xObjConfig->getByName( aClassIDs[nInd] ) >>= xObjectProps ) && xObjectProps.is()
377 && ( xObjectProps->getByName("ObjectDocumentServiceName") >>= aEntryDocName )
378 && aEntryDocName.equals( sResult ) )
380 _rClassId = comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(aClassIDs[nInd]);
381 break;
386 #if OSL_DEBUG_LEVEL > 0
387 // alternative, shorter approach
388 const Sequence< NamedValue > aProps( aConfigHelper.GetObjectPropsByMediaType( _rMediaType ) );
389 const ::comphelper::NamedValueCollection aMediaTypeProps( aProps );
390 const OUString sAlternativeResult = aMediaTypeProps.getOrDefault( "ObjectDocumentServiceName", OUString() );
391 OSL_ENSURE( sAlternativeResult == sResult, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (1)!" );
392 const Sequence< sal_Int8 > aAlternativeClassID = aMediaTypeProps.getOrDefault( "ClassID", Sequence< sal_Int8 >() );
393 OSL_ENSURE( aAlternativeClassID == _rClassId, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (2)!" );
394 #endif
396 catch ( const Exception& )
398 DBG_UNHANDLED_EXCEPTION();
400 return sResult;
403 // ODocumentDefinition
405 ODocumentDefinition::ODocumentDefinition( const Reference< XInterface >& _rxContainer, const Reference< XComponentContext >& _xORB,
406 const TContentPtr& _pImpl, bool _bForm )
407 :OContentHelper(_xORB,_rxContainer,_pImpl)
408 ,OPropertyStateContainer(OContentHelper::rBHelper)
409 ,m_pInterceptor(NULL)
410 ,m_bForm(_bForm)
411 ,m_bOpenInDesign(false)
412 ,m_bInExecute(false)
413 ,m_bRemoveListener(false)
414 ,m_pClientHelper(NULL)
416 registerProperties();
419 void ODocumentDefinition::initialLoad( const Sequence< sal_Int8 >& i_rClassID, const Sequence< PropertyValue >& i_rCreationArgs,
420 const Reference< XConnection >& i_rConnection )
422 OSL_ENSURE( i_rClassID.getLength(), "ODocumentDefinition::initialLoad: illegal class ID!" );
423 if ( !i_rClassID.getLength() )
424 return;
426 loadEmbeddedObject( i_rConnection, i_rClassID, i_rCreationArgs, false, false );
429 ODocumentDefinition::~ODocumentDefinition()
431 if ( !OContentHelper::rBHelper.bInDispose && !OContentHelper::rBHelper.bDisposed )
433 acquire();
434 dispose();
437 if ( m_pInterceptor )
439 m_pInterceptor->dispose();
440 m_pInterceptor->release();
441 m_pInterceptor = NULL;
445 void ODocumentDefinition::closeObject()
447 ::osl::MutexGuard aGuard(m_aMutex);
448 if ( m_xEmbeddedObject.is() )
452 Reference< com::sun::star::util::XCloseable> xCloseable(m_xEmbeddedObject,UNO_QUERY);
453 if ( xCloseable.is() )
454 xCloseable->close(sal_True);
456 catch(const Exception&)
459 m_xEmbeddedObject = NULL;
460 if ( m_pClientHelper )
462 m_pClientHelper->resetClient(NULL);
463 m_pClientHelper->release();
464 m_pClientHelper = NULL;
469 void SAL_CALL ODocumentDefinition::disposing()
471 OContentHelper::disposing();
472 ::osl::MutexGuard aGuard(m_aMutex);
473 closeObject();
474 ::comphelper::disposeComponent(m_xListener);
475 if ( m_bRemoveListener )
477 Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
478 if ( xCloseable.is() )
479 xCloseable->removeCloseListener(this);
483 css::uno::Sequence<sal_Int8> ODocumentDefinition::getImplementationId()
484 throw (css::uno::RuntimeException, std::exception)
486 return css::uno::Sequence<sal_Int8>();
489 IMPLEMENT_GETTYPES3(ODocumentDefinition,OContentHelper,OPropertyStateContainer,ODocumentDefinition_Base);
490 IMPLEMENT_FORWARD_XINTERFACE3( ODocumentDefinition,OContentHelper,OPropertyStateContainer,ODocumentDefinition_Base)
491 IMPLEMENT_SERVICE_INFO1(ODocumentDefinition,"com.sun.star.comp.dba.ODocumentDefinition",SERVICE_SDB_DOCUMENTDEFINITION)
493 void ODocumentDefinition::registerProperties()
495 #define REGISTER_PROPERTY( name, location ) \
496 registerProperty( PROPERTY_##name, PROPERTY_ID_##name, PropertyAttribute::READONLY, &location, cppu::UnoType<decltype(location)>::get() );
498 #define REGISTER_PROPERTY_BV( name, location ) \
499 registerProperty( PROPERTY_##name, PROPERTY_ID_##name, PropertyAttribute::CONSTRAINED | PropertyAttribute::BOUND | PropertyAttribute::READONLY, &location, cppu::UnoType<decltype(location)>::get() );
501 REGISTER_PROPERTY_BV( NAME, m_pImpl->m_aProps.aTitle );
502 REGISTER_PROPERTY ( AS_TEMPLATE, m_pImpl->m_aProps.bAsTemplate );
503 REGISTER_PROPERTY ( PERSISTENT_NAME, m_pImpl->m_aProps.sPersistentName );
504 REGISTER_PROPERTY ( IS_FORM, m_bForm );
507 void SAL_CALL ODocumentDefinition::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const
509 if ( i_nHandle == PROPERTY_ID_PERSISTENT_PATH )
511 OUString sPersistentPath;
512 if ( !m_pImpl->m_aProps.sPersistentName.isEmpty() )
514 OUStringBuffer aBuffer;
515 aBuffer.append( ODatabaseModelImpl::getObjectContainerStorageName( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT ) );
516 aBuffer.append( '/' );
517 aBuffer.append( m_pImpl->m_aProps.sPersistentName );
518 sPersistentPath = aBuffer.makeStringAndClear();
520 o_rValue <<= sPersistentPath;
521 return;
524 OPropertyStateContainer::getFastPropertyValue( o_rValue, i_nHandle );
527 Reference< XPropertySetInfo > SAL_CALL ODocumentDefinition::getPropertySetInfo( ) throw(RuntimeException, std::exception)
529 Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
530 return xInfo;
533 IPropertyArrayHelper& ODocumentDefinition::getInfoHelper()
535 return *getArrayHelper();
538 IPropertyArrayHelper* ODocumentDefinition::createArrayHelper( ) const
540 // properties maintained by our base class (see registerProperties)
541 Sequence< Property > aProps;
542 describeProperties( aProps );
544 // properties not maintained by our base class
545 Sequence< Property > aManualProps( 1 );
546 aManualProps[0].Name = PROPERTY_PERSISTENT_PATH;
547 aManualProps[0].Handle = PROPERTY_ID_PERSISTENT_PATH;
548 aManualProps[0].Type = ::cppu::UnoType<OUString>::get();
549 aManualProps[0].Attributes = PropertyAttribute::READONLY;
551 return new OPropertyArrayHelper( ::comphelper::concatSequences( aProps, aManualProps ) );
554 class OExecuteImpl
556 bool& m_rbSet;
557 public:
558 OExecuteImpl(bool& _rbSet) : m_rbSet(_rbSet){ m_rbSet=true; }
559 ~OExecuteImpl(){ m_rbSet = false; }
562 namespace
564 bool lcl_extractOpenMode( const Any& _rValue, sal_Int32& _out_rMode )
566 OpenCommandArgument aOpenCommand;
567 if ( _rValue >>= aOpenCommand )
568 _out_rMode = aOpenCommand.Mode;
569 else
571 OpenCommandArgument2 aOpenCommand2;
572 if ( _rValue >>= aOpenCommand2 )
573 _out_rMode = aOpenCommand2.Mode;
574 else
575 return false;
577 return true;
581 void ODocumentDefinition::impl_removeFrameFromDesktop_throw( const Reference<XComponentContext> & _rxContext, const Reference< XFrame >& _rxFrame )
583 Reference< XDesktop2 > xDesktop = Desktop::create( _rxContext );
584 Reference< XFrames > xFrames( xDesktop->getFrames(), UNO_QUERY_THROW );
585 xFrames->remove( _rxFrame );
588 void ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow( const bool i_bReactivated )
592 Reference< XModel > xModel( getComponent(), UNO_QUERY );
593 Reference< XController > xController( xModel.is() ? xModel->getCurrentController() : Reference< XController >() );
594 if ( !xController.is() )
595 return;
597 if ( !m_xListener.is() )
598 // it's the first time the embedded object has been activated
599 // create an OEmbedObjectHolder
600 m_xListener = new OEmbedObjectHolder( m_xEmbeddedObject, this );
602 // raise the window to top (especially necessary if this is not the first activation)
603 Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW );
604 Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
605 xTopWindow->toFront();
607 // remove the frame from the desktop's frame collection because we need full control of it.
608 impl_removeFrameFromDesktop_throw( m_aContext, xFrame );
610 // ensure that we ourself are kept alive as long as the embedded object's frame is
611 // opened
612 LifetimeCoupler::couple( *this, xFrame.get() );
614 // init the edit view
615 if ( m_bForm && m_bOpenInDesign && !i_bReactivated )
616 impl_initFormEditView( xController );
618 catch( const RuntimeException& )
620 DBG_UNHANDLED_EXCEPTION();
624 namespace
626 // PreserveVisualAreaSize
627 /** stack-guard for preserving the size of the VisArea of an XModel
629 class PreserveVisualAreaSize
631 private:
632 Reference< XVisualObject > m_xVisObject;
633 awt::Size m_aOriginalSize;
635 public:
636 inline PreserveVisualAreaSize( const Reference< XModel >& _rxModel )
637 :m_xVisObject( _rxModel, UNO_QUERY )
639 if ( m_xVisObject.is() )
643 m_aOriginalSize = m_xVisObject->getVisualAreaSize( Aspects::MSOLE_CONTENT );
645 catch ( const Exception& )
647 OSL_FAIL( "PreserveVisualAreaSize::PreserveVisualAreaSize: caught an exception!" );
652 inline ~PreserveVisualAreaSize()
654 if ( m_xVisObject.is() && m_aOriginalSize.Width && m_aOriginalSize.Height )
658 m_xVisObject->setVisualAreaSize( Aspects::MSOLE_CONTENT, m_aOriginalSize );
660 catch ( const Exception& )
662 OSL_FAIL( "PreserveVisualAreaSize::~PreserveVisualAreaSize: caught an exception!" );
668 // LayoutManagerLock
669 /** helper class for stack-usage which during its lifetime locks a layout manager
671 class LayoutManagerLock
673 private:
674 Reference< XLayoutManager > m_xLayoutManager;
676 public:
677 inline LayoutManagerLock( const Reference< XController >& _rxController )
679 OSL_ENSURE( _rxController.is(), "LayoutManagerLock::LayoutManagerLock: this will crash!" );
680 Reference< XFrame > xFrame( _rxController->getFrame() );
683 Reference< XPropertySet > xPropSet( xFrame, UNO_QUERY_THROW );
684 m_xLayoutManager.set(
685 xPropSet->getPropertyValue( "LayoutManager" ),
686 UNO_QUERY_THROW );
687 m_xLayoutManager->lock();
690 catch( const Exception& )
692 OSL_FAIL( "LayoutManagerLock::LayoutManagerLock: caught an exception!" );
696 inline ~LayoutManagerLock()
700 // unlock the layout manager
701 if ( m_xLayoutManager.is() )
702 m_xLayoutManager->unlock();
704 catch( const Exception& )
706 OSL_FAIL( "LayoutManagerLock::~LayoutManagerLock: caught an exception!" );
712 void ODocumentDefinition::impl_initFormEditView( const Reference< XController >& _rxController )
716 Reference< XViewSettingsSupplier > xSettingsSupplier( _rxController, UNO_QUERY_THROW );
717 Reference< XPropertySet > xViewSettings( xSettingsSupplier->getViewSettings(), UNO_QUERY_THROW );
719 // the below code could indirectly tamper with the "modified" flag of the model, temporarily disable this
720 LockModifiable aLockModify( _rxController->getModel() );
722 // The visual area size can be changed by the setting of the following properties
723 // so it should be restored later
724 PreserveVisualAreaSize aPreserveVisAreaSize( _rxController->getModel() );
726 // Layout manager should not layout while the size is still not restored
727 // so it will stay locked for this time
728 LayoutManagerLock aLockLayout( _rxController );
730 // setting of the visual properties
731 xViewSettings->setPropertyValue("ShowRulers",makeAny(sal_True));
732 xViewSettings->setPropertyValue("ShowVertRuler",makeAny(sal_True));
733 xViewSettings->setPropertyValue("ShowHoriRuler",makeAny(sal_True));
734 xViewSettings->setPropertyValue("IsRasterVisible",makeAny(sal_True));
735 xViewSettings->setPropertyValue("IsSnapToRaster",makeAny(sal_True));
736 xViewSettings->setPropertyValue("ShowOnlineLayout",makeAny(sal_True));
737 xViewSettings->setPropertyValue("RasterSubdivisionX",makeAny(sal_Int32(5)));
738 xViewSettings->setPropertyValue("RasterSubdivisionY",makeAny(sal_Int32(5)));
740 catch( const Exception& )
742 DBG_UNHANDLED_EXCEPTION();
746 void ODocumentDefinition::impl_showOrHideComponent_throw( const bool i_bShow )
748 const sal_Int32 nCurrentState = m_xEmbeddedObject.is() ? m_xEmbeddedObject->getCurrentState() : EmbedStates::LOADED;
749 switch ( nCurrentState )
751 default:
752 case EmbedStates::LOADED:
753 throw embed::WrongStateException( OUString(), *this );
755 case EmbedStates::RUNNING:
756 if ( !i_bShow )
757 // fine, a running (and not yet active) object is never visible
758 return;
760 LockModifiable aLockModify( impl_getComponent_throw() );
761 m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
762 impl_onActivateEmbeddedObject_nothrow( false );
764 break;
766 case EmbedStates::ACTIVE:
768 Reference< XModel > xEmbeddedDoc( impl_getComponent_throw( true ), UNO_QUERY_THROW );
769 Reference< XController > xEmbeddedController( xEmbeddedDoc->getCurrentController(), UNO_SET_THROW );
770 Reference< XFrame > xEmbeddedFrame( xEmbeddedController->getFrame(), UNO_SET_THROW );
771 Reference< XWindow > xEmbeddedWindow( xEmbeddedFrame->getContainerWindow(), UNO_SET_THROW );
772 xEmbeddedWindow->setVisible( i_bShow );
774 break;
778 Any ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, const bool _bActivate,
779 const Reference< XCommandEnvironment >& _rxEnvironment )
781 OExecuteImpl aExecuteGuard( m_bInExecute );
783 Reference< XConnection > xConnection;
784 sal_Int32 nOpenMode = OpenMode::DOCUMENT;
786 ::comphelper::NamedValueCollection aDocumentArgs;
788 // for the document, default to the interaction handler as used for loading the DB doc
789 // This might be overwritten below, when examining _rOpenArgument.
790 const ::comphelper::NamedValueCollection& aDBDocArgs( m_pImpl->m_pDataSource->getMediaDescriptor() );
791 Reference< XInteractionHandler > xHandler( aDBDocArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
792 if ( xHandler.is() )
793 aDocumentArgs.put( "InteractionHandler", xHandler );
795 ::boost::optional< sal_Int16 > aDocumentMacroMode;
797 if ( !lcl_extractOpenMode( _rOpenArgument, nOpenMode ) )
799 Sequence< PropertyValue > aArguments;
800 if ( _rOpenArgument >>= aArguments )
802 const PropertyValue* pIter = aArguments.getConstArray();
803 const PropertyValue* pEnd = pIter + aArguments.getLength();
804 for ( ;pIter != pEnd; ++pIter )
806 if ( pIter->Name == PROPERTY_ACTIVE_CONNECTION )
808 xConnection.set( pIter->Value, UNO_QUERY );
809 continue;
812 if ( lcl_extractOpenMode( pIter->Value, nOpenMode ) )
813 continue;
815 if ( pIter->Name == "MacroExecutionMode" )
817 sal_Int16 nMacroExecMode( !aDocumentMacroMode ? MacroExecMode::USE_CONFIG : *aDocumentMacroMode );
818 OSL_VERIFY( pIter->Value >>= nMacroExecMode );
819 aDocumentMacroMode.reset( nMacroExecMode );
820 continue;
823 // unknown argument -> pass to the loaded document
824 aDocumentArgs.put( pIter->Name, pIter->Value );
829 bool bExecuteDBDocMacros = m_pImpl->m_pDataSource->checkMacrosOnLoading();
830 // Note that this call implies the user might be asked for the macro execution mode.
831 // Normally, this would happen when the database document is loaded, and subsequent calls
832 // will simply use the user's decision from this point in time.
833 // However, it is possible to programmatically load forms/reports, without actually
834 // loading the database document into a frame. In this case, the user will be asked
835 // here and now.
836 // #i87741#
838 // allow the command arguments to downgrade the macro execution mode, but not to upgrade
839 // it
840 if ( ( m_pImpl->m_pDataSource->getImposedMacroExecMode() == MacroExecMode::USE_CONFIG )
841 && bExecuteDBDocMacros
844 // while loading the whole database document, USE_CONFIG, was passed.
845 // Additionally, *by now* executing macros from the DB doc is allowed (this is what bExecuteDBDocMacros
846 // indicates). This means either one of:
847 // 1. The DB doc or one of the sub docs contained macros and
848 // 1a. the user explicitly allowed executing them
849 // 1b. the configuration allows executing them without asking the user
850 // 2. Neither the DB doc nor the sub docs contained macros, thus macro
851 // execution was silently enabled, assuming that any macro will be a
852 // user-created macro
854 // The problem with this: If the to-be-opened sub document has macros embedded in
855 // the content.xml (which is valid ODF, but normally not produced by OOo itself),
856 // then this has not been detected while loading the database document - it would
857 // be too expensive, as it effectively would require loading all forms/reports.
859 // So, in such a case, and with 2. above, we would silently execute those macros,
860 // regardless of the global security settings - which would be a security issue, of
861 // course.
862 if ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eNoMacros )
864 // this is case 2. from above
865 // So, pass a USE_CONFIG to the to-be-loaded document. This means that
866 // the user will be prompted with a security message upon opening this
867 // sub document, in case the settings require this, *and* the document
868 // contains scripts in the content.xml. But this is better than the security
869 // issue we had before ...
870 aDocumentMacroMode.reset( MacroExecMode::USE_CONFIG );
874 if ( !aDocumentMacroMode )
876 // nobody so far felt responsible for setting it
877 // => use the DBDoc-wide macro exec mode for the document, too
878 aDocumentMacroMode.reset( bExecuteDBDocMacros ? MacroExecMode::ALWAYS_EXECUTE_NO_WARN : MacroExecMode::NEVER_EXECUTE );
880 aDocumentArgs.put( "MacroExecutionMode", *aDocumentMacroMode );
882 if ( ( nOpenMode == OpenMode::ALL )
883 || ( nOpenMode == OpenMode::FOLDERS )
884 || ( nOpenMode == OpenMode::DOCUMENTS )
885 || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_NONE )
886 || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_WRITE )
889 // not supported
890 ucbhelper::cancelCommandExecution(
891 makeAny( UnsupportedOpenModeException(
892 OUString(),
893 static_cast< cppu::OWeakObject * >( this ),
894 sal_Int16( nOpenMode ) ) ),
895 _rxEnvironment );
896 // Unreachable
897 OSL_FAIL( "unreachable" );
900 OSL_ENSURE( !m_pImpl->m_aProps.sPersistentName.isEmpty(),
901 "ODocumentDefinition::onCommandOpenSomething: no persistent name - cannot load!" );
902 if ( m_pImpl->m_aProps.sPersistentName.isEmpty() )
903 return Any();
905 // embedded objects themself do not support the hidden flag. We implement support for
906 // it by changing the STATE to RUNNING only, instead of ACTIVE.
907 bool bOpenHidden = aDocumentArgs.getOrDefault( "Hidden", false );
908 aDocumentArgs.remove( "Hidden" );
910 loadEmbeddedObject( xConnection, Sequence< sal_Int8 >(), aDocumentArgs.getPropertyValues(), false, !m_bOpenInDesign );
911 OSL_ENSURE( m_xEmbeddedObject.is(), "ODocumentDefinition::onCommandOpenSomething: what's this?" );
912 if ( !m_xEmbeddedObject.is() )
913 return Any();
915 Reference< XModel > xModel( getComponent(), UNO_QUERY );
916 Reference< report::XReportDefinition > xReportDefinition(xModel,UNO_QUERY);
918 Reference< XModule > xModule( xModel, UNO_QUERY );
919 if ( xModule.is() )
921 if ( m_bForm )
922 xModule->setIdentifier( "com.sun.star.sdb.FormDesign" );
923 else if ( !xReportDefinition.is() )
924 xModule->setIdentifier( "com.sun.star.text.TextDocument" );
926 updateDocumentTitle();
929 bool bIsAliveNewStyleReport = ( !m_bOpenInDesign && xReportDefinition.is() );
930 if ( bIsAliveNewStyleReport )
932 // we are in ReadOnly mode
933 // we would like to open the Writer or Calc with the report direct, without design it.
934 Reference< report::XReportEngine > xReportEngine( m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.report.OReportEngineJFree", m_aContext), UNO_QUERY_THROW );
936 xReportEngine->setReportDefinition(xReportDefinition);
937 xReportEngine->setActiveConnection(m_xLastKnownConnection);
938 if ( bOpenHidden )
939 return makeAny( xReportEngine->createDocumentModel() );
940 return makeAny( xReportEngine->createDocumentAlive( NULL ) );
943 if ( _bActivate && !bOpenHidden )
945 LockModifiable aLockModify( impl_getComponent_throw() );
946 m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
947 impl_onActivateEmbeddedObject_nothrow( false );
949 else
951 // ensure that we ourself are kept alive as long as the document is open
952 LifetimeCoupler::couple( *this, xModel.get() );
955 if ( !m_bForm && m_pImpl->m_aProps.bAsTemplate && !m_bOpenInDesign )
956 ODocumentDefinition::fillReportData( m_aContext, getComponent(), xConnection );
958 return makeAny( xModel );
961 Any SAL_CALL ODocumentDefinition::execute( const Command& aCommand, sal_Int32 CommandId, const Reference< XCommandEnvironment >& Environment ) throw (Exception, CommandAbortedException, RuntimeException, std::exception)
963 Any aRet;
965 bool bOpen = aCommand.Name == "open";
966 bool bOpenInDesign = aCommand.Name == "openDesign";
967 bool bOpenForMail = aCommand.Name == "openForMail";
968 if ( bOpen || bOpenInDesign || bOpenForMail )
970 // opening the document involves a lot of VCL code, which is not thread-safe, but needs the SolarMutex locked.
971 // Unfortunately, the DocumentDefinition, as well as the EmbeddedObject implementation, calls into VCL-dependent
972 // components *without* releasing the own mutex, which is a guaranteed recipe for deadlocks.
973 // We have control over this implementation here, and in modifying it to release the own mutex before calling into
974 // the VCL-dependent components is not too difficult (was there, seen it).
975 // However, we do /not/ have control over the EmbeddedObject implementation, and from a first look, it seems as
976 // making it release the own mutex before calling SolarMutex-code is ... difficult, at least.
977 // So, to be on the same side, we lock the SolarMutex here. Yes, it sucks.
978 ::SolarMutexGuard aSolarGuard;
979 ::osl::ClearableMutexGuard aGuard(m_aMutex);
980 if ( m_bInExecute )
981 return aRet;
983 bool bActivateObject = true;
984 if ( bOpenForMail )
986 OSL_FAIL( "ODocumentDefinition::execute: 'openForMail' should not be used anymore - use the 'Hidden' parameter instead!" );
987 bActivateObject = false;
990 // if the object is already opened, do nothing
991 if ( m_xEmbeddedObject.is() )
993 sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
994 bool bIsActive = ( nCurrentState == EmbedStates::ACTIVE );
996 if ( bIsActive )
998 // exception: new-style reports always create a new document when "open" is executed
999 Reference< report::XReportDefinition > xReportDefinition( impl_getComponent_throw( false ), UNO_QUERY );
1000 bool bIsAliveNewStyleReport = ( xReportDefinition.is() && ( bOpen || bOpenForMail ) );
1002 if ( !bIsAliveNewStyleReport )
1004 impl_onActivateEmbeddedObject_nothrow( true );
1005 return makeAny( getComponent() );
1010 m_bOpenInDesign = bOpenInDesign || bOpenForMail;
1011 return onCommandOpenSomething( aCommand.Argument, bActivateObject, Environment );
1014 ::osl::ClearableMutexGuard aGuard(m_aMutex);
1015 if ( m_bInExecute )
1016 return aRet;
1018 if ( aCommand.Name == "copyTo" )
1020 Sequence<Any> aIni;
1021 aCommand.Argument >>= aIni;
1022 if ( aIni.getLength() != 2 )
1024 OSL_FAIL( "Wrong argument type!" );
1025 ucbhelper::cancelCommandExecution(
1026 makeAny( IllegalArgumentException(
1027 OUString(),
1028 static_cast< cppu::OWeakObject * >( this ),
1029 -1 ) ),
1030 Environment );
1031 // Unreachable
1033 Reference< XStorage> xDest(aIni[0],UNO_QUERY);
1034 OUString sPersistentName;
1035 aIni[1] >>= sPersistentName;
1036 Reference< XStorage> xStorage = getContainerStorage();
1038 xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xDest,sPersistentName);
1040 else if ( aCommand.Name == "preview" )
1042 onCommandPreview(aRet);
1044 else if ( aCommand.Name == "insert" )
1046 Sequence<Any> aIni;
1047 aCommand.Argument >>= aIni;
1048 if ( !aIni.getLength() )
1050 OSL_FAIL( "Wrong argument count!" );
1051 ucbhelper::cancelCommandExecution(
1052 makeAny( IllegalArgumentException(
1053 OUString(),
1054 static_cast< cppu::OWeakObject * >( this ),
1055 -1 ) ),
1056 Environment );
1057 // Unreachable
1059 OUString sURL;
1060 aIni[0] >>= sURL;
1061 onCommandInsert( sURL, Environment );
1063 else if ( aCommand.Name == "getdocumentinfo" // compatibility
1064 || aCommand.Name == "getDocumentInfo" )
1066 onCommandGetDocumentProperties( aRet );
1068 else if ( aCommand.Name == "delete" )
1070 // delete
1071 closeObject();
1072 Reference< XStorage> xStorage = getContainerStorage();
1073 if ( xStorage.is() )
1074 xStorage->removeElement(m_pImpl->m_aProps.sPersistentName);
1076 dispose();
1079 else if ( aCommand.Name == "storeOwn" // compatibility
1080 || aCommand.Name == "store"
1083 impl_store_throw();
1085 else if ( aCommand.Name == "shutdown" // compatibility
1086 || aCommand.Name == "close"
1089 aRet <<= impl_close_throw();
1091 else if ( aCommand.Name == "show" )
1093 impl_showOrHideComponent_throw( true );
1095 else if ( aCommand.Name == "hide" )
1097 impl_showOrHideComponent_throw( false );
1099 else
1101 aRet = OContentHelper::execute(aCommand,CommandId,Environment);
1104 return aRet;
1107 namespace
1109 void lcl_resetChildFormsToEmptyDataSource( const Reference< XIndexAccess>& _rxFormsContainer )
1111 OSL_PRECOND( _rxFormsContainer.is(), "lcl_resetChildFormsToEmptyDataSource: illegal call!" );
1112 sal_Int32 count = _rxFormsContainer->getCount();
1113 for ( sal_Int32 i = 0; i < count; ++i )
1115 Reference< XForm > xForm( _rxFormsContainer->getByIndex( i ), UNO_QUERY );
1116 if ( !xForm.is() )
1117 continue;
1119 // if the element is a form, reset its DataSourceName property to an empty string
1122 Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
1123 xFormProps->setPropertyValue( PROPERTY_DATASOURCENAME, makeAny( OUString() ) );
1125 catch( const Exception& )
1127 DBG_UNHANDLED_EXCEPTION();
1130 // if the element is a container itself, step down the component hierarchy
1131 Reference< XIndexAccess > xContainer( xForm, UNO_QUERY );
1132 if ( xContainer.is() )
1133 lcl_resetChildFormsToEmptyDataSource( xContainer );
1137 void lcl_resetFormsToEmptyDataSource( const Reference< XEmbeddedObject>& _rxEmbeddedObject )
1141 Reference< XDrawPageSupplier > xSuppPage( _rxEmbeddedObject->getComponent(), UNO_QUERY_THROW );
1142 // if this interface does not exist, then either getComponent returned NULL,
1143 // or the document is a multi-page document. The latter is allowed, but currently
1144 // simply not handled by this code, as it would not normally happen.
1146 Reference< XFormsSupplier > xSuppForms( xSuppPage->getDrawPage(), UNO_QUERY_THROW );
1147 Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW );
1148 lcl_resetChildFormsToEmptyDataSource( xForms );
1150 catch( const Exception& )
1152 DBG_UNHANDLED_EXCEPTION();
1158 void ODocumentDefinition::onCommandInsert( const OUString& _sURL, const Reference< XCommandEnvironment >& Environment )
1159 throw( Exception )
1161 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1163 // Check, if all required properties were set.
1164 if ( _sURL.isEmpty() || m_xEmbeddedObject.is() )
1166 OSL_FAIL( "Content::onCommandInsert - property value missing!" );
1168 Sequence< OUString > aProps( 1 );
1169 aProps[ 0 ] = PROPERTY_URL;
1170 ucbhelper::cancelCommandExecution(
1171 makeAny( MissingPropertiesException(
1172 OUString(),
1173 static_cast< cppu::OWeakObject * >( this ),
1174 aProps ) ),
1175 Environment );
1176 // Unreachable
1179 if ( !m_xEmbeddedObject.is() )
1181 Reference< XStorage> xStorage = getContainerStorage();
1182 if ( xStorage.is() )
1184 Reference< XEmbeddedObjectCreator> xEmbedFactory = EmbeddedObjectCreator::create(m_aContext);
1185 Sequence<PropertyValue> aEmpty,aMediaDesc(1);
1186 aMediaDesc[0].Name = PROPERTY_URL;
1187 aMediaDesc[0].Value <<= _sURL;
1188 m_xEmbeddedObject.set(xEmbedFactory->createInstanceInitFromMediaDescriptor( xStorage
1189 ,m_pImpl->m_aProps.sPersistentName
1190 ,aMediaDesc
1191 ,aEmpty),UNO_QUERY);
1193 lcl_resetFormsToEmptyDataSource( m_xEmbeddedObject );
1194 // #i57669#
1196 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1197 if ( xPersist.is() )
1199 xPersist->storeOwn();
1203 Reference< com::sun::star::util::XCloseable> xCloseable(m_xEmbeddedObject,UNO_QUERY);
1204 if ( xCloseable.is() )
1205 xCloseable->close(sal_True);
1207 catch(const Exception&)
1210 m_xEmbeddedObject = NULL;
1214 aGuard.clear();
1217 bool ODocumentDefinition::save(bool _bApprove)
1219 // default handling: instantiate an interaction handler and let it handle the parameter request
1220 if ( !m_bOpenInDesign )
1221 return false;
1226 ::SolarMutexGuard aSolarGuard;
1228 // the request
1229 Reference<XNameAccess> xName(m_xParentContainer,UNO_QUERY);
1230 DocumentSaveRequest aRequest;
1231 aRequest.Name = m_pImpl->m_aProps.aTitle;
1232 if ( aRequest.Name.isEmpty() )
1234 if ( m_bForm )
1235 aRequest.Name = DBACORE_RESSTRING( RID_STR_FORM );
1236 else
1237 aRequest.Name = DBACORE_RESSTRING( RID_STR_REPORT );
1238 aRequest.Name = ::dbtools::createUniqueName(xName,aRequest.Name);
1241 aRequest.Content.set(m_xParentContainer,UNO_QUERY);
1242 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1243 Reference< XInteractionRequest > xRequest(pRequest);
1244 // some knittings
1245 // two continuations allowed: OK and Cancel
1246 ODocumentSaveContinuation* pDocuSave = NULL;
1248 if ( m_pImpl->m_aProps.aTitle.isEmpty() )
1250 pDocuSave = new ODocumentSaveContinuation;
1251 pRequest->addContinuation(pDocuSave);
1253 if ( _bApprove )
1255 OInteraction< XInteractionApprove >* pApprove = new OInteraction< XInteractionApprove >;
1256 pRequest->addContinuation(pApprove);
1259 OInteraction< XInteractionDisapprove >* pDisApprove = new OInteraction< XInteractionDisapprove >;
1260 pRequest->addContinuation(pDisApprove);
1262 OInteractionAbort* pAbort = new OInteractionAbort;
1263 pRequest->addContinuation(pAbort);
1265 // create the handler, let it handle the request
1266 Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(m_aContext, 0) );
1267 xHandler->handle(xRequest);
1269 if ( pAbort->wasSelected() )
1270 return false;
1271 if ( pDisApprove->wasSelected() )
1272 return true;
1273 if ( pDocuSave && pDocuSave->wasSelected() )
1275 Reference<XNameContainer> xNC( pDocuSave->getContent(), UNO_QUERY_THROW );
1277 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1278 NameChangeNotifier aNameChangeAndNotify( *this, pDocuSave->getName(), aGuard );
1279 m_pImpl->m_aProps.aTitle = pDocuSave->getName();
1281 Reference< XContent> xContent = this;
1282 xNC->insertByName(pDocuSave->getName(),makeAny(xContent));
1284 updateDocumentTitle();
1288 ::osl::MutexGuard aGuard(m_aMutex);
1289 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1290 if ( xPersist.is() )
1292 xPersist->storeOwn();
1293 notifyDataSourceModified();
1296 catch(const Exception&)
1298 OSL_FAIL("ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
1300 return true;
1303 bool ODocumentDefinition::saveAs()
1305 // default handling: instantiate an interaction handler and let it handle the parameter request
1306 if ( !m_bOpenInDesign )
1307 return false;
1310 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1311 if ( m_pImpl->m_aProps.aTitle.isEmpty() )
1313 aGuard.clear();
1314 return save(false); // (sal_False) : we don't want an approve dialog
1320 ::SolarMutexGuard aSolarGuard;
1322 // the request
1323 Reference<XNameAccess> xName(m_xParentContainer,UNO_QUERY);
1324 DocumentSaveRequest aRequest;
1325 aRequest.Name = m_pImpl->m_aProps.aTitle;
1327 aRequest.Content.set(m_xParentContainer,UNO_QUERY);
1328 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1329 Reference< XInteractionRequest > xRequest(pRequest);
1330 // some knittings
1331 // two continuations allowed: OK and Cancel
1332 ODocumentSaveContinuation* pDocuSave = new ODocumentSaveContinuation;
1333 pRequest->addContinuation(pDocuSave);
1334 OInteraction< XInteractionDisapprove >* pDisApprove = new OInteraction< XInteractionDisapprove >;
1335 pRequest->addContinuation(pDisApprove);
1336 OInteractionAbort* pAbort = new OInteractionAbort;
1337 pRequest->addContinuation(pAbort);
1339 // create the handler, let it handle the request
1340 Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(m_aContext, 0) );
1341 xHandler->handle(xRequest);
1343 if ( pAbort->wasSelected() )
1344 return false;
1345 if ( pDisApprove->wasSelected() )
1346 return true;
1347 if ( pDocuSave->wasSelected() )
1349 ::osl::MutexGuard aGuard(m_aMutex);
1350 Reference<XNameContainer> xNC(pDocuSave->getContent(),UNO_QUERY);
1351 if ( xNC.is() )
1353 if ( m_pImpl->m_aProps.aTitle != pDocuSave->getName() )
1357 Reference< XStorage> xStorage = getContainerStorage();
1358 static const char sBaseName[] = "Obj";
1360 OUString sPersistentName = ::dbtools::createUniqueName(xStorage,sBaseName);
1361 xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xStorage,sPersistentName);
1363 OUString sOldName = m_pImpl->m_aProps.aTitle;
1364 rename(pDocuSave->getName());
1365 updateDocumentTitle();
1367 Sequence< Any > aArguments(3);
1368 PropertyValue aValue;
1369 // set as folder
1370 aValue.Name = PROPERTY_NAME;
1371 aValue.Value <<= sOldName;
1372 aArguments[0] <<= aValue;
1374 aValue.Name = PROPERTY_PERSISTENT_NAME;
1375 aValue.Value <<= sPersistentName;
1376 aArguments[1] <<= aValue;
1378 aValue.Name = PROPERTY_AS_TEMPLATE;
1379 aValue.Value <<= m_pImpl->m_aProps.bAsTemplate;
1380 aArguments[2] <<= aValue;
1382 Reference< XMultiServiceFactory > xORB( m_xParentContainer, UNO_QUERY_THROW );
1383 Reference< XInterface > xComponent( xORB->createInstanceWithArguments( SERVICE_SDB_DOCUMENTDEFINITION, aArguments ) );
1384 Reference< XNameContainer > xNameContainer( m_xParentContainer, UNO_QUERY_THROW );
1385 xNameContainer->insertByName( sOldName, makeAny( xComponent ) );
1387 catch(const Exception&)
1389 DBG_UNHANDLED_EXCEPTION();
1392 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1393 if ( xPersist.is() )
1395 xPersist->storeOwn();
1396 notifyDataSourceModified();
1403 catch(const Exception&)
1405 OSL_FAIL("ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
1407 return true;
1410 namespace
1412 void lcl_putLoadArgs( ::comphelper::NamedValueCollection& _io_rArgs, const optional_bool& _bSuppressMacros, const optional_bool& _bReadOnly )
1414 if ( !!_bSuppressMacros )
1416 if ( *_bSuppressMacros )
1418 // if we're to suppress macros, do exactly this
1419 _io_rArgs.put( "MacroExecutionMode", MacroExecMode::NEVER_EXECUTE );
1421 else
1423 // otherwise, put the setting only if not already present
1424 if ( !_io_rArgs.has( "MacroExecutionMode" ) )
1426 _io_rArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
1431 if ( !!_bReadOnly )
1432 _io_rArgs.put( "ReadOnly", *_bReadOnly );
1436 namespace
1438 Reference< XFrame > lcl_getDatabaseDocumentFrame( ODatabaseModelImpl& _rImpl )
1440 Reference< XModel > xDatabaseDocumentModel( _rImpl.getModel_noCreate() );
1442 Reference< XController > xDatabaseDocumentController;
1443 if ( xDatabaseDocumentModel.is() )
1444 xDatabaseDocumentController = xDatabaseDocumentModel->getCurrentController();
1446 Reference< XFrame > xFrame;
1447 if ( xDatabaseDocumentController.is() )
1448 xFrame = xDatabaseDocumentController->getFrame();
1450 return xFrame;
1454 bool ODocumentDefinition::objectSupportsEmbeddedScripts() const
1456 bool bAllowDocumentMacros = !m_pImpl->m_pDataSource
1457 || ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eSubDocumentMacros );
1459 // if *any* of the objects of the database document already has macros, we
1460 // continue to allow it to have them, until the user does a migration.
1461 // If there are no macros, we don't allow them to be created.
1463 return bAllowDocumentMacros;
1466 OUString ODocumentDefinition::determineContentType() const
1468 return lcl_determineContentType_nothrow( getContainerStorage(), m_pImpl->m_aProps.sPersistentName );
1471 void ODocumentDefinition::separateOpenCommandArguments( const Sequence< PropertyValue >& i_rOpenCommandArguments,
1472 ::comphelper::NamedValueCollection& o_rDocumentLoadArgs, ::comphelper::NamedValueCollection& o_rEmbeddedObjectDescriptor )
1474 ::comphelper::NamedValueCollection aOpenCommandArguments( i_rOpenCommandArguments );
1476 const sal_Char* pObjectDescriptorArgs[] =
1478 "RecoveryStorage"
1480 for ( size_t i=0; i < sizeof( pObjectDescriptorArgs ) / sizeof( pObjectDescriptorArgs[0] ); ++i )
1482 if ( aOpenCommandArguments.has( pObjectDescriptorArgs[i] ) )
1484 o_rEmbeddedObjectDescriptor.put( pObjectDescriptorArgs[i], aOpenCommandArguments.get( pObjectDescriptorArgs[i] ) );
1485 aOpenCommandArguments.remove( pObjectDescriptorArgs[i] );
1489 o_rDocumentLoadArgs.merge( aOpenCommandArguments, false );
1492 Sequence< PropertyValue > ODocumentDefinition::fillLoadArgs( const Reference< XConnection>& _xConnection, const bool _bSuppressMacros, const bool _bReadOnly,
1493 const Sequence< PropertyValue >& i_rOpenCommandArguments, Sequence< PropertyValue >& _out_rEmbeddedObjectDescriptor )
1495 // (re-)create interceptor, and put it into the descriptor of the embedded object
1496 if ( m_pInterceptor )
1498 m_pInterceptor->dispose();
1499 m_pInterceptor->release();
1500 m_pInterceptor = NULL;
1503 m_pInterceptor = new OInterceptor( this );
1504 m_pInterceptor->acquire();
1505 Reference<XDispatchProviderInterceptor> xInterceptor = m_pInterceptor;
1507 ::comphelper::NamedValueCollection aEmbeddedDescriptor;
1508 aEmbeddedDescriptor.put( "OutplaceDispatchInterceptor", xInterceptor );
1510 ::comphelper::NamedValueCollection aMediaDesc;
1511 separateOpenCommandArguments( i_rOpenCommandArguments, aMediaDesc, aEmbeddedDescriptor );
1513 // create the OutplaceFrameProperties, and put them into the descriptor of the embedded object
1514 ::comphelper::NamedValueCollection OutplaceFrameProperties;
1515 OutplaceFrameProperties.put( "TopWindow", true );
1516 OutplaceFrameProperties.put( "SupportPersistentWindowState", true );
1518 Reference< XFrame > xParentFrame;
1519 if ( m_pImpl->m_pDataSource )
1520 xParentFrame = lcl_getDatabaseDocumentFrame( *m_pImpl->m_pDataSource );
1521 if ( !xParentFrame.is() )
1522 { // i87957 we need a parent frame
1523 Reference< XDesktop2 > xDesktop = Desktop::create( m_aContext );
1524 xParentFrame.set( xDesktop, UNO_QUERY_THROW );
1525 Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
1526 if ( xCloseable.is() )
1528 xCloseable->addCloseListener(this);
1529 m_bRemoveListener = true;
1532 OSL_ENSURE( xParentFrame.is(), "ODocumentDefinition::fillLoadArgs: no parent frame!" );
1533 if ( xParentFrame.is() )
1534 OutplaceFrameProperties.put( "ParentFrame", xParentFrame );
1536 aEmbeddedDescriptor.put( "OutplaceFrameProperties", OutplaceFrameProperties.getNamedValues() );
1538 // tell the embedded object to have (or not have) script support
1539 aEmbeddedDescriptor.put( "EmbeddedScriptSupport", objectSupportsEmbeddedScripts() );
1541 // tell the embedded object to not participate in the document recovery game - the DB doc will handle it
1542 aEmbeddedDescriptor.put( "DocumentRecoverySupport", false );
1544 // pass the descriptor of the embedded object to the caller
1545 aEmbeddedDescriptor >>= _out_rEmbeddedObjectDescriptor;
1547 // create the ComponentData, and put it into the document's media descriptor
1549 ::comphelper::NamedValueCollection aComponentData;
1550 aComponentData.put( "ActiveConnection", _xConnection );
1551 aComponentData.put( "ApplyFormDesignMode", !_bReadOnly );
1552 aMediaDesc.put( "ComponentData", aComponentData.getPropertyValues() );
1555 if ( !m_pImpl->m_aProps.aTitle.isEmpty() )
1556 aMediaDesc.put( "DocumentTitle", m_pImpl->m_aProps.aTitle );
1558 aMediaDesc.put( "DocumentBaseURL", m_pImpl->m_pDataSource->getURL() );
1560 // put the common load arguments into the document's media descriptor
1561 lcl_putLoadArgs( aMediaDesc, optional_bool( _bSuppressMacros ), optional_bool( _bReadOnly ) );
1563 return aMediaDesc.getPropertyValues();
1566 void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& i_rConnection, const Sequence< sal_Int8 >& _aClassID,
1567 const Sequence< PropertyValue >& i_rOpenCommandArguments, const bool _bSuppressMacros, const bool _bReadOnly )
1569 if ( !m_xEmbeddedObject.is() )
1571 Reference< XStorage> xStorage = getContainerStorage();
1572 if ( xStorage.is() )
1574 Reference< XEmbeddedObjectCreator> xEmbedFactory = OOoEmbeddedObjectFactory::create(m_aContext);
1575 OUString sDocumentService;
1576 bool bSetSize = false;
1577 sal_Int32 nEntryConnectionMode = EntryInitModes::DEFAULT_INIT;
1578 Sequence< sal_Int8 > aClassID = _aClassID;
1579 if ( aClassID.getLength() )
1581 nEntryConnectionMode = EntryInitModes::TRUNCATE_INIT;
1582 bSetSize = true;
1584 else
1586 sDocumentService = GetDocumentServiceFromMediaType( getContentType(), m_aContext, aClassID );
1587 // check if we are not a form and
1588 // the org.libreoffice.report.pentaho.SOReportJobFactory is not present.
1589 if ( !m_bForm && !(sDocumentService == "com.sun.star.text.TextDocument"))
1591 // we seem to be a "new style" report, check if report extension is present.
1592 Reference< XContentEnumerationAccess > xEnumAccess( m_aContext->getServiceManager(), UNO_QUERY );
1593 const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_aContext);
1594 Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName);
1595 if ( !xEnumDrivers.is() || !xEnumDrivers->hasMoreElements() )
1597 com::sun::star::io::WrongFormatException aWFE;
1598 aWFE.Message = DBACORE_RESSTRING( RID_STR_MISSING_EXTENSION );
1599 throw aWFE;
1602 if ( !aClassID.getLength() )
1604 if ( m_bForm )
1605 aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_SW_CLASSID);
1606 else
1608 aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_RPT_CLASSID_90);
1613 OSL_ENSURE( aClassID.getLength(),"No Class ID" );
1615 Sequence< PropertyValue > aEmbeddedObjectDescriptor;
1616 Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
1617 i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
1619 m_xEmbeddedObject.set(xEmbedFactory->createInstanceUserInit(aClassID
1620 ,sDocumentService
1621 ,xStorage
1622 ,m_pImpl->m_aProps.sPersistentName
1623 ,nEntryConnectionMode
1624 ,aLoadArgs
1625 ,aEmbeddedObjectDescriptor
1626 ),UNO_QUERY);
1627 if ( m_xEmbeddedObject.is() )
1629 if ( !m_pClientHelper )
1631 m_pClientHelper = new OEmbeddedClientHelper(this);
1632 m_pClientHelper->acquire();
1634 Reference<XEmbeddedClient> xClient = m_pClientHelper;
1635 m_xEmbeddedObject->setClientSite(xClient);
1636 m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
1637 if ( bSetSize )
1639 LockModifiable aLockModify( impl_getComponent_throw( false ) );
1641 awt::Size aSize( DEFAULT_WIDTH, DEFAULT_HEIGHT );
1642 m_xEmbeddedObject->setVisualAreaSize(Aspects::MSOLE_CONTENT,aSize);
1647 else
1649 sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
1650 if ( nCurrentState == EmbedStates::LOADED )
1652 if ( !m_pClientHelper )
1654 m_pClientHelper = new OEmbeddedClientHelper(this);
1655 m_pClientHelper->acquire();
1657 Reference<XEmbeddedClient> xClient = m_pClientHelper;
1658 m_xEmbeddedObject->setClientSite(xClient);
1660 Sequence< PropertyValue > aEmbeddedObjectDescriptor;
1661 Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
1662 i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
1664 Reference<XCommonEmbedPersist> xCommon(m_xEmbeddedObject,UNO_QUERY);
1665 OSL_ENSURE(xCommon.is(),"unsupported interface!");
1666 if ( xCommon.is() )
1667 xCommon->reload( aLoadArgs, aEmbeddedObjectDescriptor );
1668 m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
1670 else
1672 OSL_ENSURE( ( nCurrentState == EmbedStates::RUNNING ) || ( nCurrentState == EmbedStates::ACTIVE ),
1673 "ODocumentDefinition::loadEmbeddedObject: unexpected state!" );
1675 // if the document was already loaded (which means the embedded object is in state RUNNING or ACTIVE),
1676 // then just re-set some model parameters
1679 // ensure the media descriptor doesn't contain any values which are intended for the
1680 // EmbeddedObjectDescriptor only
1681 ::comphelper::NamedValueCollection aEmbeddedObjectDescriptor;
1682 ::comphelper::NamedValueCollection aNewMediaDesc;
1683 separateOpenCommandArguments( i_rOpenCommandArguments, aNewMediaDesc, aEmbeddedObjectDescriptor );
1685 // merge the new media descriptor into the existing media descriptor
1686 const Reference< XModel > xModel( getComponent(), UNO_QUERY_THROW );
1687 const Sequence< PropertyValue > aArgs = xModel->getArgs();
1688 ::comphelper::NamedValueCollection aExistentMediaDesc( aArgs );
1689 aExistentMediaDesc.merge( aNewMediaDesc, false );
1691 lcl_putLoadArgs( aExistentMediaDesc, optional_bool(), optional_bool() );
1692 // don't put _bSuppressMacros and _bReadOnly here - if the document was already
1693 // loaded, we should not tamper with its settings.
1694 // #i88977# #i86872#
1696 xModel->attachResource( xModel->getURL(), aExistentMediaDesc.getPropertyValues() );
1698 catch( const Exception& )
1700 DBG_UNHANDLED_EXCEPTION();
1705 // set the OfficeDatabaseDocument instance as parent of the embedded document
1706 // #i40358#
1707 Reference< XChild > xDepdendDocAsChild( getComponent(), UNO_QUERY );
1708 if ( xDepdendDocAsChild.is() )
1712 if ( !xDepdendDocAsChild->getParent().is() )
1713 { // first encounter
1714 xDepdendDocAsChild->setParent( getDataSource( m_xParentContainer ) );
1717 catch( const Exception& )
1719 DBG_UNHANDLED_EXCEPTION();
1723 if ( i_rConnection.is() )
1724 m_xLastKnownConnection = i_rConnection;
1727 void ODocumentDefinition::onCommandPreview(Any& _rImage)
1729 loadEmbeddedObjectForPreview();
1730 if ( m_xEmbeddedObject.is() )
1734 Reference<XTransferable> xTransfer(getComponent(),UNO_QUERY);
1735 if ( xTransfer.is() )
1737 DataFlavor aFlavor;
1738 aFlavor.MimeType = "image/png";
1739 aFlavor.HumanPresentableName = "Portable Network Graphics";
1740 aFlavor.DataType = cppu::UnoType<Sequence < sal_Int8 >>::get();
1742 _rImage = xTransfer->getTransferData( aFlavor );
1745 catch( const Exception& )
1751 void ODocumentDefinition::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
1753 _rDefault.clear();
1756 void ODocumentDefinition::onCommandGetDocumentProperties( Any& _rProps )
1758 loadEmbeddedObjectForPreview();
1759 if ( m_xEmbeddedObject.is() )
1763 Reference<XDocumentPropertiesSupplier> xDocSup(
1764 getComponent(), UNO_QUERY );
1765 if ( xDocSup.is() )
1766 _rProps <<= xDocSup->getDocumentProperties();
1768 catch( const Exception& )
1770 DBG_UNHANDLED_EXCEPTION();
1775 Reference< util::XCloseable > ODocumentDefinition::impl_getComponent_throw( const bool i_ForceCreate )
1777 OSL_ENSURE(m_xEmbeddedObject.is(),"Illegal call for embeddedObject");
1778 Reference< util::XCloseable > xComp;
1779 if ( m_xEmbeddedObject.is() )
1781 int nState = m_xEmbeddedObject->getCurrentState();
1782 if ( ( nState == EmbedStates::LOADED ) && i_ForceCreate )
1784 m_xEmbeddedObject->changeState( EmbedStates::RUNNING );
1785 nState = m_xEmbeddedObject->getCurrentState();
1786 OSL_ENSURE( nState == EmbedStates::RUNNING, "ODocumentDefinition::impl_getComponent_throw: could not switch to RUNNING!" );
1789 if ( nState == EmbedStates::ACTIVE || nState == EmbedStates::RUNNING )
1791 Reference<XComponentSupplier> xCompProv(m_xEmbeddedObject,UNO_QUERY);
1792 if ( xCompProv.is() )
1794 xComp = xCompProv->getComponent();
1795 OSL_ENSURE(xComp.is(),"No valid component");
1799 return xComp;
1802 Reference< util::XCloseable > ODocumentDefinition::getComponent() throw (RuntimeException, std::exception)
1804 ::osl::MutexGuard aGuard( m_aMutex );
1805 return impl_getComponent_throw( true );
1808 namespace
1810 Reference< XDatabaseDocumentUI > lcl_getDatabaseDocumentUI( ODatabaseModelImpl& _rModelImpl )
1812 Reference< XDatabaseDocumentUI > xUI;
1814 Reference< XModel > xModel( _rModelImpl.getModel_noCreate() );
1815 if ( xModel.is() )
1816 xUI.set( xModel->getCurrentController(), UNO_QUERY );
1817 return xUI;
1821 Reference< XComponent > ODocumentDefinition::impl_openUI_nolck_throw( bool _bForEditing )
1823 ::osl::ClearableMutexGuard aGuard( m_aMutex );
1824 if ( !m_pImpl || !m_pImpl->m_pDataSource )
1825 throw DisposedException();
1827 Reference< XComponent > xComponent;
1830 Reference< XDatabaseDocumentUI > xUI( lcl_getDatabaseDocumentUI( *m_pImpl->m_pDataSource ) );
1831 if ( !xUI.is() )
1833 // no XDatabaseDocumentUI -> just execute the respective command
1834 m_bOpenInDesign = _bForEditing;
1835 xComponent = Reference<XComponent>(onCommandOpenSomething(Any(), true, NULL), UNO_QUERY);
1836 OSL_ENSURE( xComponent.is(), "ODocumentDefinition::impl_openUI_nolck_throw: opening the thingie failed." );
1837 return xComponent;
1841 OUString sName( impl_getHierarchicalName( false ) );
1842 sal_Int32 nObjectType = m_bForm ? DatabaseObject::FORM : DatabaseObject::REPORT;
1843 aGuard.clear();
1845 xComponent = xUI->loadComponent(
1846 nObjectType, sName, _bForEditing
1849 catch( const RuntimeException& ) { throw; }
1850 catch( const Exception& )
1852 throw WrappedTargetException(
1853 OUString(), *this, ::cppu::getCaughtException() );
1856 return xComponent;
1859 void ODocumentDefinition::impl_store_throw()
1861 Reference<XEmbedPersist> xPersist( m_xEmbeddedObject, UNO_QUERY );
1862 if ( xPersist.is() )
1864 xPersist->storeOwn();
1865 notifyDataSourceModified();
1869 bool ODocumentDefinition::impl_close_throw()
1871 bool bSuccess = prepareClose();
1872 if ( bSuccess && m_xEmbeddedObject.is() )
1874 m_xEmbeddedObject->changeState( EmbedStates::LOADED );
1875 bSuccess = m_xEmbeddedObject->getCurrentState() == EmbedStates::LOADED;
1877 return bSuccess;
1880 Reference< XComponent > SAL_CALL ODocumentDefinition::open( ) throw (WrappedTargetException, RuntimeException, std::exception)
1882 return impl_openUI_nolck_throw( false );
1885 Reference< XComponent > SAL_CALL ODocumentDefinition::openDesign( ) throw (WrappedTargetException, RuntimeException, std::exception)
1887 return impl_openUI_nolck_throw( true );
1890 void SAL_CALL ODocumentDefinition::store( ) throw (WrappedTargetException, RuntimeException, std::exception)
1892 ::osl::MutexGuard aGuard( m_aMutex );
1895 impl_store_throw();
1897 catch( const RuntimeException& ) { throw; }
1898 catch( const Exception& )
1900 throw WrappedTargetException(
1901 OUString(), *this, ::cppu::getCaughtException() );
1905 sal_Bool SAL_CALL ODocumentDefinition::close( ) throw (WrappedTargetException, RuntimeException, std::exception)
1907 ::osl::MutexGuard aGuard( m_aMutex );
1909 bool bSuccess = false;
1912 bSuccess = impl_close_throw();
1914 catch( const RuntimeException& ) { throw; }
1915 catch( const Exception& )
1917 throw WrappedTargetException(
1918 OUString(), *this, ::cppu::getCaughtException() );
1920 return bSuccess;
1923 OUString SAL_CALL ODocumentDefinition::getHierarchicalName() throw (RuntimeException, std::exception)
1925 ::osl::MutexGuard aGuard( m_aMutex );
1926 return impl_getHierarchicalName( false );
1929 OUString SAL_CALL ODocumentDefinition::composeHierarchicalName( const OUString& i_rRelativeName ) throw (IllegalArgumentException, NoSupportException, RuntimeException, std::exception)
1931 OUStringBuffer aBuffer;
1932 aBuffer.append( getHierarchicalName() );
1933 aBuffer.append( '/' );
1934 aBuffer.append( i_rRelativeName );
1935 return aBuffer.makeStringAndClear();
1938 void SAL_CALL ODocumentDefinition::rename( const OUString& _rNewName ) throw (SQLException, ElementExistException, RuntimeException, std::exception)
1942 ::osl::ResettableMutexGuard aGuard(m_aMutex);
1943 if ( _rNewName.equals( m_pImpl->m_aProps.aTitle ) )
1944 return;
1946 // document definitions are organized in a hierarchical way, so reject names
1947 // which contain a /, as this is reserved for hierarchy level separation
1948 if ( _rNewName.indexOf( '/' ) != -1 )
1949 m_aErrorHelper.raiseException( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES, *this );
1951 NameChangeNotifier aNameChangeAndNotify( *this, _rNewName, aGuard );
1952 m_pImpl->m_aProps.aTitle = _rNewName;
1954 if ( m_xEmbeddedObject.is() && m_xEmbeddedObject->getCurrentState() == EmbedStates::ACTIVE )
1955 updateDocumentTitle();
1957 catch(const PropertyVetoException&)
1959 throw ElementExistException(_rNewName,*this);
1963 Reference< XStorage> ODocumentDefinition::getContainerStorage() const
1965 return m_pImpl->m_pDataSource
1966 ? m_pImpl->m_pDataSource->getStorage( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT )
1967 : Reference< XStorage>();
1970 bool ODocumentDefinition::isModified()
1972 osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
1973 bool bRet = false;
1974 if ( m_xEmbeddedObject.is() )
1976 Reference<XModifiable> xModel(getComponent(),UNO_QUERY);
1977 bRet = xModel.is() && xModel->isModified();
1979 return bRet;
1982 bool ODocumentDefinition::prepareClose()
1984 if ( !m_xEmbeddedObject.is() )
1985 return true;
1989 // suspend the controller. Embedded objects are not allowed to raise
1990 // own UI at their own discretion, instead, this has always to be triggered
1991 // by the embedding component. Thus, we do the suspend call here.
1992 // #i49370#
1994 Reference< util::XCloseable > xComponent( impl_getComponent_throw( false ) );
1995 if ( !xComponent.is() )
1996 return true;
1998 Reference< XModel > xModel( xComponent, UNO_QUERY );
1999 Reference< XController > xController;
2000 if ( xModel.is() )
2001 xController = xModel->getCurrentController();
2003 OSL_ENSURE( xController.is() || ( m_xEmbeddedObject->getCurrentState() < EmbedStates::ACTIVE ),
2004 "ODocumentDefinition::prepareClose: no controller!" );
2005 if ( !xController.is() )
2006 // document has not yet been activated, i.e. has no UI, yet
2007 return true;
2009 bool bCouldSuspend = xController->suspend( sal_True );
2010 if ( !bCouldSuspend )
2011 // controller vetoed the closing
2012 return false;
2014 if ( isModified() )
2016 Reference< XFrame > xFrame( xController->getFrame() );
2017 if ( xFrame.is() )
2019 Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
2020 xTopWindow->toFront();
2022 if ( !save( true ) )
2024 if ( bCouldSuspend )
2025 // revert suspension
2026 xController->suspend( sal_False );
2027 // saving failed or was cancelled
2028 return false;
2032 catch( const Exception& )
2034 DBG_UNHANDLED_EXCEPTION();
2037 return true;
2040 void ODocumentDefinition::fillReportData( const Reference< XComponentContext >& _rContext,
2041 const Reference< util::XCloseable >& _rxComponent,
2042 const Reference< XConnection >& _rxActiveConnection )
2044 Sequence< Any > aArgs(2);
2045 PropertyValue aValue;
2046 aValue.Name = "TextDocument";
2047 aValue.Value <<= _rxComponent;
2048 aArgs[0] <<= aValue;
2049 aValue.Name = "ActiveConnection";
2050 aValue.Value <<= _rxActiveConnection;
2051 aArgs[1] <<= aValue;
2055 Reference< XJobExecutor > xExecuteable(
2056 _rContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.wizards.report.CallReportWizard", aArgs, _rContext), UNO_QUERY_THROW );
2057 xExecuteable->trigger( "fill" );
2059 catch( const Exception& )
2061 DBG_UNHANDLED_EXCEPTION();
2065 void ODocumentDefinition::updateDocumentTitle()
2067 OUString sName = m_pImpl->m_aProps.aTitle;
2068 if ( m_pImpl->m_pDataSource )
2070 if ( sName.isEmpty() )
2072 if ( m_bForm )
2073 sName = DBACORE_RESSTRING( RID_STR_FORM );
2074 else
2075 sName = DBACORE_RESSTRING( RID_STR_REPORT );
2076 Reference< XUntitledNumbers > xUntitledProvider(m_pImpl->m_pDataSource->getModel_noCreate(), UNO_QUERY );
2077 if ( xUntitledProvider.is() )
2078 sName += OUString::number( xUntitledProvider->leaseNumber(getComponent()) );
2081 Reference< XTitle > xDatabaseDocumentModel(m_pImpl->m_pDataSource->getModel_noCreate(),uno::UNO_QUERY);
2082 if ( xDatabaseDocumentModel.is() )
2083 sName = xDatabaseDocumentModel->getTitle() + " : " + sName;
2085 Reference< XTitle> xTitle(getComponent(),UNO_QUERY);
2086 if ( xTitle.is() )
2087 xTitle->setTitle(sName);
2090 void SAL_CALL ODocumentDefinition::queryClosing( const lang::EventObject& Source, sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException, std::exception)
2092 (void) Source;
2093 (void) GetsOwnership;
2096 if ( !close() )
2097 throw util::CloseVetoException();
2099 catch(const lang::WrappedTargetException&)
2101 throw util::CloseVetoException();
2105 void SAL_CALL ODocumentDefinition::notifyClosing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException, std::exception)
2109 void SAL_CALL ODocumentDefinition::disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException, std::exception)
2113 void ODocumentDefinition::firePropertyChange( sal_Int32 i_nHandle, const Any& i_rNewValue, const Any& i_rOldValue,
2114 bool i_bVetoable, const NotifierAccess& )
2116 fire( &i_nHandle, &i_rNewValue, &i_rOldValue, 1, i_bVetoable );
2119 // NameChangeNotifier
2120 NameChangeNotifier::NameChangeNotifier( ODocumentDefinition& i_rDocumentDefinition, const OUString& i_rNewName,
2121 ::osl::ResettableMutexGuard& i_rClearForNotify )
2122 :m_rDocumentDefinition( i_rDocumentDefinition )
2123 ,m_aOldValue( makeAny( i_rDocumentDefinition.getCurrentName() ) )
2124 ,m_aNewValue( makeAny( i_rNewName ) )
2125 ,m_rClearForNotify( i_rClearForNotify )
2127 impl_fireEvent_throw( true );
2130 NameChangeNotifier::~NameChangeNotifier()
2132 impl_fireEvent_throw( false );
2135 void NameChangeNotifier::impl_fireEvent_throw( const bool i_bVetoable )
2137 m_rClearForNotify.clear();
2138 m_rDocumentDefinition.firePropertyChange(
2139 PROPERTY_ID_NAME, m_aNewValue, m_aOldValue, i_bVetoable, ODocumentDefinition::NotifierAccess() );
2140 m_rClearForNotify.reset();
2143 } // namespace dbaccess
2145 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */