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 .
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 <sfx2/docmacromode.hxx>
70 #include <sfx2/docstoragemodifylistener.hxx>
71 #include <unotools/sharedunocomponent.hxx>
72 #include <rtl/ref.hxx>
76 class NamedValueCollection
;
82 typedef ::com::sun::star::uno::WeakReference
< ::com::sun::star::sdbc::XConnection
> OWeakConnection
;
83 typedef std::vector
< OWeakConnection
> 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 ::com::sun::star::uno::Any DefaultValue
;
91 const sal_Char
* AsciiName
;
92 const ::com::sun::star::uno::Type
& ValueType
;
97 ,ValueType( ::cppu::UnoType
<void>::get() )
101 AsciiPropertyValue( const sal_Char
* _pAsciiName
, const ::com::sun::star::uno::Any
& _rDefaultValue
)
102 :DefaultValue( _rDefaultValue
)
103 ,AsciiName( _pAsciiName
)
104 ,ValueType( _rDefaultValue
.getValueType() )
106 OSL_ENSURE( ValueType
.getTypeClass() != ::com::sun::star::uno::TypeClass_VOID
,
107 "AsciiPropertyValue::AsciiPropertyValue: NULL values not allowed here, use the other CTOR for this!" );
109 AsciiPropertyValue( const sal_Char
* _pAsciiName
, const ::com::sun::star::uno::Type
& _rValeType
)
111 ,AsciiName( _pAsciiName
)
112 ,ValueType( _rValeType
)
114 OSL_ENSURE( ValueType
.getTypeClass() != ::com::sun::star::uno::TypeClass_VOID
,
115 "AsciiPropertyValue::AsciiPropertyValue: VOID property values not supported!" );
119 class ODatabaseContext
;
120 class OSharedConnectionManager
;
123 /** a class which provides an IMutex interface to an OSL-based mutex
125 class VosMutexFacade
: public comphelper::SolarMutex
128 /** beware of life time: the mutex you pass here must live as least as long
129 as the VosMutexFacade instance lives.
131 VosMutexFacade( ::osl::Mutex
& _rMutex
);
133 virtual void acquire() SAL_OVERRIDE
;
134 virtual void release() SAL_OVERRIDE
;
135 virtual bool tryToAcquire() SAL_OVERRIDE
;
138 ::osl::Mutex
& m_rMutex
;
141 // ODatabaseModelImpl
142 typedef ::utl::SharedUNOComponent
< ::com::sun::star::embed::XStorage
> SharedStorage
;
144 class ODatabaseContext
;
145 class DocumentStorageAccess
;
146 class OSharedConnectionManager
;
147 class ODatabaseModelImpl
:public ::sfx2::IMacroDocumentAccess
148 ,public ::sfx2::IModifiableDocument
161 // the database document (storage) itself contains macros
163 // there are sub document( storage)s containing macros
165 // there are no known macro( storage)s
170 OModuleClient m_aModuleClient
;
171 ::com::sun::star::uno::WeakReference
< ::com::sun::star::frame::XModel
> m_xModel
;
172 ::com::sun::star::uno::WeakReference
< ::com::sun::star::sdbc::XDataSource
> m_xDataSource
;
174 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 ::com::sun::star::uno::Reference
< ::com::sun::star::script::XStorageBasedLibraryContainer
> m_xBasicLibraries
;
182 ::com::sun::star::uno::Reference
< ::com::sun::star::script::XStorageBasedLibraryContainer
> m_xDialogLibraries
;
184 SharedStorage m_xDocumentStorage
;
185 ::rtl::Reference
< ::sfx2::DocumentStorageModifyListener
> m_pStorageModifyListener
;
186 ODatabaseContext
* m_pDBContext
;
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
212 OUString m_sDocumentURL
;
215 OWeakConnectionArray m_aConnections
;
216 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
> m_aContext
;
219 ::com::sun::star::uno::WeakReference
< ::com::sun::star::container::XNameAccess
> m_xCommandDefinitions
;
220 ::com::sun::star::uno::WeakReference
< ::com::sun::star::container::XNameAccess
> m_xTableDefinitions
;
222 ::com::sun::star::uno::Reference
< ::com::sun::star::util::XNumberFormatsSupplier
>
223 m_xNumberFormatsSupplier
;
224 OUString m_sConnectURL
;
225 OUString m_sName
; // transient, our creator has to tell us the title
227 OUString m_aPassword
; // transient !
228 OUString m_sFailedPassword
;
229 ::com::sun::star::uno::Sequence
< ::com::sun::star::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 ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertyBag
>
239 ::com::sun::star::uno::Sequence
< OUString
> m_aTableFilter
;
240 ::com::sun::star::uno::Sequence
< OUString
> m_aTableTypeFilter
;
241 OSharedConnectionManager
* m_pSharedConnectionManager
;
242 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XEventListener
>
243 m_xSharedConnectionManager
;
244 sal_uInt16 m_nControllerLockCount
;
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
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();
267 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
>& _rxContext
,
268 ODatabaseContext
& _pDBContext
270 virtual ~ODatabaseModelImpl();
273 const OUString
& _rRegistrationName
,
274 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
>& _rxContext
,
275 ODatabaseContext
& _rDBContext
279 void SAL_CALL
disposing( const ::com::sun::star::lang::EventObject
& Source
) throw(::com::sun::star::uno::RuntimeException
);
281 void setModified( bool bModified
);
285 inline OUString
getURL() const { return m_sDocumentURL
; }
286 inline OUString
getDocFileLocation() const { return m_sDocFileLocation
; }
288 ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>
290 const ObjectType _eType
, const sal_Int32 _nDesiredMode
= ::com::sun::star::embed::ElementModes::READWRITE
);
293 const ::com::sun::star::uno::Reference
< ::com::sun::star::util::XNumberFormatsSupplier
>&
294 getNumberFormatsSupplier();
297 getDocumentEvents() { return m_aDocumentEvents
; }
299 const ::comphelper::NamedValueCollection
&
300 getMediaDescriptor() const { return m_aMediaDescriptor
; }
303 const OUString
& _rURL
,
304 const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& _rArgs
306 void setDocFileLocation(
307 const OUString
& i_rLoadedFrom
310 static ::comphelper::NamedValueCollection
311 stripLoadArguments( const ::comphelper::NamedValueCollection
& _rArguments
);
316 // disposes all elements in m_aStorages, and clears it
317 void disposeStorages();
319 /// creates a ->com::sun::star::embed::StorageFactory
320 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XSingleServiceFactory
>
321 createStorageFactory() const;
323 /// commits our storage
324 void commitRootStorage();
326 /// commits a given storage if it's not readonly, ignoring (but asserting) all errors
327 static bool commitStorageIfWriteable_ignoreErrors(
328 const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>& _rxStorage
331 void clearConnections();
333 ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
> getOrCreateRootStorage();
334 inline ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
> getRootStorage() const { return m_xDocumentStorage
.getTyped(); }
335 inline void resetRootStorage() { impl_switchToStorage_throw( NULL
); }
337 /** returns the data source. If it doesn't exist it will be created
339 ::com::sun::star::uno::Reference
< ::com::sun::star::sdbc::XDataSource
> getOrCreateDataSource();
341 /** returns the model, if there already exists one
343 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XModel
> getModel_noCreate() const;
345 /** returns a new ->ODatabaseDocument
347 @param _bInitializeIfNecessary
348 calls XLoadable::initNew on the newly created model, if necessary
351 No ->ODatabaseDocument exists so far
356 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XModel
> createNewModel_deliverOwnership( bool _bInitialize
);
358 struct ResetModelAccess
{ friend class ODatabaseDocument
; private: ResetModelAccess() { } };
360 /** resets the model to NULL
362 Only to be called when the model is being disposed
364 void modelIsDisposing( const bool _wasInitialized
, ResetModelAccess
);
366 bool hadInitializedDocument() const { return m_bDocumentInitialized
; }
368 DocumentStorageAccess
*
369 getDocumentStorageAccess();
371 ::com::sun::star::uno::Reference
< ::com::sun::star::document::XDocumentSubStorageSupplier
>
372 getDocumentSubStorageSupplier();
374 inline const ::comphelper::SharedMutex
& getSharedMutex() const { return m_aMutex
; }
376 void SAL_CALL
acquire();
378 void SAL_CALL
release();
380 /// returns a all known data source settings, including their default values
381 static const AsciiPropertyValue
* getDefaultDataSourceSettings();
383 /** retrieves the requested container of objects (forms/reports/tables/queries)
385 TContentPtr
& getObjectContainer( const ObjectType _eType
);
387 /** returns the name of the storage which is used to stored objects of the given type, if applicable
390 getObjectContainerStorageName( const ObjectType _eType
);
392 /** revokes the data source registration at the database context
394 void revokeDataSource() const;
396 /** determines whether a given object storage contains macros
398 static bool objectHasMacros(
399 const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>& _rxContainerStorage
,
400 const OUString
& _rPersistentName
403 /** determines which kind of embedded macros are present in the document
405 EmbeddedMacros
determineEmbeddedMacros();
407 /** checks our document's macro execution mode, using the interaction handler as supplied with our
410 bool checkMacrosOnLoading();
412 /** adjusts our document's macro execution mode, without using any UI, assuming the user
413 would reject execution of macros, if she would have been asked.
415 If checkMacrosOnLoading has been called before (and thus the macro execution mode
416 is already adjusted), then the current execution mode is simply returned.
419 whether or not macro execution is allowed
421 bool adjustMacroMode_AutoReject();
423 /** resets our macro execute mode, so next time the checkMacrosOnLoading is called, it will
424 behave as if it has never been called before
426 void resetMacroExecutionMode();
428 /** ensures that ->m_xBasicLibraries resp. m_xDialogLibraries exists
431 the requested library container. Is never <NULL/>.
433 @throws RuntimeException
434 if something does wrong, which indicates a server error in the installation
436 ::com::sun::star::uno::Reference
< ::com::sun::star::script::XStorageBasedLibraryContainer
>
437 getLibraryContainer( bool _bScript
);
439 /** lets our library containers store themself into the given root storage
441 void storeLibraryContainersTo( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>& _rxToRootStorage
);
443 /** rebases the document to the given storage
445 No actual committing, copying, saving, whatsoever happens. The storage is just remembered as the documents
446 new storage, nothing more.
448 @throws ::com::sun::star::lang::IllegalArgumentException
449 if the given storage is <NULL/>
450 @throws ::com::sun::star::lang::RuntimeException
451 if any of the invoked operations does so
453 ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>
455 const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>& _rxNewRootStorage
458 /** returns the macro mode imposed by an external instance, which passed it to attachResource
460 sal_Int16
getImposedMacroExecMode() const
462 return m_nImposedMacroExecMode
;
464 void setImposedMacroExecMode( const sal_Int16 _nMacroMode
)
466 m_nImposedMacroExecMode
= _nMacroMode
;
470 // IMacroDocumentAccess overridables
471 virtual sal_Int16
getCurrentMacroExecMode() const SAL_OVERRIDE
;
472 virtual bool setCurrentMacroExecMode( sal_uInt16
) SAL_OVERRIDE
;
473 virtual OUString
getDocumentLocation() const SAL_OVERRIDE
;
474 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
> getZipStorageToSign() SAL_OVERRIDE
;
475 virtual bool documentStorageHasMacros() const SAL_OVERRIDE
;
476 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::document::XEmbeddedScripts
> getEmbeddedDocumentScripts() const SAL_OVERRIDE
;
477 virtual SignatureState
getScriptingSignatureState() SAL_OVERRIDE
;
478 virtual bool hasTrustedScriptingSignature( bool bAllowUIToAddAuthor
) SAL_OVERRIDE
;
479 virtual void showBrokenSignatureWarning( const ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>& _rxInteraction
) const SAL_OVERRIDE
;
481 // IModifiableDocument
482 virtual void storageIsModified() SAL_OVERRIDE
;
484 // don't use directly, use the ModifyLock class instead
485 void lockModify() { m_bModificationLock
= true; }
486 void unlockModify() { m_bModificationLock
= false; }
487 bool isModifyLocked() const { return m_bModificationLock
; }
490 void impl_construct_nothrow();
491 ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>
492 impl_switchToStorage_throw( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>& _rxNewRootStorage
);
494 /** switches to the given document URL, which denotes the logical URL of the document, not necessariy the
495 URL where the doc was loaded/recovered from
497 void impl_switchToLogicalURL(
498 const OUString
& i_rDocumentURL
503 /** a small base class for UNO components whose functionality depends on a ODatabaseModelImpl
505 class ModelDependentComponent
508 ::rtl::Reference
< ODatabaseModelImpl
> m_pImpl
;
509 mutable ::comphelper::SharedMutex m_aMutex
;
512 ModelDependentComponent( const ::rtl::Reference
< ODatabaseModelImpl
>& _model
);
513 virtual ~ModelDependentComponent();
515 /** returns the component itself
517 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> getThis() const = 0;
519 inline ::osl::Mutex
& getMutex() const
525 struct GuardAccess
{ friend class ModelMethodGuard
; private: GuardAccess() { } };
527 /** returns the mutex used for thread safety
529 @throws ::com::sun::star::lang::DisposedException
530 if m_pImpl is <NULL/>. Usually, you will set this member in your derived
531 component's <code>dispose</code> method to <NULL/>.
533 inline ::osl::Mutex
& getMutex( GuardAccess
) const
537 inline ::rtl::Reference
< ODatabaseModelImpl
> getImpl( GuardAccess
) const
542 /// checks whether the component is already disposed, throws a DisposedException if so
543 inline void checkDisposed() const
546 throw ::com::sun::star::lang::DisposedException( "Component is already disposed.", getThis() );
549 inline void lockModify()
551 m_pImpl
->lockModify();
554 inline void unlockModify()
556 m_pImpl
->unlockModify();
563 ModifyLock( ModelDependentComponent
& _component
)
564 :m_rComponent( _component
)
566 m_rComponent
.lockModify();
571 m_rComponent
.unlockModify();
575 ModelDependentComponent
& m_rComponent
;
578 /** a guard for public methods of objects dependent on a ODatabaseModelImpl instance
580 Just put this guard onto the stack at the beginning of your method. Don't bother yourself
581 with a MutexGuard, checks for being disposed, and the like.
583 class ModelMethodGuard
: public ::osl::ResettableMutexGuard
586 typedef ::osl::ResettableMutexGuard BaseMutexGuard
;
589 /** constructs the guard
592 the component whose functionality depends on a ODatabaseModelImpl instance
594 @throws ::com::sun::star::lang::DisposedException
595 If the given component is already disposed
597 ModelMethodGuard( const ModelDependentComponent
& _component
)
598 :BaseMutexGuard( _component
.getMutex( ModelDependentComponent::GuardAccess() ) )
600 _component
.checkDisposed();
608 } // namespace dbaccess
610 #endif // _DBA_COREDATAACCESS_DATALINK_HXX_
612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */