calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / framework / source / services / modulemanager.cxx
blob475084c4cd5cf578c4cafb536e9597b216f62f38
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 #include <sal/config.h>
22 #include <com/sun/star/frame/UnknownModuleException.hpp>
23 #include <com/sun/star/frame/XFrame.hpp>
24 #include <com/sun/star/frame/XController.hpp>
25 #include <com/sun/star/frame/XModel.hpp>
26 #include <com/sun/star/frame/XModule.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/frame/XModuleManager2.hpp>
29 #include <com/sun/star/container/XNameReplace.hpp>
30 #include <com/sun/star/container/XContainerQuery.hpp>
31 #include <com/sun/star/uno/XComponentContext.hpp>
33 #include <cppuhelper/implbase.hxx>
34 #include <cppuhelper/supportsservice.hxx>
35 #include <comphelper/configurationhelper.hxx>
36 #include <comphelper/sequenceashashmap.hxx>
37 #include <comphelper/sequence.hxx>
38 #include <comphelper/enumhelper.hxx>
39 #include <utility>
41 namespace {
43 class ModuleManager:
44 public cppu::WeakImplHelper<
45 css::lang::XServiceInfo,
46 css::frame::XModuleManager2,
47 css::container::XContainerQuery >
49 private:
51 /** the global uno service manager.
52 Must be used to create own needed services.
54 css::uno::Reference< css::uno::XComponentContext > m_xContext;
56 /** points to the underlying configuration.
57 This ModuleManager does not cache - it calls directly the
58 configuration API!
60 css::uno::Reference< css::container::XNameAccess > m_xCFG;
62 public:
64 explicit ModuleManager(css::uno::Reference< css::uno::XComponentContext > xContext);
66 ModuleManager(const ModuleManager&) = delete;
67 ModuleManager& operator=(const ModuleManager&) = delete;
69 // XServiceInfo
70 virtual OUString SAL_CALL getImplementationName() override;
72 virtual sal_Bool SAL_CALL supportsService(
73 OUString const & ServiceName) override;
75 virtual css::uno::Sequence< OUString > SAL_CALL
76 getSupportedServiceNames() override;
78 // XModuleManager
79 virtual OUString SAL_CALL identify(const css::uno::Reference< css::uno::XInterface >& xModule) override;
81 // XNameReplace
82 virtual void SAL_CALL replaceByName(const OUString& sName ,
83 const css::uno::Any& aValue) override;
85 // XNameAccess
86 virtual css::uno::Any SAL_CALL getByName(const OUString& sName) override;
88 virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override;
90 virtual sal_Bool SAL_CALL hasByName(const OUString& sName) override;
92 // XElementAccess
93 virtual css::uno::Type SAL_CALL getElementType() override;
95 virtual sal_Bool SAL_CALL hasElements() override;
97 // XContainerQuery
98 virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByQuery(const OUString& sQuery) override;
100 virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties) override;
102 private:
104 /** @short makes the real identification of the module.
106 @descr It checks for the optional but preferred interface
107 XModule first. If this module does not exists at the
108 given component it tries to use XServiceInfo instead.
110 Note: This method try to locate a suitable module name.
111 Nothing else. Selecting the right component and throwing suitable
112 exceptions must be done outside.
114 @see identify()
116 @param xComponent
117 the module for identification.
119 @return The identifier of the given module.
120 Can be empty if given component is not a real module !
122 @threadsafe
124 OUString implts_identify(const css::uno::Reference< css::uno::XInterface >& xComponent);
127 ModuleManager::ModuleManager(css::uno::Reference< css::uno::XComponentContext > xContext)
128 : m_xContext(std::move(xContext))
130 m_xCFG.set( comphelper::ConfigurationHelper::openConfig(
131 m_xContext, "/org.openoffice.Setup/Office/Factories",
132 comphelper::EConfigurationModes::ReadOnly ),
133 css::uno::UNO_QUERY_THROW );
136 OUString ModuleManager::getImplementationName()
138 return "com.sun.star.comp.framework.ModuleManager";
141 sal_Bool ModuleManager::supportsService(OUString const & ServiceName)
143 return cppu::supportsService(this, ServiceName);
146 css::uno::Sequence< OUString > ModuleManager::getSupportedServiceNames()
148 return { "com.sun.star.frame.ModuleManager" };
151 OUString SAL_CALL ModuleManager::identify(const css::uno::Reference< css::uno::XInterface >& xModule)
153 // valid parameter?
154 css::uno::Reference< css::frame::XFrame > xFrame (xModule, css::uno::UNO_QUERY);
155 css::uno::Reference< css::awt::XWindow > xWindow (xModule, css::uno::UNO_QUERY);
156 css::uno::Reference< css::frame::XController > xController(xModule, css::uno::UNO_QUERY);
157 css::uno::Reference< css::frame::XModel > xModel (xModule, css::uno::UNO_QUERY);
159 if (
160 (!xFrame.is() ) &&
161 (!xWindow.is() ) &&
162 (!xController.is()) &&
163 (!xModel.is() )
166 throw css::lang::IllegalArgumentException(
167 "Given module is not a frame nor a window, controller or model.",
168 static_cast< ::cppu::OWeakObject* >(this),
172 if (xFrame.is())
174 xController = xFrame->getController();
175 xWindow = xFrame->getComponentWindow();
177 if (xController.is())
178 xModel = xController->getModel();
180 // modules are implemented by the deepest component in hierarchy ...
181 // Means: model -> controller -> window
182 // No fallbacks to higher components are allowed !
183 // Note : A frame provides access to module components only ... but it's not a module by himself.
185 OUString sModule;
186 if (xModel.is())
187 sModule = implts_identify(xModel);
188 else if (xController.is())
189 sModule = implts_identify(xController);
190 else if (xWindow.is())
191 sModule = implts_identify(xWindow);
193 if (sModule.isEmpty())
194 throw css::frame::UnknownModuleException(
195 "Can not find suitable module for the given component.",
196 static_cast< ::cppu::OWeakObject* >(this));
198 return sModule;
201 void SAL_CALL ModuleManager::replaceByName(const OUString& sName ,
202 const css::uno::Any& aValue)
204 ::comphelper::SequenceAsHashMap lProps(aValue);
205 if (lProps.empty() )
207 throw css::lang::IllegalArgumentException(
208 "No properties given to replace part of module.",
209 static_cast< cppu::OWeakObject * >(this),
213 // get access to the element
214 // Note: Don't use impl_getConfig() method here. Because it creates a readonly access only, further
215 // it cache it as a member of this module manager instance. If we change some props there ... but don't
216 // flush changes (because an error occurred) we will read them later. If we use a different config access
217 // we can close it without a flush... and our read data won't be affected .-)
218 css::uno::Reference< css::uno::XInterface > xCfg = ::comphelper::ConfigurationHelper::openConfig(
219 m_xContext,
220 "/org.openoffice.Setup/Office/Factories",
221 ::comphelper::EConfigurationModes::Standard);
222 css::uno::Reference< css::container::XNameAccess > xModules (xCfg, css::uno::UNO_QUERY_THROW);
223 css::uno::Reference< css::container::XNameReplace > xModule ;
225 xModules->getByName(sName) >>= xModule;
226 if (!xModule.is())
228 throw css::uno::RuntimeException(
229 "Was not able to get write access to the requested module entry inside configuration.",
230 static_cast< cppu::OWeakObject * >(this));
233 for (auto const& prop : lProps)
235 // let "NoSuchElementException" out ! We support the same API ...
236 // and without a flush() at the end all changed data before will be ignored !
237 xModule->replaceByName(prop.first.maString, prop.second);
240 ::comphelper::ConfigurationHelper::flush(xCfg);
243 css::uno::Any SAL_CALL ModuleManager::getByName(const OUString& sName)
245 // get access to the element
246 css::uno::Reference< css::container::XNameAccess > xModule;
247 m_xCFG->getByName(sName) >>= xModule;
248 if (!xModule.is())
250 throw css::uno::RuntimeException(
251 "Was not able to get write access to the requested module entry inside configuration.",
252 static_cast< cppu::OWeakObject * >(this));
255 // convert it to seq< PropertyValue >
256 const css::uno::Sequence< OUString > lPropNames = xModule->getElementNames();
257 comphelper::SequenceAsHashMap lProps;
259 lProps[OUString("ooSetupFactoryModuleIdentifier")] <<= sName;
260 for (const OUString& sPropName : lPropNames)
262 lProps[sPropName] = xModule->getByName(sPropName);
265 return css::uno::Any(lProps.getAsConstPropertyValueList());
268 css::uno::Sequence< OUString > SAL_CALL ModuleManager::getElementNames()
270 return m_xCFG->getElementNames();
273 sal_Bool SAL_CALL ModuleManager::hasByName(const OUString& sName)
275 return m_xCFG->hasByName(sName);
278 css::uno::Type SAL_CALL ModuleManager::getElementType()
280 return cppu::UnoType<css::uno::Sequence< css::beans::PropertyValue >>::get();
283 sal_Bool SAL_CALL ModuleManager::hasElements()
285 return m_xCFG->hasElements();
288 css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByQuery(const OUString&)
290 return css::uno::Reference< css::container::XEnumeration >();
293 css::uno::Reference< css::container::XEnumeration > SAL_CALL ModuleManager::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
295 ::comphelper::SequenceAsHashMap lSearchProps(lProperties);
296 const css::uno::Sequence< OUString > lModules = getElementNames();
297 ::std::vector< css::uno::Any > lResult;
299 for (const OUString& rModuleName : lModules)
303 ::comphelper::SequenceAsHashMap lModuleProps = getByName(rModuleName);
304 if (lModuleProps.match(lSearchProps))
305 lResult.push_back(css::uno::Any(lModuleProps.getAsConstPropertyValueList()));
307 catch(const css::uno::Exception&)
312 return new ::comphelper::OAnyEnumeration(comphelper::containerToSequence(lResult));
315 OUString ModuleManager::implts_identify(const css::uno::Reference< css::uno::XInterface >& xComponent)
317 // Search for an optional (!) interface XModule first.
318 // It's used to overrule an existing service name. Used e.g. by our database form designer
319 // which uses a writer module internally.
320 css::uno::Reference< css::frame::XModule > xModule(xComponent, css::uno::UNO_QUERY);
321 if (xModule.is())
322 return xModule->getIdentifier();
324 // detect modules in a generic way...
325 // comparing service names with configured entries...
326 css::uno::Reference< css::lang::XServiceInfo > xInfo(xComponent, css::uno::UNO_QUERY);
327 if (!xInfo.is())
328 return OUString();
330 const css::uno::Sequence< OUString > lKnownModules = getElementNames();
331 for (const OUString& rName : lKnownModules)
333 if (xInfo->supportsService(rName))
334 return rName;
337 return OUString();
342 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
343 com_sun_star_comp_framework_ModuleManager_get_implementation(
344 css::uno::XComponentContext *context,
345 css::uno::Sequence<css::uno::Any> const &)
347 return cppu::acquire(new ModuleManager(context));
350 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */