1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
22 #include "ContentHelper.hxx"
23 #include "documentevents.hxx"
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <com/sun/star/beans/XPropertyBag.hpp>
27 #include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
28 #include <com/sun/star/embed/XStorage.hpp>
29 #include <com/sun/star/frame/XModel.hpp>
30 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
31 #include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
32 #include <com/sun/star/sdbc/XDataSource.hpp>
33 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
35 #include <comphelper/namedvaluecollection.hxx>
36 #include <cppuhelper/weakref.hxx>
37 #include <vcl/svapp.hxx>
38 #include <sfx2/docmacromode.hxx>
39 #include <sfx2/docstoragemodifylistener.hxx>
40 #include <unotools/sharedunocomponent.hxx>
41 #include <rtl/ref.hxx>
42 #include <o3tl/enumarray.hxx>
46 class NamedValueCollection
;
52 typedef std::vector
< css::uno::WeakReference
< css::sdbc::XConnection
> > OWeakConnectionArray
;
54 struct AsciiPropertyValue
56 // note: the canonic member order would be AsciiName / DefaultValue, but
57 // this crashes on unxlngi6.pro, since there's a bug which somehow results in
58 // getDefaultDataSourceSettings returning corrupted Any instances then.
59 css::uno::Any DefaultValue
;
60 const char* AsciiName
;
61 const css::uno::Type
& ValueType
;
66 ,ValueType( ::cppu::UnoType
<void>::get() )
70 AsciiPropertyValue( const char* _pAsciiName
, const css::uno::Any
& _rDefaultValue
)
71 :DefaultValue( _rDefaultValue
)
72 ,AsciiName( _pAsciiName
)
73 ,ValueType( _rDefaultValue
.getValueType() )
75 OSL_ENSURE( ValueType
.getTypeClass() != css::uno::TypeClass_VOID
,
76 "AsciiPropertyValue::AsciiPropertyValue: NULL values not allowed here, use the other CTOR for this!" );
78 AsciiPropertyValue( const char* _pAsciiName
, const css::uno::Type
& _rValeType
)
80 ,AsciiName( _pAsciiName
)
81 ,ValueType( _rValeType
)
83 OSL_ENSURE( ValueType
.getTypeClass() != css::uno::TypeClass_VOID
,
84 "AsciiPropertyValue::AsciiPropertyValue: VOID property values not supported!" );
88 class ODatabaseContext
;
89 class OSharedConnectionManager
;
92 typedef ::utl::SharedUNOComponent
< css::embed::XStorage
> SharedStorage
;
94 class ODatabaseContext
;
95 class DocumentStorageAccess
;
96 class OSharedConnectionManager
;
98 class ODatabaseModelImpl
:public ::sfx2::IMacroDocumentAccess
99 ,public ::sfx2::IModifiableDocument
103 enum class ObjectType
112 enum class EmbeddedMacros
114 // the database document (storage) itself contains macros
116 // there are sub document( storage)s containing macros
118 // there are no known macro( storage)s
123 css::uno::WeakReference
< css::frame::XModel
> m_xModel
;
124 css::uno::WeakReference
< css::sdbc::XDataSource
> m_xDataSource
;
126 rtl::Reference
<DocumentStorageAccess
> m_pStorageAccess
;
127 o3tl::enumarray
< ObjectType
, TContentPtr
> m_aContainer
; // one for each ObjectType
128 ::sfx2::DocumentMacroMode m_aMacroMode
;
129 sal_Int16 m_nImposedMacroExecMode
;
131 css::uno::Reference
< css::script::XStorageBasedLibraryContainer
> m_xBasicLibraries
;
132 css::uno::Reference
< css::script::XStorageBasedLibraryContainer
> m_xDialogLibraries
;
134 SharedStorage m_xDocumentStorage
;
135 ::rtl::Reference
< ::sfx2::DocumentStorageModifyListener
> m_pStorageModifyListener
;
136 ODatabaseContext
& m_rDBContext
;
137 DocumentEventsData m_aDocumentEvents
;
139 ::comphelper::NamedValueCollection m_aMediaDescriptor
;
140 /// the URL the document was loaded from
141 OUString m_sDocFileLocation
;
143 oslInterlockedCount m_refCount
;
145 /// do we have any object (forms/reports) which contains macros?
146 ::std::optional
< EmbeddedMacros
> m_aEmbeddedMacros
;
148 /// true if setting the Modified flag of the document is currently locked
149 bool m_bModificationLock
;
151 /// true if and only if a database document existed previously (though meanwhile disposed), and was already initialized
152 bool m_bDocumentInitialized
;
154 /** the URL which the document should report as its URL
156 This might differ from ->m_sDocFileLocation in case the document was loaded
157 as part of a crash recovery process. In this case, ->m_sDocFileLocation points to
158 the temporary file where the DB had been saved to, after a crash.
159 ->m_sDocumentURL then is the URL of the document which actually had
162 OUString m_sDocumentURL
;
164 SignatureState m_nScriptingSignatureState
;
167 OWeakConnectionArray m_aConnections
;
168 const css::uno::Reference
< css::uno::XComponentContext
> m_aContext
;
171 css::uno::WeakReference
< css::container::XNameAccess
> m_xCommandDefinitions
;
172 css::uno::WeakReference
< css::container::XNameAccess
> m_xTableDefinitions
;
174 css::uno::Reference
< css::util::XNumberFormatsSupplier
>
175 m_xNumberFormatsSupplier
;
176 OUString m_sConnectURL
;
177 OUString m_sName
; // transient, our creator has to tell us the title
179 OUString m_aPassword
; // transient !
180 OUString m_sFailedPassword
;
181 css::uno::Sequence
< css::beans::PropertyValue
>
182 m_aLayoutInformation
;
183 sal_Int32 m_nLoginTimeout
;
184 bool m_bReadOnly
: 1;
185 bool m_bPasswordRequired
: 1;
186 bool m_bSuppressVersionColumns
: 1;
187 bool m_bModified
: 1;
188 bool m_bDocumentReadOnly
: 1;
189 bool m_bMacroCallsSeenWhileLoading
: 1;
190 css::uno::Reference
< css::beans::XPropertyBag
>
192 css::uno::Sequence
< OUString
> m_aTableFilter
;
193 css::uno::Sequence
< OUString
> m_aTableTypeFilter
;
194 OSharedConnectionManager
* m_pSharedConnectionManager
;
195 css::uno::Reference
< css::lang::XEventListener
>
196 m_xSharedConnectionManager
;
197 css::uno::Reference
<css::awt::XWindow
>
199 sal_uInt16 m_nControllerLockCount
;
203 /** determines whether the database document has an embedded data storage
205 bool isEmbeddedDatabase() const { return m_sConnectURL
.startsWith("sdbc:embedded:"); }
207 /** stores the embedded storage ("database")
209 @param _bPreventRootCommits
210 Normally, committing the embedded storage results in also committing the root storage
211 - this is an automatism for data safety reasons.
212 If you pass <TRUE/> here, committing the root storage is prevented for this particular
214 @return <TRUE/> if the storage could be committed, otherwise <FALSE/>
216 bool commitEmbeddedStorage( bool _bPreventRootCommits
= false );
218 /// commits all sub storages
219 void commitStorages();
222 const css::uno::Reference
< css::uno::XComponentContext
>& _rxContext
,
223 ODatabaseContext
& _pDBContext
225 virtual ~ODatabaseModelImpl();
228 OUString _sRegistrationName
,
229 const css::uno::Reference
< css::uno::XComponentContext
>& _rxContext
,
230 ODatabaseContext
& _rDBContext
234 /// @throws css::uno::RuntimeException
235 void disposing( const css::lang::EventObject
& Source
);
237 void setModified( bool bModified
);
241 const OUString
& getURL() const { return m_sDocumentURL
; }
242 const OUString
& getDocFileLocation() const { return m_sDocFileLocation
; }
244 css::uno::Reference
< css::embed::XStorage
>
245 getStorage( const ObjectType _eType
);
248 const css::uno::Reference
< css::util::XNumberFormatsSupplier
>&
249 getNumberFormatsSupplier();
252 getDocumentEvents() { return m_aDocumentEvents
; }
254 const ::comphelper::NamedValueCollection
&
255 getMediaDescriptor() const { return m_aMediaDescriptor
; }
258 const OUString
& _rURL
,
259 const css::uno::Sequence
< css::beans::PropertyValue
>& _rArgs
261 void setDocFileLocation(
262 const OUString
& i_rLoadedFrom
265 static ::comphelper::NamedValueCollection
266 stripLoadArguments( const ::comphelper::NamedValueCollection
& _rArguments
);
270 // disposes all elements in m_aStorages, and clears it
271 void disposeStorages();
273 /// creates a ->css::embed::StorageFactory
274 css::uno::Reference
< css::lang::XSingleServiceFactory
>
275 createStorageFactory() const;
277 /// commits our storage
278 void commitRootStorage();
280 /// commits a given storage if it's not readonly, ignoring (but asserting) all errors
281 bool commitStorageIfWriteable_ignoreErrors(
282 const css::uno::Reference
< css::embed::XStorage
>& _rxStorage
285 void clearConnections();
287 css::uno::Reference
< css::embed::XStorage
> const & getOrCreateRootStorage();
288 css::uno::Reference
< css::embed::XStorage
> const & getRootStorage() const { return m_xDocumentStorage
.getTyped(); }
289 void resetRootStorage() { impl_switchToStorage_throw( nullptr ); }
291 /** returns the data source. If it doesn't exist it will be created
293 css::uno::Reference
< css::sdbc::XDataSource
> getOrCreateDataSource();
295 /** returns the model, if there already exists one
297 css::uno::Reference
< css::frame::XModel
> getModel_noCreate() const;
299 /** returns a new ->ODatabaseDocument
302 No ->ODatabaseDocument exists so far
307 css::uno::Reference
< css::frame::XModel
> createNewModel_deliverOwnership();
309 struct ResetModelAccess
{ friend class ODatabaseDocument
; private: ResetModelAccess() { } };
311 /** resets the model to NULL
313 Only to be called when the model is being disposed
315 void modelIsDisposing( const bool _wasInitialized
, ResetModelAccess
);
317 bool hadInitializedDocument() const { return m_bDocumentInitialized
; }
319 DocumentStorageAccess
*
320 getDocumentStorageAccess();
322 css::uno::Reference
< css::document::XDocumentSubStorageSupplier
>
323 getDocumentSubStorageSupplier();
329 /// returns all known data source settings, including their default values
330 static const AsciiPropertyValue
* getDefaultDataSourceSettings();
332 /** retrieves the requested container of objects (forms/reports/tables/queries)
334 TContentPtr
& getObjectContainer( const ObjectType _eType
);
336 /** returns the name of the storage which is used to stored objects of the given type, if applicable
339 getObjectContainerStorageName( const ObjectType _eType
);
341 /** determines whether a given object storage contains macros
343 static bool objectHasMacros(
344 const css::uno::Reference
< css::embed::XStorage
>& _rxContainerStorage
,
345 const OUString
& _rPersistentName
348 /** determines which kind of embedded macros are present in the document
350 EmbeddedMacros
determineEmbeddedMacros();
352 /** checks our document's macro execution mode, using the interaction handler as supplied with our
355 bool checkMacrosOnLoading();
357 /** adjusts our document's macro execution mode, without using any UI, assuming the user
358 would reject execution of macros, if she would have been asked.
360 If checkMacrosOnLoading has been called before (and thus the macro execution mode
361 is already adjusted), then the current execution mode is simply returned.
364 whether or not macro execution is allowed
366 bool adjustMacroMode_AutoReject();
368 /** resets our macro execute mode, so next time the checkMacrosOnLoading is called, it will
369 behave as if it has never been called before
371 void resetMacroExecutionMode();
373 /** ensures that ->m_xBasicLibraries resp. m_xDialogLibraries exists
376 the requested library container. Is never <NULL/>.
378 @throws RuntimeException
379 if something does wrong, which indicates a server error in the installation
381 css::uno::Reference
< css::script::XStorageBasedLibraryContainer
>
382 getLibraryContainer( bool _bScript
);
384 /** lets our library containers store themself into the given root storage
386 void storeLibraryContainersTo( const css::uno::Reference
< css::embed::XStorage
>& _rxToRootStorage
);
388 /** rebases the document to the given storage
390 No actual committing, copying, saving, whatsoever happens. The storage is just remembered as the documents
391 new storage, nothing more.
393 @throws css::lang::IllegalArgumentException
394 if the given storage is <NULL/>
395 @throws css::lang::RuntimeException
396 if any of the invoked operations does so
398 css::uno::Reference
< css::embed::XStorage
>
400 const css::uno::Reference
< css::embed::XStorage
>& _rxNewRootStorage
403 /** returns the macro mode imposed by an external instance, which passed it to attachResource
405 sal_Int16
getImposedMacroExecMode() const
407 return m_nImposedMacroExecMode
;
409 void setImposedMacroExecMode( const sal_Int16 _nMacroMode
)
411 m_nImposedMacroExecMode
= _nMacroMode
;
415 // IMacroDocumentAccess overridables
416 virtual sal_Int16
getCurrentMacroExecMode() const override
;
417 virtual void setCurrentMacroExecMode( sal_uInt16
) override
;
418 virtual OUString
getDocumentLocation() const override
;
419 virtual bool documentStorageHasMacros() const override
;
420 virtual bool macroCallsSeenWhileLoading() const override
;
421 virtual css::uno::Reference
< css::document::XEmbeddedScripts
> getEmbeddedDocumentScripts() const override
;
422 virtual SignatureState
getScriptingSignatureState() override
;
423 virtual bool hasTrustedScriptingSignature( bool bAllowUIToAddAuthor
) override
;
425 // IModifiableDocument
426 virtual void storageIsModified() override
;
428 // don't use directly, use the ModifyLock class instead
429 void lockModify() { m_bModificationLock
= true; }
430 void unlockModify() { m_bModificationLock
= false; }
431 bool isModifyLocked() const { return m_bModificationLock
; }
433 weld::Window
* GetFrameWeld();
436 void impl_construct_nothrow();
437 css::uno::Reference
< css::embed::XStorage
> const &
438 impl_switchToStorage_throw( const css::uno::Reference
< css::embed::XStorage
>& _rxNewRootStorage
);
440 /** switches to the given document URL, which denotes the logical URL of the document, not necessarily the
441 URL where the doc was loaded/recovered from
443 void impl_switchToLogicalURL(
444 const OUString
& i_rDocumentURL
449 /** a small base class for UNO components whose functionality depends on an ODatabaseModelImpl
451 class ModelDependentComponent
454 ::rtl::Reference
< ODatabaseModelImpl
> m_pImpl
;
455 ::osl::Mutex m_aMutex
; // only use this to init WeakComponentImplHelper
458 explicit ModelDependentComponent( ::rtl::Reference
< ODatabaseModelImpl
> _model
);
459 virtual ~ModelDependentComponent();
461 /** returns the component itself
463 virtual css::uno::Reference
< css::uno::XInterface
> getThis() const = 0;
465 ::osl::Mutex
& getMutex()
471 /// checks whether the component is already disposed, throws a DisposedException if so
472 void checkDisposed() const
475 throw css::lang::DisposedException( "Component is already disposed.", getThis() );
480 m_pImpl
->lockModify();
485 m_pImpl
->unlockModify();
492 explicit ModifyLock( ModelDependentComponent
& _component
)
493 :m_rComponent( _component
)
495 m_rComponent
.lockModify();
500 m_rComponent
.unlockModify();
504 ModelDependentComponent
& m_rComponent
;
507 /** a guard for public methods of objects dependent on an ODatabaseModelImpl instance
509 Just put this guard onto the stack at the beginning of your method. Don't bother yourself
510 with a MutexGuard, checks for being disposed, and the like.
512 class ModelMethodGuard
515 // to avoid deadlocks, lock SolarMutex
516 SolarMutexResettableGuard m_SolarGuard
;
519 /** constructs the guard
522 the component whose functionality depends on an ODatabaseModelImpl instance
524 @throws css::lang::DisposedException
525 If the given component is already disposed
527 explicit ModelMethodGuard( const ModelDependentComponent
& _component
)
529 _component
.checkDisposed();
534 // note: this only releases *once* so may still be locked
535 m_SolarGuard
.clear();
540 m_SolarGuard
.reset();
544 } // namespace dbaccess
546 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */