build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / dbaccess / source / core / dataaccess / ModelImpl.hxx
blob91452777ee62f52e7698e351af09fc6e2be7e72d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_DBACCESS_SOURCE_CORE_DATAACCESS_MODELIMPL_HXX
21 #define INCLUDED_DBACCESS_SOURCE_CORE_DATAACCESS_MODELIMPL_HXX
23 #include "apitools.hxx"
24 #include "bookmarkcontainer.hxx"
25 #include "ContentHelper.hxx"
26 #include "core_resource.hxx"
27 #include "documentevents.hxx"
29 #include <com/sun/star/beans/PropertyAttribute.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/beans/XPropertyBag.hpp>
32 #include <com/sun/star/container/XContainerListener.hpp>
33 #include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
34 #include <com/sun/star/document/XEventListener.hpp>
35 #include <com/sun/star/document/XStorageBasedDocument.hpp>
36 #include <com/sun/star/embed/ElementModes.hpp>
37 #include <com/sun/star/embed/XStorage.hpp>
38 #include <com/sun/star/embed/XTransactionListener.hpp>
39 #include <com/sun/star/frame/XModel.hpp>
40 #include <com/sun/star/frame/XStorable.hpp>
41 #include <com/sun/star/lang/NotInitializedException.hpp>
42 #include <com/sun/star/lang/XServiceInfo.hpp>
43 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
44 #include <com/sun/star/sdb/XBookmarksSupplier.hpp>
45 #include <com/sun/star/sdb/XCompletedConnection.hpp>
46 #include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
47 #include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
48 #include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
49 #include <com/sun/star/sdbc/XDataSource.hpp>
50 #include <com/sun/star/sdbc/XIsolatedConnection.hpp>
51 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
52 #include <com/sun/star/util/XCloseable.hpp>
53 #include <com/sun/star/util/XFlushable.hpp>
54 #include <com/sun/star/util/XModifiable.hpp>
55 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
56 #include <com/sun/star/util/XNumberFormatter.hpp>
57 #include <com/sun/star/util/XRefreshable.hpp>
58 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
59 #include <com/sun/star/frame/DoubleInitializationException.hpp>
61 #include <comphelper/broadcasthelper.hxx>
62 #include <comphelper/namedvaluecollection.hxx>
63 #include <comphelper/proparrhlp.hxx>
64 #include <comphelper/sharedmutex.hxx>
65 #include <comphelper/solarmutex.hxx>
66 #include <connectivity/CommonTools.hxx>
67 #include <cppuhelper/propshlp.hxx>
68 #include <cppuhelper/weakref.hxx>
69 #include <vcl/svapp.hxx>
70 #include <sfx2/docmacromode.hxx>
71 #include <sfx2/docstoragemodifylistener.hxx>
72 #include <unotools/sharedunocomponent.hxx>
73 #include <rtl/ref.hxx>
75 namespace comphelper
77 class NamedValueCollection;
80 namespace dbaccess
83 typedef std::vector< css::uno::WeakReference< css::sdbc::XConnection > > OWeakConnectionArray;
85 struct AsciiPropertyValue
87 // note: the canonic member order would be AsciiName / DefaultValue, but
88 // this crashes on unxlngi6.pro, since there's a bug which somehow results in
89 // getDefaultDataSourceSettings returning corrupted Any instances then.
90 css::uno::Any DefaultValue;
91 const sal_Char* AsciiName;
92 const css::uno::Type& ValueType;
94 AsciiPropertyValue()
95 :DefaultValue( )
96 ,AsciiName( nullptr )
97 ,ValueType( ::cppu::UnoType<void>::get() )
101 AsciiPropertyValue( const sal_Char* _pAsciiName, const css::uno::Any& _rDefaultValue )
102 :DefaultValue( _rDefaultValue )
103 ,AsciiName( _pAsciiName )
104 ,ValueType( _rDefaultValue.getValueType() )
106 OSL_ENSURE( ValueType.getTypeClass() != css::uno::TypeClass_VOID,
107 "AsciiPropertyValue::AsciiPropertyValue: NULL values not allowed here, use the other CTOR for this!" );
109 AsciiPropertyValue( const sal_Char* _pAsciiName, const css::uno::Type& _rValeType )
110 :DefaultValue()
111 ,AsciiName( _pAsciiName )
112 ,ValueType( _rValeType )
114 OSL_ENSURE( ValueType.getTypeClass() != css::uno::TypeClass_VOID,
115 "AsciiPropertyValue::AsciiPropertyValue: VOID property values not supported!" );
119 class ODatabaseContext;
120 class OSharedConnectionManager;
122 // VosMutexFacade
123 /** a class which provides an IMutex interface to an OSL-based mutex
125 class VosMutexFacade : public comphelper::SolarMutex
127 public:
128 /** beware of life time: the mutex you pass here must live as least as long
129 as the VosMutexFacade instance lives.
131 explicit VosMutexFacade( ::osl::Mutex& _rMutex );
133 virtual void acquire() override;
134 virtual void release() override;
135 virtual bool tryToAcquire() override;
137 private:
138 ::osl::Mutex& m_rMutex;
141 // ODatabaseModelImpl
142 typedef ::utl::SharedUNOComponent< css::embed::XStorage > SharedStorage;
144 class ODatabaseContext;
145 class DocumentStorageAccess;
146 class OSharedConnectionManager;
147 class ODatabaseModelImpl :public ::sfx2::IMacroDocumentAccess
148 ,public ::sfx2::IModifiableDocument
150 public:
151 enum ObjectType
153 E_FORM = 0,
154 E_REPORT = 1,
155 E_QUERY = 2,
156 E_TABLE = 3
159 enum EmbeddedMacros
161 // the database document (storage) itself contains macros
162 eDocumentWideMacros,
163 // there are sub document( storage)s containing macros
164 eSubDocumentMacros,
165 // there are no known macro( storage)s
166 eNoMacros
169 private:
170 OModuleClient m_aModuleClient;
171 css::uno::WeakReference< css::frame::XModel > m_xModel;
172 css::uno::WeakReference< css::sdbc::XDataSource > m_xDataSource;
174 rtl::Reference<DocumentStorageAccess> m_pStorageAccess;
175 ::comphelper::SharedMutex m_aMutex;
176 VosMutexFacade m_aMutexFacade;
177 ::std::vector< TContentPtr > m_aContainer; // one for each ObjectType
178 ::sfx2::DocumentMacroMode m_aMacroMode;
179 sal_Int16 m_nImposedMacroExecMode;
181 css::uno::Reference< css::script::XStorageBasedLibraryContainer > m_xBasicLibraries;
182 css::uno::Reference< css::script::XStorageBasedLibraryContainer > m_xDialogLibraries;
184 SharedStorage m_xDocumentStorage;
185 ::rtl::Reference< ::sfx2::DocumentStorageModifyListener > m_pStorageModifyListener;
186 ODatabaseContext& m_rDBContext;
187 DocumentEventsData m_aDocumentEvents;
189 ::comphelper::NamedValueCollection m_aMediaDescriptor;
190 /// the URL the document was loaded from
191 OUString m_sDocFileLocation;
193 oslInterlockedCount m_refCount;
195 /// do we have any object (forms/reports) which contains macros?
196 ::boost::optional< EmbeddedMacros > m_aEmbeddedMacros;
198 /// true if setting the Modified flag of the document is currently locked
199 bool m_bModificationLock;
201 /// true if and only if a database document existed previously (though meanwhile disposed), and was already initialized
202 bool m_bDocumentInitialized;
204 /** the URL which the document should report as its URL
206 This might differ from ->m_sDocFileLocation in case the document was loaded
207 as part of a crash recovery process. In this case, ->m_sDocFileLocation points to
208 the temporary file where the DB had been saved to, after a crash.
209 ->m_sDocumentURL then is the URL of the document which actually had
210 been recovered.
212 OUString m_sDocumentURL;
214 public:
215 OWeakConnectionArray m_aConnections;
216 const css::uno::Reference< css::uno::XComponentContext > m_aContext;
218 public:
219 css::uno::WeakReference< css::container::XNameAccess > m_xCommandDefinitions;
220 css::uno::WeakReference< css::container::XNameAccess > m_xTableDefinitions;
222 css::uno::Reference< css::util::XNumberFormatsSupplier >
223 m_xNumberFormatsSupplier;
224 OUString m_sConnectURL;
225 OUString m_sName; // transient, our creator has to tell us the title
226 OUString m_sUser;
227 OUString m_aPassword; // transient !
228 OUString m_sFailedPassword;
229 css::uno::Sequence< css::beans::PropertyValue>
230 m_aLayoutInformation;
231 sal_Int32 m_nLoginTimeout;
232 bool m_bReadOnly : 1;
233 bool m_bPasswordRequired : 1;
234 bool m_bSuppressVersionColumns : 1;
235 bool m_bModified : 1;
236 bool m_bDocumentReadOnly : 1;
237 css::uno::Reference< css::beans::XPropertyBag >
238 m_xSettings;
239 css::uno::Sequence< OUString > m_aTableFilter;
240 css::uno::Sequence< OUString > m_aTableTypeFilter;
241 OSharedConnectionManager* m_pSharedConnectionManager;
242 css::uno::Reference< css::lang::XEventListener >
243 m_xSharedConnectionManager;
244 sal_uInt16 m_nControllerLockCount;
246 void reset();
248 /** determines whether the database document has an embedded data storage
250 inline bool isEmbeddedDatabase() const { return ( m_sConnectURL.startsWith("sdbc:embedded:") ); }
252 /** stores the embedded storage ("database")
254 @param _bPreventRootCommits
255 Normally, committing the embedded storage results in also committing the root storage
256 - this is an automatism for data safety reasons.
257 If you pass <TRUE/> here, committing the root storage is prevented for this particular
258 call.
259 @return <TRUE/> if the storage could be committed, otherwise <FALSE/>
261 bool commitEmbeddedStorage( bool _bPreventRootCommits = false );
263 /// commits all sub storages
264 void commitStorages();
266 ODatabaseModelImpl(
267 const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
268 ODatabaseContext& _pDBContext
270 virtual ~ODatabaseModelImpl();
272 ODatabaseModelImpl(
273 const OUString& _rRegistrationName,
274 const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
275 ODatabaseContext& _rDBContext
278 // XEventListener
279 /// @throws css::uno::RuntimeException
280 void SAL_CALL disposing( const css::lang::EventObject& Source ) throw(css::uno::RuntimeException);
282 void setModified( bool bModified );
284 void dispose();
286 const OUString& getURL() const { return m_sDocumentURL; }
287 const OUString& getDocFileLocation() const { return m_sDocFileLocation; }
289 css::uno::Reference< css::embed::XStorage >
290 getStorage( const ObjectType _eType );
292 // helper
293 const css::uno::Reference< css::util::XNumberFormatsSupplier >&
294 getNumberFormatsSupplier();
296 DocumentEventsData&
297 getDocumentEvents() { return m_aDocumentEvents; }
299 const ::comphelper::NamedValueCollection&
300 getMediaDescriptor() const { return m_aMediaDescriptor; }
302 void setResource(
303 const OUString& _rURL,
304 const css::uno::Sequence< css::beans::PropertyValue >& _rArgs
306 void setDocFileLocation(
307 const OUString& i_rLoadedFrom
310 static ::comphelper::NamedValueCollection
311 stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments );
313 // other stuff
315 // disposes all elements in m_aStorages, and clears it
316 void disposeStorages();
318 /// creates a ->css::embed::StorageFactory
319 css::uno::Reference< css::lang::XSingleServiceFactory >
320 createStorageFactory() const;
322 /// commits our storage
323 void commitRootStorage();
325 /// commits a given storage if it's not readonly, ignoring (but asserting) all errors
326 static bool commitStorageIfWriteable_ignoreErrors(
327 const css::uno::Reference< css::embed::XStorage >& _rxStorage
330 void clearConnections();
332 css::uno::Reference< css::embed::XStorage > getOrCreateRootStorage();
333 inline css::uno::Reference< css::embed::XStorage > getRootStorage() const { return m_xDocumentStorage.getTyped(); }
334 inline void resetRootStorage() { impl_switchToStorage_throw( nullptr ); }
336 /** returns the data source. If it doesn't exist it will be created
338 css::uno::Reference< css::sdbc::XDataSource> getOrCreateDataSource();
340 /** returns the model, if there already exists one
342 css::uno::Reference< css::frame::XModel > getModel_noCreate() const;
344 /** returns a new ->ODatabaseDocument
346 @precond
347 No ->ODatabaseDocument exists so far
349 @seealso
350 getModel_noCreate
352 css::uno::Reference< css::frame::XModel > createNewModel_deliverOwnership();
354 struct ResetModelAccess { friend class ODatabaseDocument; private: ResetModelAccess() { } };
356 /** resets the model to NULL
358 Only to be called when the model is being disposed
360 void modelIsDisposing( const bool _wasInitialized, ResetModelAccess );
362 bool hadInitializedDocument() const { return m_bDocumentInitialized; }
364 DocumentStorageAccess*
365 getDocumentStorageAccess();
367 css::uno::Reference< css::document::XDocumentSubStorageSupplier >
368 getDocumentSubStorageSupplier();
370 inline const ::comphelper::SharedMutex& getSharedMutex() const { return m_aMutex; }
372 void SAL_CALL acquire();
374 void SAL_CALL release();
376 /// returns a all known data source settings, including their default values
377 static const AsciiPropertyValue* getDefaultDataSourceSettings();
379 /** retrieves the requested container of objects (forms/reports/tables/queries)
381 TContentPtr& getObjectContainer( const ObjectType _eType );
383 /** returns the name of the storage which is used to stored objects of the given type, if applicable
385 static OUString
386 getObjectContainerStorageName( const ObjectType _eType );
388 /** determines whether a given object storage contains macros
390 static bool objectHasMacros(
391 const css::uno::Reference< css::embed::XStorage >& _rxContainerStorage,
392 const OUString& _rPersistentName
395 /** determines which kind of embedded macros are present in the document
397 EmbeddedMacros determineEmbeddedMacros();
399 /** checks our document's macro execution mode, using the interaction handler as supplied with our
400 load arguments
402 bool checkMacrosOnLoading();
404 /** adjusts our document's macro execution mode, without using any UI, assuming the user
405 would reject execution of macros, if she would have been asked.
407 If checkMacrosOnLoading has been called before (and thus the macro execution mode
408 is already adjusted), then the current execution mode is simply returned.
410 @return
411 whether or not macro execution is allowed
413 bool adjustMacroMode_AutoReject();
415 /** resets our macro execute mode, so next time the checkMacrosOnLoading is called, it will
416 behave as if it has never been called before
418 void resetMacroExecutionMode();
420 /** ensures that ->m_xBasicLibraries resp. m_xDialogLibraries exists
422 @return
423 the requested library container. Is never <NULL/>.
425 @throws RuntimeException
426 if something does wrong, which indicates a server error in the installation
428 css::uno::Reference< css::script::XStorageBasedLibraryContainer >
429 getLibraryContainer( bool _bScript );
431 /** lets our library containers store themself into the given root storage
433 void storeLibraryContainersTo( const css::uno::Reference< css::embed::XStorage >& _rxToRootStorage );
435 /** rebases the document to the given storage
437 No actual committing, copying, saving, whatsoever happens. The storage is just remembered as the documents
438 new storage, nothing more.
440 @throws css::lang::IllegalArgumentException
441 if the given storage is <NULL/>
442 @throws css::lang::RuntimeException
443 if any of the invoked operations does so
445 css::uno::Reference< css::embed::XStorage >
446 switchToStorage(
447 const css::uno::Reference< css::embed::XStorage >& _rxNewRootStorage
450 /** returns the macro mode imposed by an external instance, which passed it to attachResource
452 sal_Int16 getImposedMacroExecMode() const
454 return m_nImposedMacroExecMode;
456 void setImposedMacroExecMode( const sal_Int16 _nMacroMode )
458 m_nImposedMacroExecMode = _nMacroMode;
461 public:
462 // IMacroDocumentAccess overridables
463 virtual sal_Int16 getCurrentMacroExecMode() const override;
464 virtual void setCurrentMacroExecMode( sal_uInt16 ) override;
465 virtual OUString getDocumentLocation() const override;
466 virtual bool documentStorageHasMacros() const override;
467 virtual css::uno::Reference< css::document::XEmbeddedScripts > getEmbeddedDocumentScripts() const override;
468 virtual SignatureState getScriptingSignatureState() override;
469 virtual bool hasTrustedScriptingSignature( bool bAllowUIToAddAuthor ) override;
470 virtual void showBrokenSignatureWarning( const css::uno::Reference< css::task::XInteractionHandler >& _rxInteraction ) const override;
472 // IModifiableDocument
473 virtual void storageIsModified() override;
475 // don't use directly, use the ModifyLock class instead
476 void lockModify() { m_bModificationLock = true; }
477 void unlockModify() { m_bModificationLock = false; }
478 bool isModifyLocked() const { return m_bModificationLock; }
480 private:
481 void impl_construct_nothrow();
482 css::uno::Reference< css::embed::XStorage >
483 impl_switchToStorage_throw( const css::uno::Reference< css::embed::XStorage >& _rxNewRootStorage );
485 /** switches to the given document URL, which denotes the logical URL of the document, not necessarily the
486 URL where the doc was loaded/recovered from
488 void impl_switchToLogicalURL(
489 const OUString& i_rDocumentURL
494 /** a small base class for UNO components whose functionality depends on a ODatabaseModelImpl
496 class ModelDependentComponent
498 protected:
499 ::rtl::Reference< ODatabaseModelImpl > m_pImpl;
500 mutable ::comphelper::SharedMutex m_aMutex;
502 protected:
503 explicit ModelDependentComponent( const ::rtl::Reference< ODatabaseModelImpl >& _model );
504 virtual ~ModelDependentComponent();
506 /** returns the component itself
508 virtual css::uno::Reference< css::uno::XInterface > getThis() const = 0;
510 inline ::osl::Mutex& getMutex() const
512 return m_aMutex;
515 public:
516 struct GuardAccess { friend class ModelMethodGuard; private: GuardAccess() { } };
518 /** returns the mutex used for thread safety
520 @throws css::lang::DisposedException
521 if m_pImpl is <NULL/>. Usually, you will set this member in your derived
522 component's <code>dispose</code> method to <NULL/>.
524 inline ::osl::Mutex& getMutex( GuardAccess ) const
526 return getMutex();
529 /// checks whether the component is already disposed, throws a DisposedException if so
530 inline void checkDisposed() const
532 if ( !m_pImpl.is() )
533 throw css::lang::DisposedException( "Component is already disposed.", getThis() );
536 inline void lockModify()
538 m_pImpl->lockModify();
541 inline void unlockModify()
543 m_pImpl->unlockModify();
547 class ModifyLock
549 public:
550 explicit ModifyLock( ModelDependentComponent& _component )
551 :m_rComponent( _component )
553 m_rComponent.lockModify();
556 ~ModifyLock()
558 m_rComponent.unlockModify();
561 private:
562 ModelDependentComponent& m_rComponent;
565 /** a guard for public methods of objects dependent on a ODatabaseModelImpl instance
567 Just put this guard onto the stack at the beginning of your method. Don't bother yourself
568 with a MutexGuard, checks for being disposed, and the like.
570 class ModelMethodGuard
572 private:
573 // to avoid deadlocks, lock SolarMutex too, and before the own osl::Mutex
574 SolarMutexResettableGuard m_SolarGuard;
575 ::osl::ResettableMutexGuard m_OslGuard;
577 typedef ::osl::ResettableMutexGuard BaseMutexGuard;
579 public:
580 /** constructs the guard
582 @param _component
583 the component whose functionality depends on a ODatabaseModelImpl instance
585 @throws css::lang::DisposedException
586 If the given component is already disposed
588 explicit ModelMethodGuard( const ModelDependentComponent& _component )
589 : m_OslGuard(_component.getMutex(ModelDependentComponent::GuardAccess()))
591 _component.checkDisposed();
594 void clear()
596 m_OslGuard.clear();
597 // note: this only releases *once* so may still be locked
598 m_SolarGuard.clear(); // SolarMutex last
601 void reset()
603 m_SolarGuard.reset(); // SolarMutex first
604 m_OslGuard.reset();
607 ~ModelMethodGuard()
612 } // namespace dbaccess
614 #endif // _DBA_COREDATAACCESS_DATALINK_HXX_
616 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */