LibreOffice Module dbaccess (master) 1
documentdefinition.cxx
Go to the documentation of this file.
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
21#include <ModelImpl.hxx>
22#include <stringconstants.hxx>
23#include <sdbcoretools.hxx>
25#include <osl/diagnose.h>
32#include <comphelper/types.hxx>
33#include <com/sun/star/frame/XUntitledNumbers.hpp>
34#include <com/sun/star/awt/Size.hpp>
35#include <com/sun/star/lang/DisposedException.hpp>
36#include <com/sun/star/lang/XMultiServiceFactory.hpp>
37#include <com/sun/star/beans/PropertyAttribute.hpp>
38#include <com/sun/star/frame/Desktop.hpp>
39#include <com/sun/star/frame/XModel.hpp>
40#include <com/sun/star/frame/XTitle.hpp>
41#include <com/sun/star/frame/XController.hpp>
42#include <com/sun/star/task/XJobExecutor.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/WrongStateException.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>
51#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
52#include <com/sun/star/embed/ElementModes.hpp>
53#include <com/sun/star/embed/XEmbedPersist.hpp>
54#include <com/sun/star/embed/EmbedStates.hpp>
55#include <com/sun/star/embed/EntryInitModes.hpp>
56#include <com/sun/star/ucb/MissingPropertiesException.hpp>
57#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
58#include <com/sun/star/util/CloseVetoException.hpp>
59#include <com/sun/star/frame/XModule.hpp>
60#include <com/sun/star/datatransfer/DataFlavor.hpp>
61#include <com/sun/star/datatransfer/XTransferable.hpp>
62#include <com/sun/star/container/XNameContainer.hpp>
63#include <com/sun/star/embed/XCommonEmbedPersist.hpp>
64#include "intercept.hxx"
65#include <com/sun/star/sdb/ErrorCondition.hpp>
66#include <com/sun/star/sdb/XInteractionDocumentSave.hpp>
67#include <com/sun/star/task/InteractionHandler.hpp>
68#include <com/sun/star/sdb/DocumentSaveRequest.hpp>
69#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
70#include <com/sun/star/document/MacroExecMode.hpp>
71#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
72#include <com/sun/star/form/XFormsSupplier.hpp>
73#include <com/sun/star/form/XForm.hpp>
76#include <vcl/svapp.hxx>
77#include <osl/mutex.hxx>
78#include <com/sun/star/view/XViewSettingsSupplier.hpp>
79#include <core_resource.hxx>
80#include <strings.hrc>
81#include <strings.hxx>
82#include <com/sun/star/task/XInteractionApprove.hpp>
83#include <com/sun/star/task/XInteractionDisapprove.hpp>
84#include <com/sun/star/frame/XLayoutManager.hpp>
89#include <com/sun/star/container/XContentEnumerationAccess.hpp>
90#include <com/sun/star/io/WrongFormatException.hpp>
91#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
92#include <com/sun/star/sdb/application/DatabaseObject.hpp>
93#include <com/sun/star/util/XModifiable2.hpp>
94
95using namespace ::com::sun::star;
96using namespace view;
97using namespace uno;
98using namespace util;
99using namespace ucb;
100using namespace beans;
101using namespace lang;
102using namespace awt;
103using namespace embed;
104using namespace frame;
105using namespace document;
106using namespace sdbc;
107using namespace sdb;
108using namespace io;
109using namespace container;
110using namespace datatransfer;
111using namespace task;
112using namespace form;
113using namespace drawing;
114using namespace ::osl;
115using namespace ::comphelper;
116using namespace ::cppu;
117
118using sdb::application::XDatabaseDocumentUI;
119namespace DatabaseObject = sdb::application::DatabaseObject;
120
121#define DEFAULT_WIDTH 10000
122#define DEFAULT_HEIGHT 7500
123
124namespace dbaccess
125{
126
127 typedef ::std::optional< bool > optional_bool;
128
129 // helper
130 namespace
131 {
132 OUString lcl_determineContentType_nothrow( const Reference< XStorage >& _rxContainerStorage,
133 const OUString& _rEntityName )
134 {
135 OUString sContentType;
136 try
137 {
139 _rxContainerStorage->openStorageElement( _rEntityName, ElementModes::READ ), UNO_QUERY_THROW );
140 OSL_VERIFY( xStorageProps->getPropertyValue( INFO_MEDIATYPE ) >>= sContentType );
141 }
142 catch( const Exception& )
143 {
144 DBG_UNHANDLED_EXCEPTION("dbaccess");
145 }
146 return sContentType;
147 }
148 }
149
150 // OEmbedObjectHolder
151 typedef ::comphelper::WeakComponentImplHelper< embed::XStateChangeListener > TEmbedObjectHolder;
152
153 namespace {
154
155 class OEmbedObjectHolder : public TEmbedObjectHolder
156 {
157 Reference< XEmbeddedObject > m_xBroadCaster;
158 ODocumentDefinition* m_pDefinition;
160 protected:
161 virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
162 public:
163 OEmbedObjectHolder(const Reference< XEmbeddedObject >& _xBroadCaster,ODocumentDefinition* _pDefinition)
164 : m_xBroadCaster(_xBroadCaster)
165 ,m_pDefinition(_pDefinition)
166 ,m_bInStateChange(false)
167 {
168 osl_atomic_increment( &m_refCount );
169 {
170 if ( m_xBroadCaster.is() )
171 m_xBroadCaster->addStateChangeListener(this);
172 }
173 osl_atomic_decrement( &m_refCount );
174 }
175
176 virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
177 virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
178 virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
179 };
180
181 }
182
183 void OEmbedObjectHolder::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
184 {
185 if ( m_xBroadCaster.is() )
186 m_xBroadCaster->removeStateChangeListener(this);
187 m_xBroadCaster = nullptr;
188 m_pDefinition = nullptr;
189 }
190
191 void SAL_CALL OEmbedObjectHolder::changingState( const lang::EventObject& /*aEvent*/, ::sal_Int32 /*nOldState*/, ::sal_Int32 /*nNewState*/ )
192 {
193 }
194
195 void SAL_CALL OEmbedObjectHolder::stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
196 {
197 if ( !m_bInStateChange && nNewState == EmbedStates::RUNNING && nOldState == EmbedStates::ACTIVE && m_pDefinition )
198 {
199 m_bInStateChange = true;
200 Reference<XInterface> xHoldAlive(static_cast< ::cppu::OWeakObject* >(m_pDefinition),UNO_QUERY);
201 {
202 Reference<XEmbeddedObject> xEmbeddedObject(aEvent.Source,UNO_QUERY);
203 if ( xEmbeddedObject.is() )
204 xEmbeddedObject->changeState(EmbedStates::LOADED);
205 }
206 m_bInStateChange = false;
207 }
208 }
209
210 void SAL_CALL OEmbedObjectHolder::disposing( const lang::EventObject& /*Source*/ )
211 {
212 m_xBroadCaster = nullptr;
213 }
214
215 // OEmbeddedClientHelper
216 class OEmbeddedClientHelper : public ::cppu::WeakImplHelper<XEmbeddedClient>
217 {
218 public:
219 virtual void SAL_CALL saveObject( ) override
220 {
221 }
222 // XComponentSupplier
223 virtual Reference< util::XCloseable > SAL_CALL getComponent( ) override
224 {
225 return Reference< css::util::XCloseable >();
226 }
227
228 // XEmbeddedClient
229 virtual void SAL_CALL visibilityChanged( sal_Bool /*bVisible*/ ) override
230 {
231 }
232 };
233
234 namespace {
235
236 // LockModifiable
237 class LockModifiable
238 {
239 public:
240 explicit LockModifiable( const Reference< XInterface >& i_rModifiable )
241 :m_xModifiable( i_rModifiable, UNO_QUERY )
242 {
243 OSL_ENSURE( m_xModifiable.is(), "LockModifiable::LockModifiable: invalid component!" );
244 if ( m_xModifiable.is() )
245 {
246 if ( !m_xModifiable->isSetModifiedEnabled() )
247 {
248 // somebody already locked that, no need to lock it, again, and no need to unlock it later
249 m_xModifiable.clear();
250 }
251 else
252 {
253 m_xModifiable->disableSetModified();
254 }
255 }
256 }
257
258 ~LockModifiable()
259 {
260 if ( m_xModifiable.is() )
261 m_xModifiable->enableSetModified();
262 }
263
264 private:
265 Reference< XModifiable2 > m_xModifiable;
266 };
267
268 }
269
270 // LifetimeCoupler
271 typedef ::cppu::WeakImplHelper< css::lang::XEventListener
273
274 namespace {
275
287 class LifetimeCoupler : public LifetimeCoupler_Base
288 {
289 private:
290 Reference< XInterface > m_xClient;
291
292 public:
293 static void couple( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
294 {
295 new LifetimeCoupler( _rxClient, _rxActor );
296 }
297
298 private:
299 LifetimeCoupler( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor )
300 :m_xClient( _rxClient )
301 {
302 OSL_ENSURE( _rxActor.is(), "LifetimeCoupler::LifetimeCoupler: this will crash!" );
303 osl_atomic_increment( &m_refCount );
304 {
305 _rxActor->addEventListener( this );
306 }
307 osl_atomic_decrement( &m_refCount );
308 OSL_ENSURE( m_refCount, "LifetimeCoupler::LifetimeCoupler: the actor is not holding us by hard ref - this won't work!" );
309 }
310
311 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
312 protected:
313 };
314
315 }
316
317 void SAL_CALL LifetimeCoupler::disposing( const css::lang::EventObject& /*Source*/ )
318 {
319 m_xClient.clear();
320 }
321
322 namespace {
323
324 // ODocumentSaveContinuation
325 class ODocumentSaveContinuation : public OInteraction< XInteractionDocumentSave >
326 {
327 OUString m_sName;
328 Reference<XContent> m_xParentContainer;
329
330 public:
331 ODocumentSaveContinuation() { }
332
333 const Reference<XContent>& getContent() const { return m_xParentContainer; }
334 const OUString& getName() const { return m_sName; }
335
336 // XInteractionDocumentSave
337 virtual void SAL_CALL setName( const OUString& _sName,const Reference<XContent>& _xParent) override;
338 };
339
340 }
341
342 void SAL_CALL ODocumentSaveContinuation::setName( const OUString& _sName,const Reference<XContent>& _xParent)
343 {
344 m_sName = _sName;
345 m_xParentContainer = _xParent;
346 }
347
348OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const Reference< XStorage >& _rxContainerStorage,
349 const OUString& _rEntityName, const Reference< XComponentContext >& _rContext,
350 Sequence< sal_Int8 >& _rClassId )
351{
353 lcl_determineContentType_nothrow( _rxContainerStorage, _rEntityName ),
354 _rContext, _rClassId );
355}
356
357OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const OUString& _rMediaType,
358 const Reference< XComponentContext >& _rContext, Sequence< sal_Int8 >& _rClassId )
359{
360 OUString sResult;
361 try
362 {
363 ::comphelper::MimeConfigurationHelper aConfigHelper( _rContext );
364 sResult = aConfigHelper.GetDocServiceNameFromMediaType( _rMediaType );
365 _rClassId = comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(aConfigHelper.GetExplicitlyRegisteredObjClassID( _rMediaType ));
366 if ( !_rClassId.hasElements() && !sResult.isEmpty() )
367 {
368 Reference< XNameAccess > xObjConfig = aConfigHelper.GetObjConfiguration();
369 if ( xObjConfig.is() )
370 {
371 const Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
372 for ( OUString const & classId : aClassIDs )
373 {
374 Reference< XNameAccess > xObjectProps;
375 OUString aEntryDocName;
376
377 if ( ( xObjConfig->getByName( classId ) >>= xObjectProps ) && xObjectProps.is()
378 && ( xObjectProps->getByName("ObjectDocumentServiceName") >>= aEntryDocName )
379 && aEntryDocName == sResult )
380 {
382 break;
383 }
384 }
385 }
386 }
387#if OSL_DEBUG_LEVEL > 0
388 // alternative, shorter approach
389 const Sequence< NamedValue > aProps( aConfigHelper.GetObjectPropsByMediaType( _rMediaType ) );
390 const ::comphelper::NamedValueCollection aMediaTypeProps( aProps );
391 const OUString sAlternativeResult = aMediaTypeProps.getOrDefault( "ObjectDocumentServiceName", OUString() );
392 OSL_ENSURE( sAlternativeResult == sResult, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (1)!" );
393 const Sequence< sal_Int8 > aAlternativeClassID = aMediaTypeProps.getOrDefault( "ClassID", Sequence< sal_Int8 >() );
394 OSL_ENSURE( aAlternativeClassID == _rClassId, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (2)!" );
395#endif
396 }
397 catch ( const Exception& )
398 {
399 DBG_UNHANDLED_EXCEPTION("dbaccess");
400 }
401 return sResult;
402}
403
404// ODocumentDefinition
405
406ODocumentDefinition::ODocumentDefinition( const Reference< XInterface >& _rxContainer, const Reference< XComponentContext >& _xORB,
407 const TContentPtr& _pImpl, bool _bForm )
408 :OContentHelper(_xORB,_rxContainer,_pImpl)
410 ,m_bForm(_bForm)
411 ,m_bOpenInDesign(false)
412 ,m_bInExecute(false)
413 ,m_bRemoveListener(false)
414{
416}
417
418void ODocumentDefinition::initialLoad( const Sequence< sal_Int8 >& i_rClassID, const Sequence< PropertyValue >& i_rCreationArgs,
419 const Reference< XConnection >& i_rConnection )
420{
421 OSL_ENSURE( i_rClassID.hasElements(), "ODocumentDefinition::initialLoad: illegal class ID!" );
422 if ( !i_rClassID.hasElements() )
423 return;
424
425 loadEmbeddedObject( i_rConnection, i_rClassID, i_rCreationArgs, false, false );
426}
427
429{
430 if ( !OContentHelper::rBHelper.bInDispose && !OContentHelper::rBHelper.bDisposed )
431 {
432 acquire();
433 dispose();
434 }
435
436 if ( m_pInterceptor.is() )
437 {
438 m_pInterceptor->dispose();
439 m_pInterceptor.clear();
440 }
441}
442
444{
445 ::osl::MutexGuard aGuard(m_aMutex);
446 if ( m_xEmbeddedObject.is() )
447 {
448 try
449 {
450 m_xEmbeddedObject->close(true);
451 }
452 catch(const Exception&)
453 {
454 }
455 m_xEmbeddedObject = nullptr;
456 m_pClientHelper.clear();
457 }
458}
459
461{
463 ::osl::MutexGuard aGuard(m_aMutex);
464 closeObject();
465 ::comphelper::disposeComponent(m_xListener);
466 if ( m_bRemoveListener )
467 {
468 Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
469 if ( xCloseable.is() )
470 xCloseable->removeCloseListener(this);
471 }
472}
473
474css::uno::Sequence<sal_Int8> ODocumentDefinition::getImplementationId()
475{
476 return css::uno::Sequence<sal_Int8>();
477}
478
479css::uno::Sequence< css::uno::Type > ODocumentDefinition::getTypes()
480{
481 return ::comphelper::concatSequences(
482 OContentHelper::getTypes( ),
483 OPropertyStateContainer::getTypes( ),
485 );
486}
488
489void ODocumentDefinition::registerProperties()
490{
491 registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::CONSTRAINED | PropertyAttribute::BOUND | PropertyAttribute::READONLY,
492 &m_pImpl->m_aProps.aTitle, cppu::UnoType<decltype(m_pImpl->m_aProps.aTitle)>::get());
493
494 registerProperty(PROPERTY_AS_TEMPLATE, PROPERTY_ID_AS_TEMPLATE, PropertyAttribute::READONLY, &m_pImpl->m_aProps.bAsTemplate,
495 cppu::UnoType<decltype(m_pImpl->m_aProps.bAsTemplate)>::get());
496
497 registerProperty(PROPERTY_PERSISTENT_NAME, PROPERTY_ID_PERSISTENT_NAME, PropertyAttribute::READONLY, &m_pImpl->m_aProps.sPersistentName,
498 cppu::UnoType<decltype(m_pImpl->m_aProps.sPersistentName)>::get());
499
500 registerProperty(PROPERTY_IS_FORM, PROPERTY_ID_IS_FORM, PropertyAttribute::READONLY, &m_bForm, cppu::UnoType<decltype(m_bForm)>::get());
501}
502
503void SAL_CALL ODocumentDefinition::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const
504{
505 if ( i_nHandle == PROPERTY_ID_PERSISTENT_PATH )
506 {
507 OUString sPersistentPath;
508 if ( !m_pImpl->m_aProps.sPersistentName.isEmpty() )
509 {
511 + "/" + m_pImpl->m_aProps.sPersistentName;
512 }
513 o_rValue <<= sPersistentPath;
514 return;
515 }
516
518}
519
520Reference< XPropertySetInfo > SAL_CALL ODocumentDefinition::getPropertySetInfo( )
521{
522 Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
523 return xInfo;
524}
525
527{
528 return *getArrayHelper();
529}
530
531IPropertyArrayHelper* ODocumentDefinition::createArrayHelper( ) const
532{
533 // properties maintained by our base class (see registerProperties)
534 Sequence< Property > aProps;
535 describeProperties( aProps );
536
537 // properties not maintained by our base class
538 Sequence< Property > aManualProps{ { /* Name */ PROPERTY_PERSISTENT_PATH,
539 /* Handle */ PROPERTY_ID_PERSISTENT_PATH,
541 /* Attributes */ PropertyAttribute::READONLY } };
542
543 return new OPropertyArrayHelper( ::comphelper::concatSequences( aProps, aManualProps ) );
544}
545
546namespace {
547
548class OExecuteImpl
549{
550 bool& m_rbSet;
551public:
552 explicit OExecuteImpl(bool& _rbSet) : m_rbSet(_rbSet){ m_rbSet=true; }
553 ~OExecuteImpl(){ m_rbSet = false; }
554};
555
556 bool lcl_extractOpenMode( const Any& _rValue, sal_Int32& _out_rMode )
557 {
558 OpenCommandArgument aOpenCommand;
559 if ( _rValue >>= aOpenCommand )
560 _out_rMode = aOpenCommand.Mode;
561 else
562 {
563 OpenCommandArgument2 aOpenCommand2;
564 if ( _rValue >>= aOpenCommand2 )
565 _out_rMode = aOpenCommand2.Mode;
566 else
567 return false;
568 }
569 return true;
570 }
571}
572
573void ODocumentDefinition::impl_removeFrameFromDesktop_throw( const Reference<XComponentContext> & _rxContext, const Reference< XFrame >& _rxFrame )
574{
575 Reference< XDesktop2 > xDesktop = Desktop::create( _rxContext );
576 Reference< XFrames > xFrames( xDesktop->getFrames(), UNO_SET_THROW );
577 xFrames->remove( _rxFrame );
578}
579
581{
582 try
583 {
584 Reference< XModel > xModel( getComponent(), UNO_QUERY );
585 Reference< XController > xController( xModel.is() ? xModel->getCurrentController() : Reference< XController >() );
586 if ( !xController.is() )
587 return;
588
589 if ( !m_xListener.is() )
590 // it's the first time the embedded object has been activated
591 // create an OEmbedObjectHolder
592 m_xListener = new OEmbedObjectHolder( m_xEmbeddedObject, this );
593
594 // raise the window to top (especially necessary if this is not the first activation)
595 Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW );
596 Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW );
597 xTopWindow->toFront();
598
599 // remove the frame from the desktop's frame collection because we need full control of it.
601
602 // ensure that we ourself are kept alive as long as the embedded object's frame is
603 // opened
604 LifetimeCoupler::couple( *this, xFrame );
605
606 // init the edit view
607 if ( m_bForm && m_bOpenInDesign && !i_bReactivated )
609 }
610 catch( const RuntimeException& )
611 {
612 DBG_UNHANDLED_EXCEPTION("dbaccess");
613 }
614}
615
616namespace
617{
618 // PreserveVisualAreaSize
621 class PreserveVisualAreaSize
622 {
623 private:
624 Reference< XVisualObject > m_xVisObject;
626
627 public:
628 explicit PreserveVisualAreaSize( const Reference< XModel >& _rxModel )
629 :m_xVisObject( _rxModel, UNO_QUERY )
630 {
631 if ( m_xVisObject.is() )
632 {
633 try
634 {
635 m_aOriginalSize = m_xVisObject->getVisualAreaSize( Aspects::MSOLE_CONTENT );
636 }
637 catch ( const Exception& )
638 {
639 TOOLS_WARN_EXCEPTION( "dbaccess", "PreserveVisualAreaSize::PreserveVisualAreaSize" );
640 }
641 }
642 }
643
644 ~PreserveVisualAreaSize()
645 {
646 if ( m_xVisObject.is() && m_aOriginalSize.Width && m_aOriginalSize.Height )
647 {
648 try
649 {
650 m_xVisObject->setVisualAreaSize( Aspects::MSOLE_CONTENT, m_aOriginalSize );
651 }
652 catch ( const Exception& )
653 {
654 TOOLS_WARN_EXCEPTION( "dbaccess", "PreserveVisualAreaSize::~PreserveVisualAreaSize" );
655 }
656 }
657 }
658 };
659
660 // LayoutManagerLock
663 class LayoutManagerLock
664 {
665 private:
666 Reference< XLayoutManager > m_xLayoutManager;
667
668 public:
669 explicit LayoutManagerLock( const Reference< XController >& _rxController )
670 {
671 OSL_ENSURE( _rxController.is(), "LayoutManagerLock::LayoutManagerLock: this will crash!" );
672 Reference< XFrame > xFrame( _rxController->getFrame() );
673 try
674 {
675 Reference< XPropertySet > xPropSet( xFrame, UNO_QUERY_THROW );
677 xPropSet->getPropertyValue( "LayoutManager" ),
678 UNO_QUERY_THROW );
679 m_xLayoutManager->lock();
680
681 }
682 catch( const Exception& )
683 {
684 TOOLS_WARN_EXCEPTION( "dbaccess", "LayoutManagerLock::LayoutManagerLock" );
685 }
686 }
687
688 ~LayoutManagerLock()
689 {
690 try
691 {
692 // unlock the layout manager
693 if ( m_xLayoutManager.is() )
694 m_xLayoutManager->unlock();
695 }
696 catch( const Exception& )
697 {
698 TOOLS_WARN_EXCEPTION( "dbaccess", "LayoutManagerLock::~LayoutManagerLock" );
699 }
700 }
701 };
702}
703
704void ODocumentDefinition::impl_initFormEditView( const Reference< XController >& _rxController )
705{
706 try
707 {
708 Reference< XViewSettingsSupplier > xSettingsSupplier( _rxController, UNO_QUERY_THROW );
709 Reference< XPropertySet > xViewSettings( xSettingsSupplier->getViewSettings(), UNO_SET_THROW );
710
711 // the below code could indirectly tamper with the "modified" flag of the model, temporarily disable this
712 LockModifiable aLockModify( _rxController->getModel() );
713
714 // The visual area size can be changed by the setting of the following properties
715 // so it should be restored later
716 PreserveVisualAreaSize aPreserveVisAreaSize( _rxController->getModel() );
717
718 // Layout manager should not layout while the size is still not restored
719 // so it will stay locked for this time
720 LayoutManagerLock aLockLayout( _rxController );
721
722 // setting of the visual properties
723 xViewSettings->setPropertyValue("ShowRulers",Any(true));
724 xViewSettings->setPropertyValue("ShowVertRuler",Any(true));
725 xViewSettings->setPropertyValue("ShowHoriRuler",Any(true));
726 xViewSettings->setPropertyValue("IsRasterVisible",Any(true));
727 xViewSettings->setPropertyValue("IsSnapToRaster",Any(true));
728 xViewSettings->setPropertyValue("ShowOnlineLayout",Any(true));
729 xViewSettings->setPropertyValue("RasterSubdivisionX",Any(sal_Int32(5)));
730 xViewSettings->setPropertyValue("RasterSubdivisionY",Any(sal_Int32(5)));
731 }
732 catch( const Exception& )
733 {
734 DBG_UNHANDLED_EXCEPTION("dbaccess");
735 }
736}
737
739{
740 const sal_Int32 nCurrentState = m_xEmbeddedObject.is() ? m_xEmbeddedObject->getCurrentState() : EmbedStates::LOADED;
741 switch ( nCurrentState )
742 {
743 default:
744 case EmbedStates::LOADED:
745 throw embed::WrongStateException( OUString(), *this );
746
747 case EmbedStates::RUNNING:
748 if ( !i_bShow )
749 // fine, a running (and not yet active) object is never visible
750 return;
751 {
752 LockModifiable aLockModify( impl_getComponent_throw() );
753 m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
755 }
756 break;
757
758 case EmbedStates::ACTIVE:
759 {
760 Reference< XModel > xEmbeddedDoc( impl_getComponent_throw(), UNO_QUERY_THROW );
761 Reference< XController > xEmbeddedController( xEmbeddedDoc->getCurrentController(), UNO_SET_THROW );
762 Reference< XFrame > xEmbeddedFrame( xEmbeddedController->getFrame(), UNO_SET_THROW );
763 Reference< XWindow > xEmbeddedWindow( xEmbeddedFrame->getContainerWindow(), UNO_SET_THROW );
764 xEmbeddedWindow->setVisible( i_bShow );
765 }
766 break;
767 }
768}
769
770Any ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, const bool _bActivate,
771 const Reference< XCommandEnvironment >& _rxEnvironment )
772{
773 OExecuteImpl aExecuteGuard( m_bInExecute );
774
775 Reference< XConnection > xConnection;
776 sal_Int32 nOpenMode = OpenMode::DOCUMENT;
777
779
780 // for the document, default to the interaction handler as used for loading the DB doc
781 // This might be overwritten below, when examining _rOpenArgument.
782 const ::comphelper::NamedValueCollection& aDBDocArgs( m_pImpl->m_pDataSource->getMediaDescriptor() );
783 Reference< XInteractionHandler > xHandler( aDBDocArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
784 if ( xHandler.is() )
785 aDocumentArgs.put( "InteractionHandler", xHandler );
786
787 ::std::optional< sal_Int16 > aDocumentMacroMode;
788
789 if ( !lcl_extractOpenMode( _rOpenArgument, nOpenMode ) )
790 {
791 Sequence< PropertyValue > aArguments;
792 if ( _rOpenArgument >>= aArguments )
793 {
794 const PropertyValue* pIter = aArguments.getConstArray();
795 const PropertyValue* pEnd = pIter + aArguments.getLength();
796 for ( ;pIter != pEnd; ++pIter )
797 {
798 if ( pIter->Name == PROPERTY_ACTIVE_CONNECTION )
799 {
800 xConnection.set( pIter->Value, UNO_QUERY );
801 continue;
802 }
803
804 if ( lcl_extractOpenMode( pIter->Value, nOpenMode ) )
805 continue;
806
807 if ( pIter->Name == "MacroExecutionMode" )
808 {
809 sal_Int16 nMacroExecMode( !aDocumentMacroMode ? MacroExecMode::USE_CONFIG : *aDocumentMacroMode );
810 OSL_VERIFY( pIter->Value >>= nMacroExecMode );
811 aDocumentMacroMode = nMacroExecMode;
812 continue;
813 }
814
815 // unknown argument -> pass to the loaded document
816 aDocumentArgs.put( pIter->Name, pIter->Value );
817 }
818 }
819 }
820
821 bool bExecuteDBDocMacros = m_pImpl->m_pDataSource->checkMacrosOnLoading();
822 // Note that this call implies the user might be asked for the macro execution mode.
823 // Normally, this would happen when the database document is loaded, and subsequent calls
824 // will simply use the user's decision from this point in time.
825 // However, it is possible to programmatically load forms/reports, without actually
826 // loading the database document into a frame. In this case, the user will be asked
827 // here and now.
828 // #i87741#
829
830 // allow the command arguments to downgrade the macro execution mode, but not to upgrade
831 // it
832 if ( ( m_pImpl->m_pDataSource->getImposedMacroExecMode() == MacroExecMode::USE_CONFIG )
833 && bExecuteDBDocMacros
834 )
835 {
836 // while loading the whole database document, USE_CONFIG, was passed.
837 // Additionally, *by now* executing macros from the DB doc is allowed (this is what bExecuteDBDocMacros
838 // indicates). This means either one of:
839 // 1. The DB doc or one of the sub docs contained macros and
840 // 1a. the user explicitly allowed executing them
841 // 1b. the configuration allows executing them without asking the user
842 // 2. Neither the DB doc nor the sub docs contained macros, thus macro
843 // execution was silently enabled, assuming that any macro will be a
844 // user-created macro
845 //
846 // The problem with this: If the to-be-opened sub document has macros embedded in
847 // the content.xml (which is valid ODF, but normally not produced by OOo itself),
848 // then this has not been detected while loading the database document - it would
849 // be too expensive, as it effectively would require loading all forms/reports.
850 //
851 // So, in such a case, and with 2. above, we would silently execute those macros,
852 // regardless of the global security settings - which would be a security issue, of
853 // course.
854 if ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::EmbeddedMacros::NONE )
855 {
856 // this is case 2. from above
857 // So, pass a USE_CONFIG to the to-be-loaded document. This means that
858 // the user will be prompted with a security message upon opening this
859 // sub document, in case the settings require this, *and* the document
860 // contains scripts in the content.xml. But this is better than the security
861 // issue we had before ...
862 aDocumentMacroMode = MacroExecMode::USE_CONFIG;
863 }
864 }
865
866 if ( !aDocumentMacroMode )
867 {
868 // nobody so far felt responsible for setting it
869 // => use the DBDoc-wide macro exec mode for the document, too
870 aDocumentMacroMode = bExecuteDBDocMacros ? MacroExecMode::ALWAYS_EXECUTE_NO_WARN
871 : MacroExecMode::NEVER_EXECUTE;
872 }
873 aDocumentArgs.put( "MacroExecutionMode", *aDocumentMacroMode );
874
875 if ( ( nOpenMode == OpenMode::ALL )
876 || ( nOpenMode == OpenMode::FOLDERS )
877 || ( nOpenMode == OpenMode::DOCUMENTS )
878 || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_NONE )
879 || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_WRITE )
880 )
881 {
882 // not supported
884 Any( UnsupportedOpenModeException(
885 OUString(),
886 static_cast< cppu::OWeakObject * >( this ),
887 sal_Int16( nOpenMode ) ) ),
888 _rxEnvironment );
889 // Unreachable
890 OSL_FAIL( "unreachable" );
891 }
892
893 OSL_ENSURE( !m_pImpl->m_aProps.sPersistentName.isEmpty(),
894 "ODocumentDefinition::onCommandOpenSomething: no persistent name - cannot load!" );
895 if ( m_pImpl->m_aProps.sPersistentName.isEmpty() )
896 return Any();
897
898 // embedded objects themself do not support the hidden flag. We implement support for
899 // it by changing the STATE to RUNNING only, instead of ACTIVE.
900 bool bOpenHidden = aDocumentArgs.getOrDefault( "Hidden", false );
901 aDocumentArgs.remove( "Hidden" );
902
903 loadEmbeddedObject( xConnection, Sequence< sal_Int8 >(), aDocumentArgs.getPropertyValues(), false, !m_bOpenInDesign );
904 OSL_ENSURE( m_xEmbeddedObject.is(), "ODocumentDefinition::onCommandOpenSomething: what's this?" );
905 if ( !m_xEmbeddedObject.is() )
906 return Any();
907
908 Reference< XModel > xModel( getComponent(), UNO_QUERY );
909 Reference< report::XReportDefinition > xReportDefinition(xModel,UNO_QUERY);
910
911 Reference< XModule > xModule( xModel, UNO_QUERY );
912 if ( xModule.is() )
913 {
914 if ( m_bForm )
915 xModule->setIdentifier( "com.sun.star.sdb.FormDesign" );
916 else if ( !xReportDefinition.is() )
917 xModule->setIdentifier( "com.sun.star.text.TextDocument" );
918
920 }
921
922 bool bIsAliveNewStyleReport = ( !m_bOpenInDesign && xReportDefinition.is() );
923 if ( bIsAliveNewStyleReport )
924 {
925 // we are in ReadOnly mode
926 // we would like to open the Writer or Calc with the report direct, without design it.
927 Reference< report::XReportEngine > xReportEngine( m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.report.OReportEngineJFree", m_aContext), UNO_QUERY_THROW );
928
929 xReportEngine->setReportDefinition(xReportDefinition);
930 xReportEngine->setActiveConnection(m_xLastKnownConnection);
931 if ( bOpenHidden )
932 return Any( xReportEngine->createDocumentModel() );
933 return Any( xReportEngine->createDocumentAlive( nullptr ) );
934 }
935
936 if ( _bActivate && !bOpenHidden )
937 {
938 LockModifiable aLockModify( impl_getComponent_throw() );
939 m_xEmbeddedObject->changeState( EmbedStates::ACTIVE );
941 }
942 else
943 {
944 // ensure that we ourself are kept alive as long as the document is open
945 LifetimeCoupler::couple( *this, xModel );
946 }
947
948 if ( !m_bForm && m_pImpl->m_aProps.bAsTemplate && !m_bOpenInDesign )
950
951 return Any( xModel );
952}
953
954Any SAL_CALL ODocumentDefinition::execute( const Command& aCommand, sal_Int32 CommandId, const Reference< XCommandEnvironment >& Environment )
955{
956 Any aRet;
957
958 bool bOpen = aCommand.Name == "open";
959 bool bOpenInDesign = aCommand.Name == "openDesign";
960 bool bOpenForMail = aCommand.Name == "openForMail";
961 if ( bOpen || bOpenInDesign || bOpenForMail )
962 {
963 // opening the document involves a lot of VCL code, which is not thread-safe, but needs the SolarMutex locked.
964 // Unfortunately, the DocumentDefinition, as well as the EmbeddedObject implementation, calls into VCL-dependent
965 // components *without* releasing the own mutex, which is a guaranteed recipe for deadlocks.
966 // We have control over this implementation here, and in modifying it to release the own mutex before calling into
967 // the VCL-dependent components is not too difficult (was there, seen it).
968 // However, we do /not/ have control over the EmbeddedObject implementation, and from a first look, it seems as
969 // making it release the own mutex before calling SolarMutex-code is ... difficult, at least.
970 // So, to be on the same side, we lock the SolarMutex here. Yes, it sucks.
971 ::SolarMutexGuard aSolarGuard;
972 osl::MutexGuard aGuard(m_aMutex);
973 if ( m_bInExecute )
974 return aRet;
975
976 bool bActivateObject = true;
977 if ( bOpenForMail )
978 {
979 OSL_FAIL( "ODocumentDefinition::execute: 'openForMail' should not be used anymore - use the 'Hidden' parameter instead!" );
980 bActivateObject = false;
981 }
982
983 // if the object is already opened, do nothing
984 if ( m_xEmbeddedObject.is() )
985 {
986 sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
987 bool bIsActive = ( nCurrentState == EmbedStates::ACTIVE );
988
989 if ( bIsActive )
990 {
991 // exception: new-style reports always create a new document when "open" is executed
992 Reference< report::XReportDefinition > xReportDefinition( impl_getComponent_throw( false ), UNO_QUERY );
993 bool bIsAliveNewStyleReport = ( xReportDefinition.is() && ( bOpen || bOpenForMail ) );
994
995 if ( !bIsAliveNewStyleReport )
996 {
998 return Any( getComponent() );
999 }
1000 }
1001 }
1002
1003 m_bOpenInDesign = bOpenInDesign || bOpenForMail;
1004 return onCommandOpenSomething( aCommand.Argument, bActivateObject, Environment );
1005 }
1006
1007 osl::MutexGuard aGuard(m_aMutex);
1008 if ( m_bInExecute )
1009 return aRet;
1010
1011 if ( aCommand.Name == "copyTo" )
1012 {
1013 Sequence<Any> aIni;
1014 aCommand.Argument >>= aIni;
1015 if ( aIni.getLength() != 2 )
1016 {
1017 OSL_FAIL( "Wrong argument type!" );
1019 Any( IllegalArgumentException(
1020 OUString(),
1021 static_cast< cppu::OWeakObject * >( this ),
1022 -1 ) ),
1023 Environment );
1024 // Unreachable
1025 }
1026 Reference< XStorage> xDest(aIni[0],UNO_QUERY);
1027 OUString sPersistentName;
1028 aIni[1] >>= sPersistentName;
1029 Reference< XStorage> xStorage = getContainerStorage();
1030
1031 xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xDest,sPersistentName);
1032 }
1033 else if ( aCommand.Name == "preview" )
1034 {
1035 onCommandPreview(aRet);
1036 }
1037 else if ( aCommand.Name == "insert" )
1038 {
1039 Sequence<Any> aIni;
1040 aCommand.Argument >>= aIni;
1041 if ( !aIni.hasElements() )
1042 {
1043 OSL_FAIL( "Wrong argument count!" );
1045 Any( IllegalArgumentException(
1046 OUString(),
1047 static_cast< cppu::OWeakObject * >( this ),
1048 -1 ) ),
1049 Environment );
1050 // Unreachable
1051 }
1052 OUString sURL;
1053 aIni[0] >>= sURL;
1055 }
1056 else if ( aCommand.Name == "getdocumentinfo" // compatibility
1057 || aCommand.Name == "getDocumentInfo" )
1058 {
1060 }
1061 else if ( aCommand.Name == "delete" )
1062 {
1063 // delete
1064 closeObject();
1065 Reference< XStorage> xStorage = getContainerStorage();
1066 if ( xStorage.is() )
1067 xStorage->removeElement(m_pImpl->m_aProps.sPersistentName);
1068
1069 dispose();
1070
1071 }
1072 else if ( aCommand.Name == "storeOwn" // compatibility
1073 || aCommand.Name == "store"
1074 )
1075 {
1077 }
1078 else if ( aCommand.Name == "shutdown" // compatibility
1079 || aCommand.Name == "close"
1080 )
1081 {
1082 aRet <<= impl_close_throw();
1083 }
1084 else if ( aCommand.Name == "show" )
1085 {
1087 }
1088 else if ( aCommand.Name == "hide" )
1089 {
1091 }
1092 else
1093 {
1095 }
1096
1097 return aRet;
1098}
1099
1100namespace
1101{
1102 void lcl_resetChildFormsToEmptyDataSource( const Reference< XIndexAccess>& _rxFormsContainer )
1103 {
1104 OSL_PRECOND( _rxFormsContainer.is(), "lcl_resetChildFormsToEmptyDataSource: illegal call!" );
1105 sal_Int32 count = _rxFormsContainer->getCount();
1106 for ( sal_Int32 i = 0; i < count; ++i )
1107 {
1108 Reference< XForm > xForm( _rxFormsContainer->getByIndex( i ), UNO_QUERY );
1109 if ( !xForm.is() )
1110 continue;
1111
1112 // if the element is a form, reset its DataSourceName property to an empty string
1113 try
1114 {
1115 Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
1116 xFormProps->setPropertyValue( PROPERTY_DATASOURCENAME, Any( OUString() ) );
1117 }
1118 catch( const Exception& )
1119 {
1120 DBG_UNHANDLED_EXCEPTION("dbaccess");
1121 }
1122
1123 // if the element is a container itself, step down the component hierarchy
1124 Reference< XIndexAccess > xContainer( xForm, UNO_QUERY );
1125 if ( xContainer.is() )
1126 lcl_resetChildFormsToEmptyDataSource( xContainer );
1127 }
1128 }
1129
1130 void lcl_resetFormsToEmptyDataSource( const Reference< XEmbeddedObject>& _rxEmbeddedObject )
1131 {
1132 try
1133 {
1134 Reference< XDrawPageSupplier > xSuppPage( _rxEmbeddedObject->getComponent(), UNO_QUERY_THROW );
1135 // if this interface does not exist, then either getComponent returned NULL,
1136 // or the document is a multi-page document. The latter is allowed, but currently
1137 // simply not handled by this code, as it would not normally happen.
1138
1139 Reference< XFormsSupplier > xSuppForms( xSuppPage->getDrawPage(), UNO_QUERY_THROW );
1140 Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW );
1141 lcl_resetChildFormsToEmptyDataSource( xForms );
1142 }
1143 catch( const Exception& )
1144 {
1145 DBG_UNHANDLED_EXCEPTION("dbaccess");
1146 }
1147
1148 }
1149}
1150
1151void ODocumentDefinition::onCommandInsert( const OUString& _sURL, const Reference< XCommandEnvironment >& Environment )
1152{
1153 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1154
1155 // Check, if all required properties were set.
1156 if ( _sURL.isEmpty() || m_xEmbeddedObject.is() )
1157 {
1158 OSL_FAIL( "Content::onCommandInsert - property value missing!" );
1159
1160 Sequence<OUString> aProps { PROPERTY_URL };
1162 Any( MissingPropertiesException(
1163 OUString(),
1164 static_cast< cppu::OWeakObject * >( this ),
1165 aProps ) ),
1166 Environment );
1167 // Unreachable
1168 }
1169
1170 if ( !m_xEmbeddedObject.is() )
1171 {
1172 Reference< XStorage> xStorage = getContainerStorage();
1173 if ( xStorage.is() )
1174 {
1175 Reference< XEmbeddedObjectCreator> xEmbedFactory = EmbeddedObjectCreator::create(m_aContext);
1176 Sequence<PropertyValue> aEmpty;
1177 Sequence<PropertyValue> aMediaDesc{ comphelper::makePropertyValue(PROPERTY_URL,
1178 _sURL) };
1179 m_xEmbeddedObject.set(xEmbedFactory->createInstanceInitFromMediaDescriptor( xStorage
1180 ,m_pImpl->m_aProps.sPersistentName
1181 ,aMediaDesc
1182 ,aEmpty),UNO_QUERY);
1183
1184 lcl_resetFormsToEmptyDataSource( m_xEmbeddedObject );
1185 // #i57669#
1186
1187 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1188 if ( xPersist.is() )
1189 {
1190 xPersist->storeOwn();
1191 }
1192 try
1193 {
1194 if ( m_xEmbeddedObject.is() )
1195 m_xEmbeddedObject->close(true);
1196 }
1197 catch(const Exception&)
1198 {
1199 }
1200 m_xEmbeddedObject = nullptr;
1201 }
1202 }
1203
1204 aGuard.clear();
1205}
1206
1207bool ODocumentDefinition::save(bool _bApprove, const css::uno::Reference<css::awt::XTopWindow>& rDialogParent)
1208{
1209 // default handling: instantiate an interaction handler and let it handle the parameter request
1210 if ( !m_bOpenInDesign )
1211 return false;
1212 try
1213 {
1214
1215 {
1216 ::SolarMutexGuard aSolarGuard;
1217
1218 // the request
1219 Reference<XNameAccess> xName(m_xParentContainer,UNO_QUERY);
1220 DocumentSaveRequest aRequest;
1221 aRequest.Name = m_pImpl->m_aProps.aTitle;
1222 if ( aRequest.Name.isEmpty() )
1223 {
1224 if ( m_bForm )
1225 aRequest.Name = DBA_RES( RID_STR_FORM );
1226 else
1227 aRequest.Name = DBA_RES( RID_STR_REPORT );
1228 aRequest.Name = ::dbtools::createUniqueName(xName,aRequest.Name);
1229 }
1230
1231 aRequest.Content.set(m_xParentContainer,UNO_QUERY);
1233 // some knittings
1234 // two continuations allowed: OK and Cancel
1236
1237 if ( m_pImpl->m_aProps.aTitle.isEmpty() )
1238 {
1239 pDocuSave = new ODocumentSaveContinuation;
1240 pRequest->addContinuation(pDocuSave);
1241 }
1242 if ( _bApprove )
1243 {
1245 pRequest->addContinuation(pApprove);
1246 }
1247
1249 pRequest->addContinuation(pDisApprove);
1250
1252 pRequest->addContinuation(pAbort);
1253
1254 Reference<XWindow> xDialogParent(rDialogParent, UNO_QUERY);
1255
1256 // create the handler, let it handle the request
1257 Reference<XInteractionHandler2> xHandler(InteractionHandler::createWithParent(m_aContext, xDialogParent));
1258 xHandler->handle(pRequest);
1259
1260 if ( pAbort->wasSelected() )
1261 return false;
1262 if ( pDisApprove->wasSelected() )
1263 return true;
1264 if ( pDocuSave && pDocuSave->wasSelected() )
1265 {
1266 Reference<XNameContainer> xNC( pDocuSave->getContent(), UNO_QUERY_THROW );
1267
1268 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1269 NameChangeNotifier aNameChangeAndNotify( *this, pDocuSave->getName(), aGuard );
1270 m_pImpl->m_aProps.aTitle = pDocuSave->getName();
1271
1272 Reference< XContent> xContent = this;
1273 xNC->insertByName(pDocuSave->getName(),Any(xContent));
1274
1276 }
1277 }
1278
1279 ::osl::MutexGuard aGuard(m_aMutex);
1280 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1281 if ( xPersist.is() )
1282 {
1283 xPersist->storeOwn();
1285 }
1286 }
1287 catch(const Exception&)
1288 {
1289 TOOLS_WARN_EXCEPTION( "dbaccess", "ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
1290 }
1291 return true;
1292}
1293
1295{
1296 // default handling: instantiate an interaction handler and let it handle the parameter request
1297 if ( !m_bOpenInDesign )
1298 return;
1299
1300 {
1301 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1302 if ( m_pImpl->m_aProps.aTitle.isEmpty() )
1303 {
1304 aGuard.clear();
1305 save(false, css::uno::Reference<css::awt::XTopWindow>()); // (sal_False) : we don't want an approve dialog
1306 return;
1307 }
1308 }
1309 try
1310 {
1311 ::SolarMutexGuard aSolarGuard;
1312
1313 // the request
1314 DocumentSaveRequest aRequest;
1315 aRequest.Name = m_pImpl->m_aProps.aTitle;
1316
1317 aRequest.Content.set(m_xParentContainer,UNO_QUERY);
1319 // some knittings
1320 // two continuations allowed: OK and Cancel
1321 rtl::Reference<ODocumentSaveContinuation> pDocuSave = new ODocumentSaveContinuation;
1322 pRequest->addContinuation(pDocuSave);
1324 pRequest->addContinuation(pDisApprove);
1326 pRequest->addContinuation(pAbort);
1327
1328 // create the handler, let it handle the request
1329 Reference< XInteractionHandler2 > xHandler( InteractionHandler::createWithParent(m_aContext, nullptr) );
1330 xHandler->handle(pRequest);
1331
1332 if ( pAbort->wasSelected() )
1333 return;
1334 if ( pDisApprove->wasSelected() )
1335 return;
1336 if ( pDocuSave->wasSelected() )
1337 {
1338 ::osl::MutexGuard aGuard(m_aMutex);
1339 Reference<XNameContainer> xNC(pDocuSave->getContent(),UNO_QUERY);
1340 if ( xNC.is() )
1341 {
1342 if ( m_pImpl->m_aProps.aTitle != pDocuSave->getName() )
1343 {
1344 try
1345 {
1346 Reference< XStorage> xStorage = getContainerStorage();
1347
1348 OUString sPersistentName = ::dbtools::createUniqueName(xStorage,"Obj");
1349 xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xStorage,sPersistentName);
1350
1351 OUString sOldName = m_pImpl->m_aProps.aTitle;
1352 rename(pDocuSave->getName());
1354
1355 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
1356 {
1357 {PROPERTY_NAME, uno::Any(sOldName)}, // set as folder
1358 {PROPERTY_PERSISTENT_NAME, uno::Any(sPersistentName)},
1359 {PROPERTY_AS_TEMPLATE, uno::Any(m_pImpl->m_aProps.bAsTemplate)},
1360 }));
1361 Reference< XMultiServiceFactory > xORB( m_xParentContainer, UNO_QUERY_THROW );
1362 Reference< XInterface > xComponent( xORB->createInstanceWithArguments( SERVICE_SDB_DOCUMENTDEFINITION, aArguments ) );
1363 Reference< XNameContainer > xNameContainer( m_xParentContainer, UNO_QUERY_THROW );
1364 xNameContainer->insertByName( sOldName, Any( xComponent ) );
1365 }
1366 catch(const Exception&)
1367 {
1368 DBG_UNHANDLED_EXCEPTION("dbaccess");
1369 }
1370 }
1371 Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY);
1372 if ( xPersist.is() )
1373 {
1374 xPersist->storeOwn();
1376 }
1377 }
1378 }
1379 }
1380 catch(const Exception&)
1381 {
1382 TOOLS_WARN_EXCEPTION( "dbaccess", "ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!");
1383 }
1384}
1385
1386namespace
1387{
1388 void lcl_putLoadArgs( ::comphelper::NamedValueCollection& _io_rArgs, const optional_bool& _bSuppressMacros, const optional_bool& _bReadOnly )
1389 {
1390 if ( !!_bSuppressMacros )
1391 {
1392 if ( *_bSuppressMacros )
1393 {
1394 // if we're to suppress macros, do exactly this
1395 _io_rArgs.put( "MacroExecutionMode", MacroExecMode::NEVER_EXECUTE );
1396 }
1397 else
1398 {
1399 // otherwise, put the setting only if not already present
1400 if ( !_io_rArgs.has( "MacroExecutionMode" ) )
1401 {
1402 _io_rArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
1403 }
1404 }
1405 }
1406
1407 if ( !!_bReadOnly )
1408 _io_rArgs.put( "ReadOnly", *_bReadOnly );
1409 }
1410}
1411
1412namespace
1413{
1414 Reference< XFrame > lcl_getDatabaseDocumentFrame( ODatabaseModelImpl const & _rImpl )
1415 {
1416 Reference< XModel > xDatabaseDocumentModel( _rImpl.getModel_noCreate() );
1417
1418 Reference< XController > xDatabaseDocumentController;
1419 if ( xDatabaseDocumentModel.is() )
1420 xDatabaseDocumentController = xDatabaseDocumentModel->getCurrentController();
1421
1422 Reference< XFrame > xFrame;
1423 if ( xDatabaseDocumentController.is() )
1424 xFrame = xDatabaseDocumentController->getFrame();
1425
1426 return xFrame;
1427 }
1428}
1429
1431{
1432 bool bAllowDocumentMacros = !m_pImpl->m_pDataSource
1433 || ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::EmbeddedMacros::SubDocument );
1434
1435 // if *any* of the objects of the database document already has macros, we
1436 // continue to allow it to have them, until the user does a migration.
1437 // If there are no macros, we don't allow them to be created.
1438
1439 return bAllowDocumentMacros;
1440}
1441
1443{
1444 return lcl_determineContentType_nothrow( getContainerStorage(), m_pImpl->m_aProps.sPersistentName );
1445}
1446
1447void ODocumentDefinition::separateOpenCommandArguments( const Sequence< PropertyValue >& i_rOpenCommandArguments,
1448 ::comphelper::NamedValueCollection& o_rDocumentLoadArgs, ::comphelper::NamedValueCollection& o_rEmbeddedObjectDescriptor )
1449{
1450 ::comphelper::NamedValueCollection aOpenCommandArguments( i_rOpenCommandArguments );
1451
1452 static const std::u16string_view sObjectDescriptorArgs[] = { u"RecoveryStorage" };
1453 for (const auto& rObjectDescriptorArg : sObjectDescriptorArgs)
1454 {
1455 const OUString sObjectDescriptorArg(rObjectDescriptorArg);
1456 if ( aOpenCommandArguments.has( sObjectDescriptorArg ) )
1457 {
1458 o_rEmbeddedObjectDescriptor.put( sObjectDescriptorArg, aOpenCommandArguments.get( sObjectDescriptorArg ) );
1459 aOpenCommandArguments.remove( sObjectDescriptorArg );
1460 }
1461 }
1462
1463 o_rDocumentLoadArgs.merge( aOpenCommandArguments, false );
1464}
1465
1466Sequence< PropertyValue > ODocumentDefinition::fillLoadArgs( const Reference< XConnection>& _xConnection, const bool _bSuppressMacros, const bool _bReadOnly,
1467 const Sequence< PropertyValue >& i_rOpenCommandArguments, Sequence< PropertyValue >& _out_rEmbeddedObjectDescriptor )
1468{
1469 // (re-)create interceptor, and put it into the descriptor of the embedded object
1470 if ( m_pInterceptor.is() )
1471 {
1472 m_pInterceptor->dispose();
1473 m_pInterceptor.clear();
1474 }
1475
1476 m_pInterceptor = new OInterceptor( this );
1477 Reference<XDispatchProviderInterceptor> xInterceptor = m_pInterceptor;
1478
1479 ::comphelper::NamedValueCollection aEmbeddedDescriptor;
1480 aEmbeddedDescriptor.put( "OutplaceDispatchInterceptor", xInterceptor );
1481
1483 separateOpenCommandArguments( i_rOpenCommandArguments, aMediaDesc, aEmbeddedDescriptor );
1484
1485 // create the OutplaceFrameProperties, and put them into the descriptor of the embedded object
1486 ::comphelper::NamedValueCollection OutplaceFrameProperties;
1487 OutplaceFrameProperties.put( "TopWindow", true );
1488 OutplaceFrameProperties.put( "SupportPersistentWindowState", true );
1489
1490 Reference< XFrame > xParentFrame;
1491 if ( m_pImpl->m_pDataSource )
1492 xParentFrame = lcl_getDatabaseDocumentFrame( *m_pImpl->m_pDataSource );
1493 if ( !xParentFrame.is() )
1494 { // i87957 we need a parent frame
1495 Reference< XDesktop2 > xDesktop = Desktop::create( m_aContext );
1496 xParentFrame.set( xDesktop, UNO_QUERY_THROW );
1497 Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY);
1498 if ( xCloseable.is() )
1499 {
1500 xCloseable->addCloseListener(this);
1501 m_bRemoveListener = true;
1502 }
1503 }
1504 OSL_ENSURE( xParentFrame.is(), "ODocumentDefinition::fillLoadArgs: no parent frame!" );
1505 if ( xParentFrame.is() )
1506 OutplaceFrameProperties.put( "ParentFrame", xParentFrame );
1507
1508 aEmbeddedDescriptor.put( "OutplaceFrameProperties", OutplaceFrameProperties.getNamedValues() );
1509
1510 // tell the embedded object to have (or not have) script support
1511 aEmbeddedDescriptor.put( "EmbeddedScriptSupport", objectSupportsEmbeddedScripts() );
1512
1513 // tell the embedded object to not participate in the document recovery game - the DB doc will handle it
1514 aEmbeddedDescriptor.put( "DocumentRecoverySupport", false );
1515
1516 // pass the descriptor of the embedded object to the caller
1517 aEmbeddedDescriptor >>= _out_rEmbeddedObjectDescriptor;
1518
1519 // create the ComponentData, and put it into the document's media descriptor
1520 {
1522 aComponentData.put( "ActiveConnection", _xConnection );
1523 aComponentData.put( "ApplyFormDesignMode", !_bReadOnly );
1524 aMediaDesc.put( "ComponentData", aComponentData.getPropertyValues() );
1525 }
1526
1527 if ( !m_pImpl->m_aProps.aTitle.isEmpty() )
1528 aMediaDesc.put( "DocumentTitle", m_pImpl->m_aProps.aTitle );
1529
1530 aMediaDesc.put( "DocumentBaseURL", m_pImpl->m_pDataSource->getURL() );
1531
1532 // put the common load arguments into the document's media descriptor
1533 lcl_putLoadArgs( aMediaDesc, optional_bool( _bSuppressMacros ), optional_bool( _bReadOnly ) );
1534
1535 return aMediaDesc.getPropertyValues();
1536}
1537
1538void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& i_rConnection, const Sequence< sal_Int8 >& _aClassID,
1539 const Sequence< PropertyValue >& i_rOpenCommandArguments, const bool _bSuppressMacros, const bool _bReadOnly )
1540{
1541 if ( !m_xEmbeddedObject.is() )
1542 {
1543 Reference< XStorage> xStorage = getContainerStorage();
1544 if ( xStorage.is() )
1545 {
1546 Reference< XEmbeddedObjectCreator> xEmbedFactory = OOoEmbeddedObjectFactory::create(m_aContext);
1547 OUString sDocumentService;
1548 bool bSetSize = false;
1549 sal_Int32 nEntryConnectionMode = EntryInitModes::DEFAULT_INIT;
1550 Sequence< sal_Int8 > aClassID = _aClassID;
1551 if ( aClassID.hasElements() )
1552 {
1553 nEntryConnectionMode = EntryInitModes::TRUNCATE_INIT;
1554 bSetSize = true;
1555 }
1556 else
1557 {
1559 // check if we are not a form and
1560 // the org.libreoffice.report.pentaho.SOReportJobFactory is not present.
1561 if ( !m_bForm && sDocumentService != "com.sun.star.text.TextDocument")
1562 {
1563 // we seem to be a "new style" report, check if report extension is present.
1564 Reference< XContentEnumerationAccess > xEnumAccess( m_aContext->getServiceManager(), UNO_QUERY );
1565 const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_aContext);
1566 Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName);
1567 if ( !xEnumDrivers.is() || !xEnumDrivers->hasMoreElements() )
1568 {
1569 css::io::WrongFormatException aWFE;
1570 aWFE.Message = DBA_RES( RID_STR_MISSING_EXTENSION );
1571 throw aWFE;
1572 }
1573 }
1574 if ( !aClassID.hasElements() )
1575 {
1576 if ( m_bForm )
1578 else
1579 {
1581 }
1582 }
1583 }
1584
1585 OSL_ENSURE( aClassID.hasElements(),"No Class ID" );
1586
1587 Sequence< PropertyValue > aEmbeddedObjectDescriptor;
1588 Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
1589 i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
1590
1591 m_xEmbeddedObject.set(xEmbedFactory->createInstanceUserInit(aClassID
1593 ,xStorage
1594 ,m_pImpl->m_aProps.sPersistentName
1595 ,nEntryConnectionMode
1596 ,aLoadArgs
1597 ,aEmbeddedObjectDescriptor
1598 ),UNO_QUERY);
1599 if ( m_xEmbeddedObject.is() )
1600 {
1601 if ( !m_pClientHelper.is() )
1602 {
1604 }
1605 m_xEmbeddedObject->setClientSite(m_pClientHelper);
1606 m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
1607 if ( bSetSize )
1608 {
1609 LockModifiable aLockModify( impl_getComponent_throw( false ) );
1610
1611 awt::Size aSize( DEFAULT_WIDTH, DEFAULT_HEIGHT );
1612 m_xEmbeddedObject->setVisualAreaSize(Aspects::MSOLE_CONTENT,aSize);
1613 }
1614 }
1615 }
1616 }
1617 else
1618 {
1619 sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState();
1620 if ( nCurrentState == EmbedStates::LOADED )
1621 {
1622 if ( !m_pClientHelper.is() )
1623 {
1625 }
1626 m_xEmbeddedObject->setClientSite(m_pClientHelper);
1627
1628 Sequence< PropertyValue > aEmbeddedObjectDescriptor;
1629 Sequence< PropertyValue > aLoadArgs( fillLoadArgs(
1630 i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) );
1631
1632 Reference<XCommonEmbedPersist> xCommon(m_xEmbeddedObject,UNO_QUERY);
1633 OSL_ENSURE(xCommon.is(),"unsupported interface!");
1634 if ( xCommon.is() )
1635 xCommon->reload( aLoadArgs, aEmbeddedObjectDescriptor );
1636 m_xEmbeddedObject->changeState(EmbedStates::RUNNING);
1637 }
1638 else
1639 {
1640 OSL_ENSURE( ( nCurrentState == EmbedStates::RUNNING ) || ( nCurrentState == EmbedStates::ACTIVE ),
1641 "ODocumentDefinition::loadEmbeddedObject: unexpected state!" );
1642
1643 // if the document was already loaded (which means the embedded object is in state RUNNING or ACTIVE),
1644 // then just re-set some model parameters
1645 try
1646 {
1647 // ensure the media descriptor doesn't contain any values which are intended for the
1648 // EmbeddedObjectDescriptor only
1649 ::comphelper::NamedValueCollection aEmbeddedObjectDescriptor;
1651 separateOpenCommandArguments( i_rOpenCommandArguments, aNewMediaDesc, aEmbeddedObjectDescriptor );
1652
1653 // merge the new media descriptor into the existing media descriptor
1654 const Reference< XModel > xModel( getComponent(), UNO_QUERY_THROW );
1655 const Sequence< PropertyValue > aArgs = xModel->getArgs();
1656 ::comphelper::NamedValueCollection aExistentMediaDesc( aArgs );
1657 aExistentMediaDesc.merge( aNewMediaDesc, false );
1658
1659 lcl_putLoadArgs( aExistentMediaDesc, optional_bool(), optional_bool() );
1660 // don't put _bSuppressMacros and _bReadOnly here - if the document was already
1661 // loaded, we should not tamper with its settings.
1662 // #i88977# #i86872#
1663
1664 xModel->attachResource( xModel->getURL(), aExistentMediaDesc.getPropertyValues() );
1665 }
1666 catch( const Exception& )
1667 {
1668 DBG_UNHANDLED_EXCEPTION("dbaccess");
1669 }
1670 }
1671 }
1672
1673 // set the OfficeDatabaseDocument instance as parent of the embedded document
1674 // #i40358#
1675 Reference< XChild > xDepdendDocAsChild( getComponent(), UNO_QUERY );
1676 if ( xDepdendDocAsChild.is() )
1677 {
1678 try
1679 {
1680 if ( !xDepdendDocAsChild->getParent().is() )
1681 { // first encounter
1682 xDepdendDocAsChild->setParent( getDataSource( m_xParentContainer ) );
1683 }
1684 }
1685 catch( const Exception& )
1686 {
1687 DBG_UNHANDLED_EXCEPTION("dbaccess");
1688 }
1689 }
1690
1691 if ( i_rConnection.is() )
1692 m_xLastKnownConnection = i_rConnection;
1693}
1694
1696{
1698 if ( !m_xEmbeddedObject.is() )
1699 return;
1700
1701 try
1702 {
1703 Reference<XTransferable> xTransfer(getComponent(),UNO_QUERY);
1704 if ( xTransfer.is() )
1705 {
1706 DataFlavor aFlavor;
1707 aFlavor.MimeType = "image/png";
1708 aFlavor.HumanPresentableName = "Portable Network Graphics";
1709 aFlavor.DataType = cppu::UnoType<Sequence < sal_Int8 >>::get();
1710
1711 _rImage = xTransfer->getTransferData( aFlavor );
1712 }
1713 }
1714 catch( const Exception& )
1715 {
1716 }
1717}
1718
1719void ODocumentDefinition::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
1720{
1721 _rDefault.clear();
1722}
1723
1725{
1727 if ( !m_xEmbeddedObject.is() )
1728 return;
1729
1730 try
1731 {
1732 Reference<XDocumentPropertiesSupplier> xDocSup(
1733 getComponent(), UNO_QUERY );
1734 if ( xDocSup.is() )
1735 _rProps <<= xDocSup->getDocumentProperties();
1736 }
1737 catch( const Exception& )
1738 {
1739 DBG_UNHANDLED_EXCEPTION("dbaccess");
1740 }
1741}
1742
1743Reference< util::XCloseable > ODocumentDefinition::impl_getComponent_throw( const bool i_ForceCreate )
1744{
1745 OSL_ENSURE(m_xEmbeddedObject.is(),"Illegal call for embeddedObject");
1746 Reference< util::XCloseable > xComp;
1747 if ( m_xEmbeddedObject.is() )
1748 {
1749 int nState = m_xEmbeddedObject->getCurrentState();
1750 if ( ( nState == EmbedStates::LOADED ) && i_ForceCreate )
1751 {
1752 m_xEmbeddedObject->changeState( EmbedStates::RUNNING );
1753 nState = m_xEmbeddedObject->getCurrentState();
1754 OSL_ENSURE( nState == EmbedStates::RUNNING, "ODocumentDefinition::impl_getComponent_throw: could not switch to RUNNING!" );
1755 }
1756
1757 if ( nState == EmbedStates::ACTIVE || nState == EmbedStates::RUNNING )
1758 {
1759 if ( m_xEmbeddedObject.is() )
1760 {
1761 xComp = m_xEmbeddedObject->getComponent();
1762 OSL_ENSURE(xComp.is(),"No valid component");
1763 }
1764 }
1765 }
1766 return xComp;
1767}
1768
1769Reference< util::XCloseable > ODocumentDefinition::getComponent()
1770{
1771 ::osl::MutexGuard aGuard( m_aMutex );
1772 return impl_getComponent_throw();
1773}
1774
1775namespace
1776{
1777 Reference< XDatabaseDocumentUI > lcl_getDatabaseDocumentUI( ODatabaseModelImpl const & _rModelImpl )
1778 {
1779 Reference< XDatabaseDocumentUI > xUI;
1780
1781 Reference< XModel > xModel( _rModelImpl.getModel_noCreate() );
1782 if ( xModel.is() )
1783 xUI.set( xModel->getCurrentController(), UNO_QUERY );
1784 return xUI;
1785 }
1786}
1787
1788Reference< XComponent > ODocumentDefinition::impl_openUI_nolck_throw( bool _bForEditing )
1789{
1790 ::osl::ClearableMutexGuard aGuard( m_aMutex );
1791 if ( !m_pImpl || !m_pImpl->m_pDataSource )
1792 throw DisposedException();
1793
1794 Reference< XComponent > xComponent;
1795 try
1796 {
1797 Reference< XDatabaseDocumentUI > xUI( lcl_getDatabaseDocumentUI( *m_pImpl->m_pDataSource ) );
1798 if ( !xUI.is() )
1799 {
1800 // no XDatabaseDocumentUI -> just execute the respective command
1801 m_bOpenInDesign = _bForEditing;
1802 xComponent = Reference<XComponent>(onCommandOpenSomething(Any(), true, nullptr), UNO_QUERY);
1803 OSL_ENSURE( xComponent.is(), "ODocumentDefinition::impl_openUI_nolck_throw: opening the thingie failed." );
1804 return xComponent;
1805 }
1806
1807
1808 OUString sName( impl_getHierarchicalName( false ) );
1809 sal_Int32 nObjectType = m_bForm ? DatabaseObject::FORM : DatabaseObject::REPORT;
1810 aGuard.clear();
1811
1812 xComponent = xUI->loadComponent(
1813 nObjectType, sName, _bForEditing
1814 );
1815 }
1816 catch( const RuntimeException& ) { throw; }
1817 catch( const Exception& )
1818 {
1819 throw WrappedTargetException(
1820 OUString(), *this, ::cppu::getCaughtException() );
1821 }
1822
1823 return xComponent;
1824}
1825
1827{
1828 Reference<XEmbedPersist> xPersist( m_xEmbeddedObject, UNO_QUERY );
1829 if ( xPersist.is() )
1830 {
1831 xPersist->storeOwn();
1833 }
1834}
1835
1837{
1838 bool bSuccess = prepareClose();
1839 if ( bSuccess && m_xEmbeddedObject.is() )
1840 {
1841 m_xEmbeddedObject->changeState( EmbedStates::LOADED );
1842 bSuccess = m_xEmbeddedObject->getCurrentState() == EmbedStates::LOADED;
1843 }
1844 return bSuccess;
1845}
1846
1847Reference< XComponent > SAL_CALL ODocumentDefinition::open( )
1848{
1849 return impl_openUI_nolck_throw( false );
1850}
1851
1852Reference< XComponent > SAL_CALL ODocumentDefinition::openDesign( )
1853{
1854 return impl_openUI_nolck_throw( true );
1855}
1856
1858{
1859 ::osl::MutexGuard aGuard( m_aMutex );
1860 try
1861 {
1863 }
1864 catch( const RuntimeException& ) { throw; }
1865 catch( const Exception& )
1866 {
1867 throw WrappedTargetException(
1868 OUString(), *this, ::cppu::getCaughtException() );
1869 }
1870}
1871
1873{
1874 ::osl::MutexGuard aGuard( m_aMutex );
1875
1876 bool bSuccess = false;
1877 try
1878 {
1879 bSuccess = impl_close_throw();
1880 }
1881 catch( const RuntimeException& ) { throw; }
1882 catch( const Exception& )
1883 {
1884 throw WrappedTargetException(
1885 OUString(), *this, ::cppu::getCaughtException() );
1886 }
1887 return bSuccess;
1888}
1889
1891{
1892 ::osl::MutexGuard aGuard( m_aMutex );
1893 return impl_getHierarchicalName( false );
1894}
1895
1896OUString SAL_CALL ODocumentDefinition::composeHierarchicalName( const OUString& i_rRelativeName )
1897{
1898 return getHierarchicalName() + "/" + i_rRelativeName;
1899}
1900
1901void SAL_CALL ODocumentDefinition::rename( const OUString& _rNewName )
1902{
1903 try
1904 {
1905 ::osl::ResettableMutexGuard aGuard(m_aMutex);
1906 if ( _rNewName == m_pImpl->m_aProps.aTitle )
1907 return;
1908
1909 // document definitions are organized in a hierarchical way, so reject names
1910 // which contain a /, as this is reserved for hierarchy level separation
1911 if ( _rNewName.indexOf( '/' ) != -1 )
1912 m_aErrorHelper.raiseException( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES, *this );
1913
1914 NameChangeNotifier aNameChangeAndNotify( *this, _rNewName, aGuard );
1915 m_pImpl->m_aProps.aTitle = _rNewName;
1916
1917 if ( m_xEmbeddedObject.is() && m_xEmbeddedObject->getCurrentState() == EmbedStates::ACTIVE )
1919 }
1920 catch(const PropertyVetoException&)
1921 {
1922 throw ElementExistException(_rNewName,*this);
1923 }
1924}
1925
1927{
1928 return m_pImpl->m_pDataSource
1930 : Reference< XStorage>();
1931}
1932
1934{
1935 osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
1936 bool bRet = false;
1937 if ( m_xEmbeddedObject.is() )
1938 {
1939 Reference<XModifiable> xModel(getComponent(),UNO_QUERY);
1940 bRet = xModel.is() && xModel->isModified();
1941 }
1942 return bRet;
1943}
1944
1946{
1947 if ( !m_xEmbeddedObject.is() )
1948 return true;
1949
1950 try
1951 {
1952 // suspend the controller. Embedded objects are not allowed to raise
1953 // own UI at their own discretion, instead, this has always to be triggered
1954 // by the embedding component. Thus, we do the suspend call here.
1955 // #i49370#
1956
1957 Reference< util::XCloseable > xComponent( impl_getComponent_throw( false ) );
1958 if ( !xComponent.is() )
1959 return true;
1960
1961 Reference< XModel > xModel( xComponent, UNO_QUERY );
1962 Reference< XController > xController;
1963 if ( xModel.is() )
1964 xController = xModel->getCurrentController();
1965
1966 OSL_ENSURE( xController.is() || ( m_xEmbeddedObject->getCurrentState() < EmbedStates::ACTIVE ),
1967 "ODocumentDefinition::prepareClose: no controller!" );
1968 if ( !xController.is() )
1969 // document has not yet been activated, i.e. has no UI, yet
1970 return true;
1971
1972 if (!xController->suspend(true))
1973 // controller vetoed the closing
1974 return false;
1975
1976 if ( isModified() )
1977 {
1978 Reference< XFrame > xFrame( xController->getFrame() );
1979 Reference<XTopWindow> xTopWindow;
1980 if ( xFrame.is() )
1981 {
1982 xTopWindow = Reference<XTopWindow>(xFrame->getContainerWindow(), UNO_QUERY_THROW);
1983 xTopWindow->toFront();
1984 }
1985 if (!save(true, xTopWindow))
1986 {
1987 // revert suspension
1988 xController->suspend(false);
1989 // saving failed or was cancelled
1990 return false;
1991 }
1992 }
1993 }
1994 catch( const Exception& )
1995 {
1996 DBG_UNHANDLED_EXCEPTION("dbaccess");
1997 }
1998
1999 return true;
2000}
2001
2002void ODocumentDefinition::fillReportData( const Reference< XComponentContext >& _rContext,
2003 const Reference< util::XCloseable >& _rxComponent,
2004 const Reference< XConnection >& _rxActiveConnection )
2005{
2006 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
2007 {
2008 {"TextDocument", uno::Any(_rxComponent)},
2009 {"ActiveConnection", uno::Any(_rxActiveConnection)}
2010 }));
2011 try
2012 {
2013 Reference< XJobExecutor > xExecutable(
2014 _rContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.wizards.report.CallReportWizard", aArgs, _rContext), UNO_QUERY_THROW );
2015 xExecutable->trigger( "fill" );
2016 }
2017 catch( const Exception& )
2018 {
2019 DBG_UNHANDLED_EXCEPTION("dbaccess");
2020 }
2021}
2022
2024{
2025 OUString sName = m_pImpl->m_aProps.aTitle;
2026 if ( m_pImpl->m_pDataSource )
2027 {
2028 if ( sName.isEmpty() )
2029 {
2030 if ( m_bForm )
2031 sName = DBA_RES( RID_STR_FORM );
2032 else
2033 sName = DBA_RES( RID_STR_REPORT );
2034 Reference< XUntitledNumbers > xUntitledProvider(m_pImpl->m_pDataSource->getModel_noCreate(), UNO_QUERY );
2035 if ( xUntitledProvider.is() )
2036 sName += OUString::number( xUntitledProvider->leaseNumber(getComponent()) );
2037 }
2038
2039 Reference< XTitle > xDatabaseDocumentModel(m_pImpl->m_pDataSource->getModel_noCreate(),uno::UNO_QUERY);
2040 if ( xDatabaseDocumentModel.is() )
2041 sName = xDatabaseDocumentModel->getTitle() + " : " + sName;
2042 }
2043 Reference< XTitle> xTitle(getComponent(),UNO_QUERY);
2044 if ( xTitle.is() )
2045 xTitle->setTitle(sName);
2046}
2047
2048void SAL_CALL ODocumentDefinition::queryClosing( const lang::EventObject&, sal_Bool )
2049{
2050 try
2051 {
2052 if ( !close() )
2053 throw util::CloseVetoException();
2054 }
2055 catch(const lang::WrappedTargetException&)
2056 {
2057 throw util::CloseVetoException();
2058 }
2059}
2060
2061void SAL_CALL ODocumentDefinition::notifyClosing( const lang::EventObject& /*Source*/ )
2062{
2063}
2064
2065void SAL_CALL ODocumentDefinition::disposing( const lang::EventObject& /*Source*/ )
2066{
2067}
2068
2069void ODocumentDefinition::firePropertyChange( sal_Int32 i_nHandle, const Any& i_rNewValue, const Any& i_rOldValue,
2070 bool i_bVetoable, const NotifierAccess& )
2071{
2072 fire( &i_nHandle, &i_rNewValue, &i_rOldValue, 1, i_bVetoable );
2073}
2074
2075// NameChangeNotifier
2076NameChangeNotifier::NameChangeNotifier( ODocumentDefinition& i_rDocumentDefinition, const OUString& i_rNewName,
2077 ::osl::ResettableMutexGuard& i_rClearForNotify )
2078 :m_rDocumentDefinition( i_rDocumentDefinition )
2079 ,m_aOldValue( Any( i_rDocumentDefinition.getCurrentName() ) )
2080 ,m_aNewValue( Any( i_rNewName ) )
2081 ,m_rClearForNotify( i_rClearForNotify )
2082{
2083 impl_fireEvent_throw( true );
2084}
2085
2087{
2088 impl_fireEvent_throw( false );
2089}
2090
2091void NameChangeNotifier::impl_fireEvent_throw( const bool i_bVetoable )
2092{
2093 m_rClearForNotify.clear();
2096 m_rClearForNotify.reset();
2097}
2098
2099} // namespace dbaccess
2100
2101/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OptionalString sName
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
constexpr OUStringLiteral sDocumentService
AnyEventRef aEvent
static css::uno::Sequence< sal_Int8 > GetSequenceClassIDRepresentation(std::u16string_view aClassID)
static css::uno::Sequence< sal_Int8 > GetSequenceClassID(sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3, sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11, sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15)
bool has(const OUString &_rValueName) const
const css::uno::Any & get(const OUString &_rValueName) const
bool remove(const OUString &_rValueName)
bool put(const OUString &_rValueName, const VALUE_TYPE &_rValue)
css::uno::Sequence< css::beans::NamedValue > getNamedValues() const
NamedValueCollection & merge(const NamedValueCollection &_rAdditionalValues, bool _bOverwriteExisting)
css::uno::Sequence< css::beans::PropertyValue > getPropertyValues() const
VALUE_TYPE getOrDefault(const OUString &_rValueName, const VALUE_TYPE &_rDefault) const
void describeProperties(css::uno::Sequence< css::beans::Property > &_rProps) const
virtual void SAL_CALL getFastPropertyValue(css::uno::Any &rValue, sal_Int32 nHandle) const override
void raiseException(const ErrorCondition _eCondition, const css::uno::Reference< css::uno::XInterface > &_rxContext, const std::optional< OUString > &_rParamValue1=std::nullopt, const std::optional< OUString > &_rParamValue2=std::nullopt, const std::optional< OUString > &_rParamValue3=std::nullopt) const
mutable::osl::Mutex m_aMutex
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
css::uno::Type const & get()
::osl::ResettableMutexGuard & m_rClearForNotify
NameChangeNotifier(ODocumentDefinition &i_rDocumentDefinition, const OUString &i_rNewName, ::osl::ResettableMutexGuard &i_rClearForNotify)
void impl_fireEvent_throw(const bool i_bVetoable)
ODocumentDefinition & m_rDocumentDefinition
OUString impl_getHierarchicalName(bool _includingRootContainer) const
virtual void SAL_CALL disposing() override
const css::uno::Reference< css::uno::XComponentContext > m_aContext
virtual css::uno::Any SAL_CALL execute(const css::ucb::Command &aCommand, sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment > &Environment) override
const ::connectivity::SQLError m_aErrorHelper
virtual OUString SAL_CALL getContentType() override
css::uno::Reference< css::uno::XInterface > m_xParentContainer
css::uno::Reference< css::frame::XModel > getModel_noCreate() const
returns the model, if there already exists one
Definition: ModelImpl.cxx:963
static OUString getObjectContainerStorageName(const ObjectType _eType)
returns the name of the storage which is used to stored objects of the given type,...
Definition: ModelImpl.cxx:1285
virtual void SAL_CALL rename(const OUString &newName) override
static void impl_initFormEditView(const css::uno::Reference< css::frame::XController > &_rxController)
initializes a newly created view/controller of a form which is displaying our embedded object
static void impl_removeFrameFromDesktop_throw(const css::uno::Reference< css::uno::XComponentContext > &_rContext, const css::uno::Reference< css::frame::XFrame > &_rxFrame)
removes the given frame from the desktop's frame collection
bool impl_close_throw()
closes our document, if it's open
css::uno::Reference< css::sdbc::XConnection > m_xLastKnownConnection
virtual void getPropertyDefaultByHandle(sal_Int32 _nHandle, css::uno::Any &_rDefault) const override
void onCommandInsert(const OUString &_sURL, const css::uno::Reference< css::ucb::XCommandEnvironment > &Environment)
rtl::Reference< OEmbeddedClientHelper > m_pClientHelper
static void separateOpenCommandArguments(const css::uno::Sequence< css::beans::PropertyValue > &i_rOpenCommandArguments, ::comphelper::NamedValueCollection &o_rDocumentLoadArgs, ::comphelper::NamedValueCollection &o_rEmbeddedObjectDescriptor)
splits the given arguments to an "open*" command into arguments for loading the document,...
bool prepareClose()
prepares closing the document component
virtual css::uno::Reference< css::util::XCloseable > SAL_CALL getComponent() override
virtual void SAL_CALL disposing() override
void updateDocumentTitle()
searches for read-only flag in the args of the model and sets it to the given value,...
css::uno::Sequence< css::beans::PropertyValue > fillLoadArgs(const css::uno::Reference< css::sdbc::XConnection > &_xConnection, const bool _bSuppressMacros, const bool _bReadOnly, const css::uno::Sequence< css::beans::PropertyValue > &i_rOpenCommandArguments, css::uno::Sequence< css::beans::PropertyValue > &_out_rEmbeddedObjectDescriptor)
fills the load arguments
void loadEmbeddedObject(const css::uno::Reference< css::sdbc::XConnection > &_xConnection, const css::uno::Sequence< sal_Int8 > &_aClassID, const css::uno::Sequence< css::beans::PropertyValue > &_rAdditionalArgs, const bool _bSuppressMacros, const bool _bReadOnly)
loads the EmbeddedObject if not already loaded
void loadEmbeddedObjectForPreview()
loads the embedded object for preview.
static void fillReportData(const css::uno::Reference< css::uno::XComponentContext > &_rxContext, const css::uno::Reference< css::util::XCloseable > &_rxComponent, const css::uno::Reference< css::sdbc::XConnection > &_rxActiveConnection)
bool save(bool _bApprove, const css::uno::Reference< css::awt::XTopWindow > &rDialogParent)
void impl_store_throw()
stores our document, if it's already loaded
ODocumentDefinition(const css::uno::Reference< css::uno::XInterface > &_rxContainer, const css::uno::Reference< css::uno::XComponentContext > &, const TContentPtr &_pImpl, bool _bForm)
void onCommandPreview(css::uno::Any &_rImage)
virtual OUString determineContentType() const override
css::uno::Reference< css::embed::XStorage > getContainerStorage() const
returns the forms/reports container storage, depending on m_bForm.
virtual ::cppu::IPropertyArrayHelper * createArrayHelper() const override
rtl::Reference< OInterceptor > m_pInterceptor
css::uno::Reference< css::util::XCloseable > impl_getComponent_throw(const bool i_ForceCreate=true)
returns our component, creates it if necessary
virtual css::uno::Reference< css::lang::XComponent > SAL_CALL open() override
void firePropertyChange(sal_Int32 i_nHandle, const css::uno::Any &i_rNewValue, const css::uno::Any &i_rOldValue, bool i_bVetoable, const NotifierAccess &)
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
virtual sal_Bool SAL_CALL close() override
css::uno::Reference< css::embed::XEmbeddedObject > m_xEmbeddedObject
void impl_showOrHideComponent_throw(const bool i_bShow)
shows or hides our component
virtual ::cppu::IPropertyArrayHelper &SAL_CALL getInfoHelper() override
void impl_onActivateEmbeddedObject_nothrow(const bool i_bReactivated)
does necessary initializations after our embedded object has been switched to ACTIVE
void onCommandGetDocumentProperties(css::uno::Any &_rProps)
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
bool objectSupportsEmbeddedScripts() const
determines whether the document we represent supports embedded scripts and macros
virtual css::uno::Reference< css::lang::XComponent > SAL_CALL openDesign() override
void initialLoad(const css::uno::Sequence< sal_Int8 > &i_rClassID, const css::uno::Sequence< css::beans::PropertyValue > &i_rCreationArgs, const css::uno::Reference< css::sdbc::XConnection > &i_rConnection)
css::uno::Any onCommandOpenSomething(const css::uno::Any &_rArgument, const bool _bActivate, const css::uno::Reference< css::ucb::XCommandEnvironment > &_rxEnvironment)
css::uno::Reference< css::lang::XComponent > impl_openUI_nolck_throw(bool _bForEditing)
opens the UI for this sub document
virtual void SAL_CALL store() override
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
virtual OUString SAL_CALL getHierarchicalName() override
virtual void SAL_CALL notifyClosing(const css::lang::EventObject &Source) override
css::uno::Reference< css::embed::XStateChangeListener > m_xListener
virtual void SAL_CALL queryClosing(const css::lang::EventObject &Source, sal_Bool GetsOwnership) override
virtual css::uno::Any SAL_CALL execute(const css::ucb::Command &aCommand, sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment > &Environment) override
virtual OUString SAL_CALL composeHierarchicalName(const OUString &aRelativeName) override
static OUString GetDocumentServiceFromMediaType(const OUString &_rMediaType, const css::uno::Reference< css::uno::XComponentContext > &_rxContext, css::uno::Sequence< sal_Int8 > &_rClassId)
virtual void SAL_CALL getFastPropertyValue(css::uno::Any &o_rValue, sal_Int32 i_nHandle) const override
virtual void SAL_CALL visibilityChanged(sal_Bool) override
virtual void SAL_CALL saveObject() override
virtual Reference< util::XCloseable > SAL_CALL getComponent() override
#define SO3_SW_CLASSID
#define SO3_RPT_CLASSID_90
#define DBA_RES(id)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
ODocumentDefinition * m_pDefinition
Reference< XVisualObject > m_xVisObject
#define DEFAULT_HEIGHT
Reference< XModifiable2 > m_xModifiable
Reference< XEmbeddedObject > m_xBroadCaster
bool & m_rbSet
#define DEFAULT_WIDTH
OUString m_sName
awt::Size m_aOriginalSize
Reference< XInterface > m_xClient
Reference< XLayoutManager > m_xLayoutManager
Reference< XContent > m_xParentContainer
bool m_bInStateChange
float u
sal_Int32 nState
Sequence< PropertyValue > aArguments
Definition: intercept.cxx:88
@ Exception
css::uno::Sequence< css::uno::Any > InitAnyPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
std::shared_ptr< OContentHelper_Impl > TContentPtr
css::uno::Reference< css::uno::XInterface > getDataSource(const css::uno::Reference< css::uno::XInterface > &_rxDependentObject)
::cppu::WeakImplHelper< css::lang::XEventListener > LifetimeCoupler_Base
::comphelper::WeakComponentImplHelper< embed::XStateChangeListener > TEmbedObjectHolder
::std::optional< bool > optional_bool
int i
void dispose()
void cancelCommandExecution(const uno::Any &rException, const uno::Reference< ucb::XCommandEnvironment > &xEnv)
const char *const aClassID
#define PROPERTY_ID_NAME
#define PROPERTY_ID_AS_TEMPLATE
#define PROPERTY_ID_PERSISTENT_NAME
#define PROPERTY_ID_IS_FORM
#define PROPERTY_ID_PERSISTENT_PATH
constexpr OUStringLiteral INFO_MEDIATYPE
Definition: strings.hxx:229
constexpr OUStringLiteral PROPERTY_URL(u"URL")
constexpr OUStringLiteral PROPERTY_PERSISTENT_NAME(u"PersistentName")
constexpr OUStringLiteral PROPERTY_IS_FORM(u"IsForm")
constexpr OUStringLiteral SERVICE_SDB_DOCUMENTDEFINITION
Definition: strings.hxx:196
constexpr OUStringLiteral PROPERTY_ACTIVE_CONNECTION(u"ActiveConnection")
constexpr OUStringLiteral PROPERTY_AS_TEMPLATE(u"AsTemplate")
constexpr OUStringLiteral PROPERTY_NAME(u"Name")
constexpr OUStringLiteral PROPERTY_PERSISTENT_PATH(u"PersistentPath")
constexpr OUStringLiteral PROPERTY_DATASOURCENAME(u"DataSourceName")
Reference< XController > xController
the controller of the sub component. Must not be <NULL>
Reference< XFrame > xFrame
the frame which the component resides in. Must not be <NULL>
Reference< XModel > xModel
the model of the sub component. Might be <NULL>
OUString aCommand
unsigned char sal_Bool
#define IMPLEMENT_FORWARD_XINTERFACE3(classname, refcountbase, baseclass2, baseclass3)