/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project .
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2 . 0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice :
*
* Licensed to the Apache Software Foundation ( ASF ) under one or more
* contributor license agreements . See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership . The ASF licenses this file to you under the Apache
* License , Version 2 . 0 ( the " License " ) ; you may not use this file
* except in compliance with the License . You may obtain a copy of
* the License at http : //www.apache.org/licenses/LICENSE-2.0 .
*/
#pragma once
#include "ContentHelper.hxx"
#include "documentevents.hxx"
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/XPropertyBag.hpp>
#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/lang/XEventListener.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/reflection/ProxyFactory.hpp>
#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
#include <com/sun/star/sdbc/XDataSource.hpp>
#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
#include <comphelper/namedvaluecollection.hxx>
#include <cppuhelper/weakref.hxx>
#include <vcl/svapp.hxx>
#include <sfx2/docmacromode.hxx>
#include <sfx2/docstoragemodifylistener.hxx>
#include <unotools/sharedunocomponent.hxx>
#include <rtl/digest.h>
#include <rtl/ref.hxx>
#include <o3tl/enumarray.hxx>
#include <unotools/weakref.hxx>
#include <span>
namespace dbaccess
{
class OCommandContainer;
class OConnection;
typedef std::vector< css::uno::WeakReference< css::sdbc::XConnection > > OWeakConnectionArray;
struct DefaultPropertyValue
{
OUString Name;
css::uno::Any DefaultValue;
const css::uno::Type& ValueType;
DefaultPropertyValue(const OUString& _aName, const css::uno::Any& _rDefaultValue)
:Name( _aName )
,DefaultValue( _rDefaultValue )
,ValueType( _rDefaultValue.getValueType() )
{
OSL_ENSURE( ValueType.getTypeClass() != css::uno::TypeClass_VOID,
"AsciiPropertyValue::AsciiPropertyValue: NULL values not allowed here, use the other CTOR for this!" );
}
DefaultPropertyValue(const OUString& _aName, const css::uno::Type& _rValeType)
:Name( _aName )
,ValueType( _rValeType )
{
OSL_ENSURE( ValueType.getTypeClass() != css::uno::TypeClass_VOID,
"AsciiPropertyValue::AsciiPropertyValue: VOID property values not supported!" );
}
};
// ODatabaseModelImpl
typedef ::utl::SharedUNOComponent< css::embed::XStorage > SharedStorage;
class ODatabaseContext;
class DocumentStorageAccess;
class ODatabaseSource;
class ODatabaseDocument;
/** The class OSharedConnectionManager implements a structure to share connections.
It owns the master connections which will be disposed when the last connection proxy is gone .
*/
// need to hold the digest
struct TDigestHolder
{
sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1];
TDigestHolder()
{
m_pBuffer[0 ] = 0 ;
}
};
class OSharedConnectionManager : public ::cppu::WeakImplHelper< css::lang::XEventListener >
{
// contains the currently used master connections
struct TConnectionHolder
{
rtl::Reference< OConnection > xMasterConnection;
oslInterlockedCount nALiveCount;
};
// the less-compare functor, used for the stl::map
struct TDigestLess
{
bool operator () (const TDigestHolder& x, const TDigestHolder& y) const
{
sal_uInt32 i;
for (i=0 ;i < RTL_DIGEST_LENGTH_SHA1 && (x.m_pBuffer[i] >= y.m_pBuffer[i]); ++i)
;
return i < RTL_DIGEST_LENGTH_SHA1;
}
};
typedef std::map< TDigestHolder,TConnectionHolder,TDigestLess> TConnectionMap; // holds the master connections
typedef std::map< css::uno::Reference< css::sdbc::XConnection >,TConnectionMap::iterator> TSharedConnectionMap;// holds the shared connections
::osl::Mutex m_aMutex;
TConnectionMap m_aConnections; // remember the master connection in conjunction with the digest
TSharedConnectionMap m_aSharedConnection; // the shared connections with conjunction with an iterator into the connections map
css::uno::Reference< css::reflection::XProxyFactory > m_xProxyFactory;
protected :
virtual ~OSharedConnectionManager() override;
public :
explicit OSharedConnectionManager(const css::uno::Reference< css::uno::XComponentContext >& _rxContext);
void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
css::uno::Reference< css::sdbc::XConnection > getConnection( const OUString& url,
const OUString& user,
const OUString& password,
const css::uno::Sequence< css::beans::PropertyValue >& _aInfo,
ODatabaseSource* _pDataSource);
void addEventListener(const css::uno::Reference< css::sdbc::XConnection >& _rxConnection, TConnectionMap::iterator const & _rIter);
};
class ODatabaseModelImpl :public ::sfx2::IMacroDocumentAccess
,public ::sfx2::IModifiableDocument
{
public :
enum class ObjectType
{
Form = 0 ,
Report = 1 ,
Query = 2 ,
Table = 3 ,
LAST = Table
};
enum class EmbeddedMacros
{
// the database document (storage) itself contains macros
DocumentWide,
// there are sub document( storage)s containing macros
SubDocument,
// there are no known macro( storage)s
NONE
};
private :
unotools::WeakReference< ODatabaseDocument > m_xModel;
unotools::WeakReference< ODatabaseSource > m_xDataSource;
rtl::Reference<DocumentStorageAccess> m_pStorageAccess;
o3tl::enumarray< ObjectType, TContentPtr > m_aContainer; // one for each ObjectType
::sfx2::DocumentMacroMode m_aMacroMode;
sal_Int16 m_nImposedMacroExecMode;
css::uno::Reference< css::script::XStorageBasedLibraryContainer > m_xBasicLibraries;
css::uno::Reference< css::script::XStorageBasedLibraryContainer > m_xDialogLibraries;
SharedStorage m_xDocumentStorage;
::rtl::Reference< ::sfx2::DocumentStorageModifyListener > m_pStorageModifyListener;
ODatabaseContext& m_rDBContext;
DocumentEventsData m_aDocumentEvents;
::comphelper::NamedValueCollection m_aMediaDescriptor;
/// the URL the document was loaded from
OUString m_sDocFileLocation;
oslInterlockedCount m_refCount;
/// do we have any object (forms/reports) which contains macros?
::std::optional< EmbeddedMacros > m_aEmbeddedMacros;
/// true if setting the Modified flag of the document is currently locked
bool m_bModificationLock;
/// true if and only if a database document existed previously (though meanwhile disposed), and was already initialized
bool m_bDocumentInitialized;
/** the URL which the document should report as its URL
This might differ from - > m_sDocFileLocation in case the document was loaded
as part of a crash recovery process . In this case , - > m_sDocFileLocation points to
the temporary file where the DB had been saved to , after a crash .
- > m_sDocumentURL then is the URL of the document which actually had
been recovered .
*/
OUString m_sDocumentURL;
SignatureState m_nScriptingSignatureState;
public :
OWeakConnectionArray m_aConnections;
const css::uno::Reference< css::uno::XComponentContext > m_aContext;
public :
css::uno::WeakReference< css::container::XNameAccess > m_xCommandDefinitions;
unotools::WeakReference< ::dbaccess::OCommandContainer > m_xTableDefinitions;
css::uno::Reference< css::util::XNumberFormatsSupplier >
m_xNumberFormatsSupplier;
OUString m_sConnectURL;
OUString m_sName; // transient, our creator has to tell us the title
OUString m_sUser;
OUString m_aPassword; // transient !
OUString m_sFailedPassword;
css::uno::Sequence< css::beans::PropertyValue>
m_aLayoutInformation;
sal_Int32 m_nLoginTimeout;
bool m_bReadOnly : 1 ;
bool m_bPasswordRequired : 1 ;
bool m_bSuppressVersionColumns : 1 ;
bool m_bModified : 1 ;
bool m_bDocumentReadOnly : 1 ;
bool m_bMacroCallsSeenWhileLoading : 1 ;
css::uno::Reference< css::beans::XPropertyBag >
m_xSettings;
css::uno::Sequence< OUString > m_aTableFilter;
css::uno::Sequence< OUString > m_aTableTypeFilter;
rtl::Reference< OSharedConnectionManager > m_xSharedConnectionManager;
css::uno::Reference<css::awt::XWindow>
m_xDialogParent;
sal_uInt16 m_nControllerLockCount;
void reset();
/** determines whether the database document has an embedded data storage
*/
bool isEmbeddedDatabase() const { return m_sConnectURL.startsWith("sdbc:embedded:" ); }
/** stores the embedded storage ("database")
@ param _ bPreventRootCommits
Normally , committing the embedded storage results in also committing the root storage
- this is an automatism for data safety reasons .
If you pass < TRUE / > here , committing the root storage is prevented for this particular
call .
@ return < TRUE / > if the storage could be committed , otherwise < FALSE / >
*/
bool commitEmbeddedStorage( bool _bPreventRootCommits = false );
/// commits all sub storages
void commitStorages();
ODatabaseModelImpl(
const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
ODatabaseContext& _pDBContext
);
virtual ~ODatabaseModelImpl();
ODatabaseModelImpl(
OUString _sRegistrationName,
const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
ODatabaseContext& _rDBContext
);
// XEventListener
/// @throws css::uno::RuntimeException
void disposing( const css::lang::EventObject& Source );
void setModified( bool bModified );
void dispose();
const OUString& getURL() const { return m_sDocumentURL; }
const OUString& getDocFileLocation() const { return m_sDocFileLocation; }
css::uno::Reference< css::embed::XStorage >
getStorage( const ObjectType _eType );
// helper
const css::uno::Reference< css::util::XNumberFormatsSupplier >&
getNumberFormatsSupplier();
DocumentEventsData&
getDocumentEvents() { return m_aDocumentEvents; }
const ::comphelper::NamedValueCollection&
getMediaDescriptor() const { return m_aMediaDescriptor; }
void setResource(
const OUString& _rURL,
const css::uno::Sequence< css::beans::PropertyValue >& _rArgs
);
void setDocFileLocation(
const OUString& i_rLoadedFrom
);
static ::comphelper::NamedValueCollection
stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments );
// other stuff
// disposes all elements in m_aStorages, and clears it
void disposeStorages();
/// creates a ->css::embed::StorageFactory
css::uno::Reference< css::lang::XSingleServiceFactory >
createStorageFactory() const ;
/// commits our storage
void commitRootStorage();
/// commits a given storage if it's not readonly, ignoring (but asserting) all errors
bool commitStorageIfWriteable_ignoreErrors(
const css::uno::Reference< css::embed::XStorage >& _rxStorage
);
void clearConnections();
css::uno::Reference< css::embed::XStorage > const & getOrCreateRootStorage();
css::uno::Reference< css::embed::XStorage > const & getRootStorage() const { return m_xDocumentStorage.getTyped(); }
void resetRootStorage() { impl_switchToStorage_throw( nullptr ); }
/** returns the data source. If it doesn't exist it will be created
*/
css::uno::Reference< css::sdbc::XDataSource> getOrCreateDataSource();
/** returns the model, if there already exists one
*/
rtl::Reference< ODatabaseDocument > getModel_noCreate() const ;
/** returns a new ->ODatabaseDocument
@ precond
No - > ODatabaseDocument exists so far
@ seealso
getModel_noCreate
*/
rtl::Reference< ODatabaseDocument > createNewModel_deliverOwnership();
struct ResetModelAccess { friend class ODatabaseDocument; private : ResetModelAccess() { } };
/** resets the model to NULL
Only to be called when the model is being disposed
*/
void modelIsDisposing( const bool _wasInitialized, ResetModelAccess );
bool hadInitializedDocument() const { return m_bDocumentInitialized; }
DocumentStorageAccess*
getDocumentStorageAccess();
css::uno::Reference< css::document::XDocumentSubStorageSupplier >
getDocumentSubStorageSupplier();
void acquire();
void release();
/// returns all known data source settings, including their default values
static std::span<const DefaultPropertyValue> getDefaultDataSourceSettings();
/** retrieves the requested container of objects (forms/reports/tables/queries)
*/
TContentPtr& getObjectContainer( const ObjectType _eType );
/** returns the name of the storage which is used to stored objects of the given type, if applicable
*/
static OUString
getObjectContainerStorageName( const ObjectType _eType );
/** determines whether a given object storage contains macros
*/
static bool objectHasMacros(
const css::uno::Reference< css::embed::XStorage >& _rxContainerStorage,
const OUString& _rPersistentName
);
/** determines which kind of embedded macros are present in the document
*/
EmbeddedMacros determineEmbeddedMacros();
/** checks our document's macro execution mode, using the interaction handler as supplied with our
load arguments
*/
bool checkMacrosOnLoading();
/** adjusts our document's macro execution mode, without using any UI, assuming the user
would reject execution of macros , if she would have been asked .
If checkMacrosOnLoading has been called before ( and thus the macro execution mode
is already adjusted ) , then the current execution mode is simply returned .
@ return
whether or not macro execution is allowed
*/
bool adjustMacroMode_AutoReject();
/** resets our macro execute mode, so next time the checkMacrosOnLoading is called, it will
behave as if it has never been called before
*/
void resetMacroExecutionMode();
/** ensures that ->m_xBasicLibraries resp. m_xDialogLibraries exists
@ return
the requested library container . Is never < NULL / > .
@ throws RuntimeException
if something does wrong , which indicates a server error in the installation
*/
css::uno::Reference< css::script::XStorageBasedLibraryContainer >
getLibraryContainer( bool _bScript );
/** lets our library containers store themselves into the given root storage
*/
void storeLibraryContainersTo( const css::uno::Reference< css::embed::XStorage >& _rxToRootStorage );
/** rebases the document to the given storage
No actual committing , copying , saving , whatsoever happens . The storage is just remembered as the documents
new storage , nothing more .
@ throws css : : lang : : IllegalArgumentException
if the given storage is < NULL / >
@ throws css : : lang : : RuntimeException
if any of the invoked operations does so
*/
css::uno::Reference< css::embed::XStorage >
switchToStorage(
const css::uno::Reference< css::embed::XStorage >& _rxNewRootStorage
);
/** returns the macro mode imposed by an external instance, which passed it to attachResource
*/
sal_Int16 getImposedMacroExecMode() const
{
return m_nImposedMacroExecMode;
}
void setImposedMacroExecMode( const sal_Int16 _nMacroMode )
{
m_nImposedMacroExecMode = _nMacroMode;
}
public :
// IMacroDocumentAccess overridables
virtual sal_Int16 getCurrentMacroExecMode() const override;
virtual void setCurrentMacroExecMode( sal_uInt16 ) override;
virtual OUString getDocumentLocation() const override;
virtual bool documentStorageHasMacros() const override;
virtual bool macroCallsSeenWhileLoading() const override;
virtual css::uno::Reference< css::document::XEmbeddedScripts > getEmbeddedDocumentScripts() const override;
virtual SignatureState getScriptingSignatureState() override;
virtual bool hasTrustedScriptingSignature(
const css::uno::Reference<css::task::XInteractionHandler>& _rxInteraction) override;
// IModifiableDocument
virtual void storageIsModified() override;
// don't use directly, use the ModifyLock class instead
void lockModify() { m_bModificationLock = true ; }
void unlockModify() { m_bModificationLock = false ; }
bool isModifyLocked() const { return m_bModificationLock; }
weld::Window* GetFrameWeld();
private :
void impl_construct_nothrow();
css::uno::Reference< css::embed::XStorage > const &
impl_switchToStorage_throw( const css::uno::Reference< css::embed::XStorage >& _rxNewRootStorage );
/** switches to the given document URL, which denotes the logical URL of the document, not necessarily the
URL where the doc was loaded / recovered from
*/
void impl_switchToLogicalURL(
const OUString& i_rDocumentURL
);
};
/** a small base class for UNO components whose functionality depends on an ODatabaseModelImpl
*/
class ModelDependentComponent
{
protected :
::rtl::Reference< ODatabaseModelImpl > m_pImpl;
::osl::Mutex m_aMutex; // only use this to init WeakComponentImplHelper
protected :
explicit ModelDependentComponent( ::rtl::Reference< ODatabaseModelImpl > _model );
virtual ~ModelDependentComponent();
/** returns the component itself
*/
virtual css::uno::Reference< css::uno::XInterface > getThis() const = 0 ;
::osl::Mutex& getMutex()
{
return m_aMutex;
}
public :
/// checks whether the component is already disposed, throws a DisposedException if so
void checkDisposed() const
{
if ( !m_pImpl.is() )
throw css::lang::DisposedException( u"Component is already disposed." _ustr, getThis() );
}
void lockModify()
{
m_pImpl->lockModify();
}
void unlockModify()
{
m_pImpl->unlockModify();
}
};
class ModifyLock
{
public :
explicit ModifyLock( ModelDependentComponent& _component )
:m_rComponent( _component )
{
m_rComponent.lockModify();
}
~ModifyLock()
{
m_rComponent.unlockModify();
}
private :
ModelDependentComponent& m_rComponent;
};
/** a guard for public methods of objects dependent on an ODatabaseModelImpl instance
Just put this guard onto the stack at the beginning of your method . Don ' t bother yourself
with a MutexGuard , checks for being disposed , and the like .
*/
class ModelMethodGuard
{
private :
// to avoid deadlocks, lock SolarMutex
SolarMutexResettableGuard m_SolarGuard;
public :
/** constructs the guard
@ param _ component
the component whose functionality depends on an ODatabaseModelImpl instance
@ throws css : : lang : : DisposedException
If the given component is already disposed
*/
explicit ModelMethodGuard( const ModelDependentComponent& _component )
{
_component.checkDisposed();
}
void clear()
{
// note: this only releases *once* so may still be locked
m_SolarGuard.clear();
}
void reset()
{
m_SolarGuard.reset();
}
};
} // namespace dbaccess
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=94 H=91 G=92
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland