diff options
Diffstat (limited to '')
-rw-r--r-- | cppuhelper/source/servicemanager.hxx | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx new file mode 100644 index 000000000..cdf23b277 --- /dev/null +++ b/cppuhelper/source/servicemanager.hxx @@ -0,0 +1,361 @@ +/* -*- 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/. + */ + +#pragma once + +#include <sal/config.h> + +#include <cassert> +#include <unordered_map> +#include <memory> +#include <mutex> +#include <string_view> +#include <utility> +#include <vector> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase.hxx> +#include <rtl/ustring.hxx> + +namespace com::sun::star::lang { + class XSingleComponentFactory; +} +namespace cppu { struct ContextEntry_Init; } +namespace com :: sun :: star :: lang { class XSingleServiceFactory; } +namespace com :: sun :: star :: uno { class XComponentContext; } + +class RegistryKey; + +namespace cppuhelper { + +extern "C" { + +typedef css::uno::XInterface * ImplementationConstructorFn( + css::uno::XComponentContext *, css::uno::Sequence<css::uno::Any> const &); + +} + +typedef std::function<css::uno::XInterface * (css::uno::XComponentContext *, css::uno::Sequence<css::uno::Any> const&)> WrapperConstructorFn; + +typedef cppu::WeakComponentImplHelper< + css::lang::XServiceInfo, css::lang::XMultiServiceFactory, + css::lang::XMultiComponentFactory, css::container::XSet, + css::container::XContentEnumerationAccess, css::beans::XPropertySet, + css::beans::XPropertySetInfo, css::lang::XEventListener, + css::lang::XInitialization> +ServiceManagerBase; + +class ServiceManager: + private cppu::BaseMutex, public ServiceManagerBase +{ +public: + struct Data { + Data() = default; + Data(const Data&) = delete; + const Data& operator=(const Data&) = delete; + + struct Implementation { + Implementation( + OUString theName, OUString theLoader, + OUString theUri, OUString theEnvironment, + OUString theConstructorName, + OUString thePrefix, + bool theIsSingleInstance, + css::uno::Reference< css::uno::XComponentContext > theAlienContext, + OUString theRdbFile): + name(std::move(theName)), loader(std::move(theLoader)), uri(std::move(theUri)), environment(std::move(theEnvironment)), + constructorName(std::move(theConstructorName)), prefix(std::move(thePrefix)), + isSingleInstance(theIsSingleInstance), + alienContext(std::move(theAlienContext)), rdbFile(std::move(theRdbFile)), + constructorFn(nullptr), status(STATUS_NEW), dispose(true) + {} + + Implementation( + OUString theName, + css::uno::Reference< css::lang::XSingleComponentFactory > + const & theFactory1, + css::uno::Reference< css::lang::XSingleServiceFactory > const & + theFactory2, + css::uno::Reference< css::lang::XComponent > theComponent): + name(std::move(theName)), isSingleInstance(false), constructorFn(nullptr), + factory1(theFactory1), factory2(theFactory2), + component(std::move(theComponent)), status(STATUS_LOADED), dispose(true) + { assert(theFactory1.is() || theFactory2.is()); } + + Implementation(const Implementation&) = delete; + const Implementation& operator=(const Implementation&) = delete; + + css::uno::Reference<css::uno::XInterface> createInstance( + css::uno::Reference<css::uno::XComponentContext> const & + context, + bool singletonRequest); + + css::uno::Reference<css::uno::XInterface> + createInstanceWithArguments( + css::uno::Reference<css::uno::XComponentContext> const & + context, + bool singletonRequest, + css::uno::Sequence<css::uno::Any> const & arguments); + + bool shallDispose() const { return isSingleInstance || !singletons.empty(); } + + enum Status { STATUS_NEW, STATUS_WRAPPER, STATUS_LOADED }; + + // Logically, exactly one of constructorFn, factory1, factory2 should + // be set. However, there are two exceptions: For one, when + // constructorFn is set, ServiceManager::createContentEnumeration will + // store the necessary ImplementationWrapper in factory1 (so that + // multiple calls to createContentEnumeration will return the same + // wrapper). For another, when factory1 should be set but status is + // STATUS_NEW, factory1 is not yet set (and when status is + // STATUS_WRAPPER, factory1 is merely set to an + // ImplementationWrapper---also due to a + // ServiceManager::createContentEnumeration call---and will be + // loaded later). + OUString name; + OUString loader; + OUString uri; + OUString environment; + OUString constructorName; + OUString prefix; + bool isSingleInstance; + css::uno::Reference< css::uno::XComponentContext > alienContext; + OUString rdbFile; + std::vector< OUString > services; + std::vector< OUString > singletons; + WrapperConstructorFn constructorFn; + css::uno::Reference< css::lang::XSingleComponentFactory > factory1; + css::uno::Reference< css::lang::XSingleServiceFactory > factory2; + css::uno::Reference< css::lang::XComponent > component; + Status status; + + std::mutex mutex; + css::uno::Reference<css::uno::XInterface> singleInstance; + css::uno::Reference< css::lang::XComponent > disposeInstance; + bool dispose; + + private: + css::uno::Reference<css::uno::XInterface> doCreateInstance( + css::uno::Reference<css::uno::XComponentContext> const & context); + + css::uno::Reference<css::uno::XInterface> doCreateInstanceWithArguments( + css::uno::Reference<css::uno::XComponentContext> const & context, + css::uno::Sequence<css::uno::Any> const & arguments); + + void updateDisposeInstance( + bool singletonRequest, + css::uno::Reference<css::uno::XInterface> const & instance); + }; + + typedef std::unordered_map< OUString, std::shared_ptr< Implementation > > + NamedImplementations; + + typedef + std::unordered_map< + css::uno::Reference< css::lang::XServiceInfo >, + std::shared_ptr< Implementation > > + DynamicImplementations; + + typedef + std::unordered_map< + OUString, + std::vector< std::shared_ptr< Implementation > > > + ImplementationMap; + + NamedImplementations namedImplementations; + DynamicImplementations dynamicImplementations; + ImplementationMap services; + ImplementationMap singletons; + }; + + ServiceManager(): ServiceManagerBase(m_aMutex) {} + + ServiceManager(const ServiceManager&) = delete; + const ServiceManager& operator=(const ServiceManager&) = delete; + + using ServiceManagerBase::acquire; + using ServiceManagerBase::release; + + void init(std::u16string_view rdbUris); + + void setContext( + css::uno::Reference< css::uno::XComponentContext > const & context) + { + assert(context.is()); + assert(!context_.is()); + context_ = context; + } + + void addSingletonContextEntries( + std::vector< cppu::ContextEntry_Init > * entries); + + css::uno::Reference< css::uno::XComponentContext > const & getContext() + const + { + assert(context_.is()); + return context_; + } + + void loadImplementation( + css::uno::Reference< css::uno::XComponentContext > const & context, + std::shared_ptr< Data::Implementation > const & implementation); + +private: + virtual ~ServiceManager() override; + + virtual void SAL_CALL disposing() override; + + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override; + + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( + OUString const & aServiceSpecifier) override; + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL + createInstanceWithArguments( + OUString const & ServiceSpecifier, + css::uno::Sequence< css::uno::Any > const & Arguments) override; + + virtual css::uno::Sequence< OUString > SAL_CALL + getAvailableServiceNames() override; + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL + createInstanceWithContext( + OUString const & aServiceSpecifier, + css::uno::Reference< css::uno::XComponentContext > const & Context) override; + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL + createInstanceWithArgumentsAndContext( + OUString const & ServiceSpecifier, + css::uno::Sequence< css::uno::Any > const & Arguments, + css::uno::Reference< css::uno::XComponentContext > const & Context) override; + + virtual css::uno::Type SAL_CALL getElementType() override; + + virtual sal_Bool SAL_CALL hasElements() override; + + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL + createEnumeration() override; + + virtual sal_Bool SAL_CALL has(css::uno::Any const & aElement) override; + + virtual void SAL_CALL insert(css::uno::Any const & aElement) override; + + virtual void SAL_CALL remove(css::uno::Any const & aElement) override; + + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL + createContentEnumeration(OUString const & aServiceName) override; + + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + virtual void SAL_CALL setPropertyValue( + OUString const & aPropertyName, css::uno::Any const & aValue) override; + + virtual css::uno::Any SAL_CALL getPropertyValue( + OUString const & PropertyName) override; + + virtual void SAL_CALL addPropertyChangeListener( + OUString const & aPropertyName, + css::uno::Reference< css::beans::XPropertyChangeListener > const & + xListener) override; + + virtual void SAL_CALL removePropertyChangeListener( + OUString const & aPropertyName, + css::uno::Reference< css::beans::XPropertyChangeListener > const & + aListener) override; + + virtual void SAL_CALL addVetoableChangeListener( + OUString const & PropertyName, + css::uno::Reference< css::beans::XVetoableChangeListener > const & + aListener) override; + + virtual void SAL_CALL removeVetoableChangeListener( + OUString const & PropertyName, + css::uno::Reference< css::beans::XVetoableChangeListener > const & + aListener) override; + + virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties() override; + + virtual css::beans::Property SAL_CALL getPropertyByName( + OUString const & aName) override; + + virtual sal_Bool SAL_CALL hasPropertyByName(OUString const & Name) override; + + virtual void SAL_CALL disposing(css::lang::EventObject const & Source) override; + + virtual void SAL_CALL initialize( + css::uno::Sequence<css::uno::Any> const & aArguments) + override; + + // needs to be called with rBHelper.rMutex locked: + bool isDisposed() const { return rBHelper.bDisposed || rBHelper.bInDispose; } + + void removeEventListenerFromComponent( + css::uno::Reference< css::lang::XComponent > const & component); + + void readRdbDirectory(std::u16string_view uri, bool optional); + + void readRdbFile(OUString const & uri, bool optional); + + bool readLegacyRdbFile(OUString const & uri); + + OUString readLegacyRdbString( + std::u16string_view uri, RegistryKey & key, + OUString const & path); + + void readLegacyRdbStrings( + std::u16string_view uri, RegistryKey & key, + OUString const & path, std::vector< OUString > * strings); + + void insertRdbFiles( + std::vector< OUString > const & uris, + css::uno::Reference< css::uno::XComponentContext > const & + alientContext); + + void insertLegacyFactory( + css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo); + + bool insertExtraData(Data const & extra); + + void removeRdbFiles(std::vector< OUString > const & uris); + + bool removeLegacyFactory( + css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo, + bool removeListener); + + void removeImplementation(const OUString & name); + + std::shared_ptr< Data::Implementation > findServiceImplementation( + css::uno::Reference< css::uno::XComponentContext > const & context, + OUString const & specifier); + + void preloadImplementations(); + + css::uno::Reference< css::uno::XComponentContext > context_; + Data data_; +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |