use boost::small_vector in cppuhelper
[libreoffice.git] / cppuhelper / source / servicemanager.cxx
blob32b4976cf1e1e9fc17daf544c996f1ed3cf80476
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/.
8 */
10 #include <sal/config.h>
12 #include <algorithm>
13 #include <cassert>
14 #include <iostream>
15 #include <mutex>
16 #include <string_view>
17 #include <utility>
18 #include <vector>
20 #include <config_fuzzers.h>
22 #include <com/sun/star/beans/NamedValue.hpp>
23 #include <com/sun/star/beans/PropertyAttribute.hpp>
24 #include <com/sun/star/container/ElementExistException.hpp>
25 #include <com/sun/star/container/XEnumeration.hpp>
26 #include <com/sun/star/container/XNameContainer.hpp>
27 #include <com/sun/star/lang/XInitialization.hpp>
28 #include <com/sun/star/lang/XServiceInfo.hpp>
29 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
30 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
31 #include <com/sun/star/loader/XImplementationLoader.hpp>
32 #include <com/sun/star/registry/InvalidRegistryException.hpp>
33 #include <com/sun/star/uno/DeploymentException.hpp>
34 #include <com/sun/star/uno/Reference.hxx>
35 #include <com/sun/star/uno/XComponentContext.hpp>
36 #include <comphelper/sequence.hxx>
37 #include <cppuhelper/bootstrap.hxx>
38 #include <cppuhelper/component_context.hxx>
39 #include <cppuhelper/implbase.hxx>
40 #include <cppuhelper/supportsservice.hxx>
41 #include <cppuhelper/factory.hxx>
42 #include <o3tl/safeint.hxx>
43 #include <osl/file.hxx>
44 #include <osl/module.hxx>
45 #include <rtl/ref.hxx>
46 #include <rtl/uri.hxx>
47 #include <rtl/ustring.hxx>
48 #include <rtl/ustrbuf.hxx>
49 #include <sal/log.hxx>
50 #include <uno/environment.hxx>
51 #include <uno/mapping.hxx>
52 #include <o3tl/string_view.hxx>
54 #include "loadsharedlibcomponentfactory.hxx"
56 #include <registry/registry.hxx>
57 #include <xmlreader/xmlreader.hxx>
59 #include "paths.hxx"
60 #include "servicemanager.hxx"
62 namespace {
64 void insertImplementationMap(
65 cppuhelper::ServiceManager::Data::ImplementationMap * destination,
66 cppuhelper::ServiceManager::Data::ImplementationMap const & source)
68 assert(destination != nullptr);
69 for (const auto& [rName, rImpls] : source)
71 auto & impls = (*destination)[rName];
72 impls.insert(impls.end(), rImpls.begin(), rImpls.end());
76 void removeFromImplementationMap(
77 cppuhelper::ServiceManager::Data::ImplementationMap * map,
78 std::vector< OUString > const & elements,
79 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
80 const & implementation)
82 // The underlying data structures make this function somewhat inefficient,
83 // but the assumption is that it is rarely called:
84 assert(map != nullptr);
85 for (const auto& rElement : elements)
87 auto j(map->find(rElement));
88 assert(j != map->end());
89 auto k(std::find(j->second.begin(), j->second.end(), implementation));
90 assert(k != j->second.end());
91 j->second.erase(k);
92 if (j->second.empty()) {
93 map->erase(j);
98 // For simplicity, this code keeps throwing
99 // css::registry::InvalidRegistryException for invalid XML rdbs (even though
100 // that does not fit the exception's name):
101 class Parser {
102 public:
103 Parser(
104 OUString const & uri,
105 css::uno::Reference< css::uno::XComponentContext > alienContext,
106 cppuhelper::ServiceManager::Data * data);
108 Parser(const Parser&) = delete;
109 const Parser& operator=(const Parser&) = delete;
111 private:
112 void handleComponent();
114 void handleImplementation();
116 void handleService();
118 void handleSingleton();
120 OUString getNameAttribute();
122 xmlreader::XmlReader reader_;
123 css::uno::Reference< css::uno::XComponentContext > alienContext_;
124 cppuhelper::ServiceManager::Data * data_;
125 OUString attrLoader_;
126 OUString attrUri_;
127 OUString attrEnvironment_;
128 OUString attrPrefix_;
129 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
130 implementation_;
133 Parser::Parser(
134 OUString const & uri,
135 css::uno::Reference< css::uno::XComponentContext > alienContext,
136 cppuhelper::ServiceManager::Data * data):
137 reader_(uri), alienContext_(std::move(alienContext)), data_(data)
139 assert(data != nullptr);
140 int ucNsId = reader_.registerNamespaceIri(
141 xmlreader::Span(
142 RTL_CONSTASCII_STRINGPARAM(
143 "http://openoffice.org/2010/uno-components")));
144 enum State {
145 STATE_BEGIN, STATE_END, STATE_COMPONENTS, STATE_COMPONENT_INITIAL,
146 STATE_COMPONENT, STATE_IMPLEMENTATION, STATE_SERVICE, STATE_SINGLETON };
147 for (State state = STATE_BEGIN;;) {
148 xmlreader::Span name;
149 int nsId;
150 xmlreader::XmlReader::Result res = reader_.nextItem(
151 xmlreader::XmlReader::Text::NONE, &name, &nsId);
152 switch (state) {
153 case STATE_BEGIN:
154 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
155 && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
157 state = STATE_COMPONENTS;
158 break;
160 throw css::registry::InvalidRegistryException(
161 reader_.getUrl() + ": unexpected item in outer level");
162 case STATE_END:
163 if (res == xmlreader::XmlReader::Result::Done) {
164 return;
166 throw css::registry::InvalidRegistryException(
167 reader_.getUrl() + ": unexpected item in outer level");
168 case STATE_COMPONENTS:
169 if (res == xmlreader::XmlReader::Result::End) {
170 state = STATE_END;
171 break;
173 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
174 && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
176 handleComponent();
177 state = STATE_COMPONENT_INITIAL;
178 break;
180 throw css::registry::InvalidRegistryException(
181 reader_.getUrl() + ": unexpected item in <components>");
182 case STATE_COMPONENT:
183 if (res == xmlreader::XmlReader::Result::End) {
184 state = STATE_COMPONENTS;
185 break;
187 [[fallthrough]];
188 case STATE_COMPONENT_INITIAL:
189 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
190 && name.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
192 handleImplementation();
193 state = STATE_IMPLEMENTATION;
194 break;
196 throw css::registry::InvalidRegistryException(
197 reader_.getUrl() + ": unexpected item in <component>");
198 case STATE_IMPLEMENTATION:
199 if (res == xmlreader::XmlReader::Result::End) {
200 state = STATE_COMPONENT;
201 break;
203 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
204 && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
206 handleService();
207 state = STATE_SERVICE;
208 break;
210 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
211 && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
213 handleSingleton();
214 state = STATE_SINGLETON;
215 break;
217 throw css::registry::InvalidRegistryException(
218 reader_.getUrl() + ": unexpected item in <implementation>");
219 case STATE_SERVICE:
220 if (res == xmlreader::XmlReader::Result::End) {
221 state = STATE_IMPLEMENTATION;
222 break;
224 throw css::registry::InvalidRegistryException(
225 reader_.getUrl() + ": unexpected item in <service>");
226 case STATE_SINGLETON:
227 if (res == xmlreader::XmlReader::Result::End) {
228 state = STATE_IMPLEMENTATION;
229 break;
231 throw css::registry::InvalidRegistryException(
232 reader_.getUrl() + ": unexpected item in <service>");
237 void Parser::handleComponent() {
238 attrLoader_ = OUString();
239 attrUri_ = OUString();
240 attrEnvironment_ = OUString();
241 attrPrefix_ = OUString();
242 xmlreader::Span name;
243 int nsId;
244 while (reader_.nextAttribute(&nsId, &name)) {
245 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
246 && name.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
248 if (!attrLoader_.isEmpty()) {
249 throw css::registry::InvalidRegistryException(
250 reader_.getUrl()
251 + ": <component> has multiple \"loader\" attributes");
253 attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8();
254 if (attrLoader_.isEmpty()) {
255 throw css::registry::InvalidRegistryException(
256 reader_.getUrl()
257 + ": <component> has empty \"loader\" attribute");
259 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
260 && name.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
262 if (!attrUri_.isEmpty()) {
263 throw css::registry::InvalidRegistryException(
264 reader_.getUrl()
265 + ": <component> has multiple \"uri\" attributes");
267 attrUri_ = reader_.getAttributeValue(false).convertFromUtf8();
268 if (attrUri_.isEmpty()) {
269 throw css::registry::InvalidRegistryException(
270 reader_.getUrl()
271 + ": <component> has empty \"uri\" attribute");
273 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
274 && name.equals(RTL_CONSTASCII_STRINGPARAM("environment")))
276 if (!attrEnvironment_.isEmpty()) {
277 throw css::registry::InvalidRegistryException(
278 reader_.getUrl() +
279 ": <component> has multiple \"environment\" attributes");
281 attrEnvironment_ = reader_.getAttributeValue(false)
282 .convertFromUtf8();
283 if (attrEnvironment_.isEmpty()) {
284 throw css::registry::InvalidRegistryException(
285 reader_.getUrl() +
286 ": <component> has empty \"environment\" attribute");
288 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
289 && name.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
291 if (!attrPrefix_.isEmpty()) {
292 throw css::registry::InvalidRegistryException(
293 reader_.getUrl() +
294 ": <component> has multiple \"prefix\" attributes");
296 attrPrefix_ = reader_.getAttributeValue(false).convertFromUtf8();
297 if (attrPrefix_.isEmpty()) {
298 throw css::registry::InvalidRegistryException(
299 reader_.getUrl() +
300 ": <component> has empty \"prefix\" attribute");
302 } else {
303 throw css::registry::InvalidRegistryException(
304 reader_.getUrl() + ": unexpected attribute \""
305 + name.convertFromUtf8() + "\" in <component>");
308 if (attrLoader_.isEmpty()) {
309 throw css::registry::InvalidRegistryException(
310 reader_.getUrl() + ": <component> is missing \"loader\" attribute");
312 if (attrUri_.isEmpty()) {
313 throw css::registry::InvalidRegistryException(
314 reader_.getUrl() + ": <component> is missing \"uri\" attribute");
316 #ifndef DISABLE_DYNLOADING
317 try {
318 attrUri_ = rtl::Uri::convertRelToAbs(reader_.getUrl(), attrUri_);
319 } catch (const rtl::MalformedUriException & e) {
320 throw css::registry::InvalidRegistryException(
321 reader_.getUrl() + ": bad \"uri\" attribute: " + e.getMessage());
323 #endif
326 void Parser::handleImplementation() {
327 OUString attrName;
328 OUString attrConstructor;
329 bool attrSingleInstance = false;
330 xmlreader::Span name;
331 int nsId;
332 while (reader_.nextAttribute(&nsId, &name)) {
333 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
334 && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
336 if (!attrName.isEmpty()) {
337 throw css::registry::InvalidRegistryException(
338 reader_.getUrl()
339 + ": <implementation> has multiple \"name\" attributes");
341 attrName = reader_.getAttributeValue(false).convertFromUtf8();
342 if (attrName.isEmpty()) {
343 throw css::registry::InvalidRegistryException(
344 reader_.getUrl()
345 + ": <implementation> has empty \"name\" attribute");
347 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
348 && name.equals(RTL_CONSTASCII_STRINGPARAM("constructor")))
350 if (!attrConstructor.isEmpty()) {
351 throw css::registry::InvalidRegistryException(
352 reader_.getUrl()
353 + ": <implementation> has multiple \"constructor\""
354 " attributes");
356 attrConstructor = reader_.getAttributeValue(false)
357 .convertFromUtf8();
358 if (attrConstructor.isEmpty()) {
359 throw css::registry::InvalidRegistryException(
360 reader_.getUrl()
361 + ": element has empty \"constructor\" attribute");
363 if (attrEnvironment_.isEmpty()) {
364 throw css::registry::InvalidRegistryException(
365 reader_.getUrl()
366 + ": <implementation> has \"constructor\" attribute but"
367 " <component> has no \"environment\" attribute");
369 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
370 && name.equals(RTL_CONSTASCII_STRINGPARAM("single-instance")))
372 if (attrSingleInstance) {
373 throw css::registry::InvalidRegistryException(
374 reader_.getUrl()
375 + ": <implementation> has multiple \"single-instance\" attributes");
377 if (!reader_.getAttributeValue(false).equals(RTL_CONSTASCII_STRINGPARAM("true"))) {
378 throw css::registry::InvalidRegistryException(
379 reader_.getUrl() + ": <implementation> has bad \"single-instance\" attribute");
381 attrSingleInstance = true;
382 } else {
383 throw css::registry::InvalidRegistryException(
384 reader_.getUrl() + ": unexpected element attribute \""
385 + name.convertFromUtf8() + "\" in <implementation>");
388 if (attrName.isEmpty()) {
389 throw css::registry::InvalidRegistryException(
390 reader_.getUrl()
391 + ": <implementation> is missing \"name\" attribute");
393 implementation_ =
394 std::make_shared<cppuhelper::ServiceManager::Data::Implementation>(
395 attrName, attrLoader_, attrUri_, attrEnvironment_, attrConstructor,
396 attrPrefix_, attrSingleInstance, alienContext_, reader_.getUrl());
397 if (!data_->namedImplementations.emplace(attrName, implementation_).
398 second)
400 throw css::registry::InvalidRegistryException(
401 reader_.getUrl() + ": duplicate <implementation name=\"" + attrName
402 + "\">");
406 void Parser::handleService() {
407 OUString name(getNameAttribute());
408 implementation_->services.push_back(name);
409 data_->services[name].push_back(implementation_);
412 void Parser::handleSingleton() {
413 OUString name(getNameAttribute());
414 implementation_->singletons.push_back(name);
415 data_->singletons[name].push_back(implementation_);
418 OUString Parser::getNameAttribute() {
419 OUString attrName;
420 xmlreader::Span name;
421 int nsId;
422 while (reader_.nextAttribute(&nsId, &name)) {
423 if (nsId != xmlreader::XmlReader::NAMESPACE_NONE
424 || !name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
426 throw css::registry::InvalidRegistryException(
427 reader_.getUrl() + ": expected element attribute \"name\"");
429 if (!attrName.isEmpty()) {
430 throw css::registry::InvalidRegistryException(
431 reader_.getUrl()
432 + ": element has multiple \"name\" attributes");
434 attrName = reader_.getAttributeValue(false).convertFromUtf8();
435 if (attrName.isEmpty()) {
436 throw css::registry::InvalidRegistryException(
437 reader_.getUrl() + ": element has empty \"name\" attribute");
440 if (attrName.isEmpty()) {
441 throw css::registry::InvalidRegistryException(
442 reader_.getUrl() + ": element is missing \"name\" attribute");
444 return attrName;
447 class ContentEnumeration:
448 public cppu::WeakImplHelper< css::container::XEnumeration >
450 public:
451 explicit ContentEnumeration(std::vector< css::uno::Any >&& factories):
452 factories_(std::move(factories)), iterator_(factories_.begin()) {}
454 ContentEnumeration(const ContentEnumeration&) = delete;
455 const ContentEnumeration& operator=(const ContentEnumeration&) = delete;
457 private:
458 virtual ~ContentEnumeration() override {}
460 virtual sal_Bool SAL_CALL hasMoreElements() override;
462 virtual css::uno::Any SAL_CALL nextElement() override;
464 std::mutex mutex_;
465 std::vector< css::uno::Any > factories_;
466 std::vector< css::uno::Any >::const_iterator iterator_;
469 sal_Bool ContentEnumeration::hasMoreElements()
471 std::scoped_lock g(mutex_);
472 return iterator_ != factories_.end();
475 css::uno::Any ContentEnumeration::nextElement()
477 std::scoped_lock g(mutex_);
478 if (iterator_ == factories_.end()) {
479 throw css::container::NoSuchElementException(
480 u"Bootstrap service manager service enumerator has no more elements"_ustr,
481 static_cast< cppu::OWeakObject * >(this));
483 return *iterator_++;
486 css::beans::Property getDefaultContextProperty() {
487 return css::beans::Property(
488 u"DefaultContext"_ustr, -1,
489 cppu::UnoType< css::uno::XComponentContext >::get(),
490 css::beans::PropertyAttribute::READONLY);
493 class SingletonFactory:
494 public cppu::WeakImplHelper<css::lang::XSingleComponentFactory>
496 public:
497 SingletonFactory(
498 rtl::Reference< cppuhelper::ServiceManager > const & manager,
499 std::shared_ptr<
500 cppuhelper::ServiceManager::Data::Implementation > const &
501 implementation):
502 manager_(manager), implementation_(implementation)
503 { assert(manager.is()); assert(implementation); }
505 SingletonFactory(const SingletonFactory&) = delete;
506 const SingletonFactory& operator=(const SingletonFactory&) = delete;
508 private:
509 virtual ~SingletonFactory() override {}
511 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
512 createInstanceWithContext(
513 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
515 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
516 createInstanceWithArgumentsAndContext(
517 css::uno::Sequence< css::uno::Any > const & Arguments,
518 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
520 rtl::Reference< cppuhelper::ServiceManager > manager_;
521 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
522 implementation_;
525 css::uno::Reference< css::uno::XInterface >
526 SingletonFactory::createInstanceWithContext(
527 css::uno::Reference< css::uno::XComponentContext > const & Context)
529 manager_->loadImplementation(Context, implementation_);
530 return implementation_->createInstance(Context, true);
533 css::uno::Reference< css::uno::XInterface >
534 SingletonFactory::createInstanceWithArgumentsAndContext(
535 css::uno::Sequence< css::uno::Any > const & Arguments,
536 css::uno::Reference< css::uno::XComponentContext > const & Context)
538 manager_->loadImplementation(Context, implementation_);
539 return implementation_->createInstanceWithArguments(
540 Context, true, Arguments);
543 class ImplementationWrapper:
544 public cppu::WeakImplHelper<
545 css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
546 css::lang::XServiceInfo >
548 public:
549 ImplementationWrapper(
550 rtl::Reference< cppuhelper::ServiceManager > const & manager,
551 std::shared_ptr<
552 cppuhelper::ServiceManager::Data::Implementation > const &
553 implementation):
554 manager_(manager), implementation_(implementation)
555 { assert(manager.is()); assert(implementation); }
557 ImplementationWrapper(const ImplementationWrapper&) = delete;
558 const ImplementationWrapper& operator=(const ImplementationWrapper&) = delete;
560 private:
561 virtual ~ImplementationWrapper() override {}
563 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
564 createInstanceWithContext(
565 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
567 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
568 createInstanceWithArgumentsAndContext(
569 css::uno::Sequence< css::uno::Any > const & Arguments,
570 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
572 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
573 createInstance() override;
575 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
576 createInstanceWithArguments(
577 css::uno::Sequence< css::uno::Any > const & Arguments) override;
579 virtual OUString SAL_CALL getImplementationName() override;
581 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
583 virtual css::uno::Sequence< OUString > SAL_CALL
584 getSupportedServiceNames() override;
586 rtl::Reference< cppuhelper::ServiceManager > manager_;
587 std::weak_ptr< cppuhelper::ServiceManager::Data::Implementation >
588 implementation_;
591 css::uno::Reference< css::uno::XInterface >
592 ImplementationWrapper::createInstanceWithContext(
593 css::uno::Reference< css::uno::XComponentContext > const & Context)
595 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
596 assert(impl);
597 manager_->loadImplementation(Context, impl);
598 return impl->createInstance(Context, false);
601 css::uno::Reference< css::uno::XInterface >
602 ImplementationWrapper::createInstanceWithArgumentsAndContext(
603 css::uno::Sequence< css::uno::Any > const & Arguments,
604 css::uno::Reference< css::uno::XComponentContext > const & Context)
606 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
607 assert(impl);
608 manager_->loadImplementation(Context, impl);
609 return impl->createInstanceWithArguments(
610 Context, false, Arguments);
613 css::uno::Reference< css::uno::XInterface >
614 ImplementationWrapper::createInstance()
616 return createInstanceWithContext(manager_->getContext());
619 css::uno::Reference< css::uno::XInterface >
620 ImplementationWrapper::createInstanceWithArguments(
621 css::uno::Sequence< css::uno::Any > const & Arguments)
623 return createInstanceWithArgumentsAndContext(
624 Arguments, manager_->getContext());
627 OUString ImplementationWrapper::getImplementationName()
629 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
630 assert(impl);
631 return impl->name;
634 sal_Bool ImplementationWrapper::supportsService(OUString const & ServiceName)
636 return cppu::supportsService(this, ServiceName);
639 css::uno::Sequence< OUString >
640 ImplementationWrapper::getSupportedServiceNames()
642 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
643 assert(impl);
644 if (impl->services.size()
645 > o3tl::make_unsigned(SAL_MAX_INT32))
647 throw css::uno::RuntimeException(
648 ("Implementation " + impl->name
649 + " supports too many services"),
650 static_cast< cppu::OWeakObject * >(this));
652 return comphelper::containerToSequence(impl->services);
657 css::uno::Reference<css::uno::XInterface>
658 cppuhelper::ServiceManager::Data::Implementation::createInstance(
659 css::uno::Reference<css::uno::XComponentContext> const & context,
660 bool singletonRequest)
662 css::uno::Reference<css::uno::XInterface> inst;
663 if (isSingleInstance) {
664 std::unique_lock g(mutex);
665 if (!singleInstance.is()) {
666 singleInstance = doCreateInstance(context);
668 inst = singleInstance;
669 } else {
670 inst = doCreateInstance(context);
672 updateDisposeInstance(singletonRequest, inst);
673 return inst;
676 css::uno::Reference<css::uno::XInterface>
677 cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
678 css::uno::Reference<css::uno::XComponentContext> const & context,
679 bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
681 css::uno::Reference<css::uno::XInterface> inst;
682 if (isSingleInstance) {
683 std::unique_lock g(mutex);
684 if (!singleInstance.is()) {
685 singleInstance = doCreateInstanceWithArguments(context, arguments);
687 inst = singleInstance;
688 } else {
689 inst = doCreateInstanceWithArguments(context, arguments);
691 updateDisposeInstance(singletonRequest, inst);
692 return inst;
695 css::uno::Reference<css::uno::XInterface>
696 cppuhelper::ServiceManager::Data::Implementation::doCreateInstance(
697 css::uno::Reference<css::uno::XComponentContext> const & context)
699 if (constructorFn) {
700 return css::uno::Reference<css::uno::XInterface>(
701 constructorFn(context.get(), css::uno::Sequence<css::uno::Any>()),
702 SAL_NO_ACQUIRE);
703 } else if (factory1.is()) {
704 return factory1->createInstanceWithContext(context);
705 } else {
706 assert(factory2.is());
707 return factory2->createInstance();
711 css::uno::Reference<css::uno::XInterface>
712 cppuhelper::ServiceManager::Data::Implementation::doCreateInstanceWithArguments(
713 css::uno::Reference<css::uno::XComponentContext> const & context,
714 css::uno::Sequence<css::uno::Any> const & arguments)
716 if (constructorFn) {
717 css::uno::Reference<css::uno::XInterface> inst(
718 constructorFn(context.get(), arguments), SAL_NO_ACQUIRE);
719 //HACK: The constructor will either observe arguments and return inst
720 // that does not implement XInitialization (or null), or ignore
721 // arguments and return inst that implements XInitialization; this
722 // should be removed again once XInitialization-based implementations
723 // have become rare:
724 css::uno::Reference<css::lang::XInitialization> init(
725 inst, css::uno::UNO_QUERY);
726 if (init.is()) {
727 init->initialize(arguments);
729 return inst;
730 } else if (factory1.is()) {
731 return factory1->createInstanceWithArgumentsAndContext(
732 arguments, context);
733 } else {
734 assert(factory2.is());
735 return factory2->createInstanceWithArguments(arguments);
739 void cppuhelper::ServiceManager::Data::Implementation::updateDisposeInstance(
740 bool singletonRequest,
741 css::uno::Reference<css::uno::XInterface> const & instance)
743 // This is an optimization, to only call dispose once (from the component
744 // context) on a singleton that is obtained both via the component context
745 // and via the service manager; however, there is a harmless race here that
746 // may cause two calls to dispose nevertheless (also, this calls dispose on
747 // at most one of the instances obtained via the service manager, in case
748 // the implementation hands out different instances):
749 if (singletonRequest) {
750 std::unique_lock g(mutex);
751 disposeInstance.clear();
752 dispose = false;
753 } else if (shallDispose()) {
754 css::uno::Reference<css::lang::XComponent> comp(
755 instance, css::uno::UNO_QUERY);
756 if (comp.is()) {
757 std::unique_lock g(mutex);
758 if (dispose) {
759 disposeInstance = comp;
765 void cppuhelper::ServiceManager::addSingletonContextEntries(
766 std::vector< cppu::ContextEntry_Init > * entries)
768 assert(entries != nullptr);
769 for (const auto& [rName, rImpls] : data_.singletons)
771 assert(!rImpls.empty());
772 assert(rImpls[0]);
773 SAL_INFO_IF(
774 rImpls.size() > 1, "cppuhelper",
775 "Arbitrarily choosing " << rImpls[0]->name
776 << " among multiple implementations for " << rName);
777 entries->push_back(
778 cppu::ContextEntry_Init(
779 "/singletons/" + rName,
780 css::uno::Any(
781 css::uno::Reference<css::lang::XSingleComponentFactory>(
782 new SingletonFactory(this, rImpls[0]))),
783 true));
787 void cppuhelper::ServiceManager::loadImplementation(
788 css::uno::Reference< css::uno::XComponentContext > const & context,
789 std::shared_ptr< Data::Implementation > const & implementation)
791 assert(implementation);
793 std::unique_lock g(m_aMutex);
794 if (implementation->status == Data::Implementation::STATUS_LOADED) {
795 return;
798 OUString uri;
799 try {
800 uri = cppu::bootstrap_expandUri(implementation->uri);
801 } catch (css::lang::IllegalArgumentException & e) {
802 throw css::uno::DeploymentException(
803 "Cannot expand URI" + implementation->uri + ": " + e.Message,
804 static_cast< cppu::OWeakObject * >(this));
806 cppuhelper::WrapperConstructorFn ctor;
807 css::uno::Reference< css::uno::XInterface > f0;
808 // Special handling of SharedLibrary loader, with support for environment,
809 // constructor, and prefix arguments:
810 if (!implementation->alienContext.is()
811 && implementation->loader == "com.sun.star.loader.SharedLibrary")
813 cppuhelper::detail::loadSharedLibComponentFactory(
814 uri, implementation->environment,
815 implementation->prefix, implementation->name,
816 implementation->constructorName, this, &ctor, &f0);
817 if (ctor) {
818 assert(!implementation->environment.isEmpty());
820 } else {
821 SAL_WARN_IF(
822 !implementation->environment.isEmpty(), "cppuhelper",
823 "Loader " << implementation->loader
824 << " and non-empty environment "
825 << implementation->environment);
826 SAL_WARN_IF(
827 !implementation->prefix.isEmpty(), "cppuhelper",
828 "Loader " << implementation->loader
829 << " and non-empty constructor "
830 << implementation->constructorName);
831 SAL_WARN_IF(
832 !implementation->prefix.isEmpty(), "cppuhelper",
833 "Loader " << implementation->loader
834 << " and non-empty prefix " << implementation->prefix);
835 css::uno::Reference< css::uno::XComponentContext > ctxt;
836 css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
837 if (implementation->alienContext.is()) {
838 ctxt = implementation->alienContext;
839 smgr.set(ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
840 } else {
841 assert(context.is());
842 ctxt = context;
843 smgr = this;
845 css::uno::Reference< css::loader::XImplementationLoader > loader(
846 smgr->createInstanceWithContext(implementation->loader, ctxt),
847 css::uno::UNO_QUERY_THROW);
848 f0 = loader->activate(
849 implementation->name, OUString(), uri,
850 css::uno::Reference< css::registry::XRegistryKey >());
852 css::uno::Reference<css::lang::XSingleComponentFactory> f1;
853 css::uno::Reference<css::lang::XSingleServiceFactory> f2;
854 if (!ctor) {
855 f1.set(f0, css::uno::UNO_QUERY);
856 if (!f1.is()) {
857 f2.set(f0, css::uno::UNO_QUERY);
858 if (!f2.is()) {
859 throw css::uno::DeploymentException(
860 ("Implementation " + implementation->name
861 + " does not provide a constructor or factory"),
862 static_cast< cppu::OWeakObject * >(this));
866 //TODO: There is a race here, as the relevant service factory can be removed
867 // while the mutex is unlocked and loading can thus fail, as the entity from
868 // which to load can disappear once the service factory is removed.
869 std::unique_lock g(m_aMutex);
870 if (!(m_bDisposed
871 || implementation->status == Data::Implementation::STATUS_LOADED))
873 implementation->status = Data::Implementation::STATUS_LOADED;
874 implementation->constructorFn = ctor;
875 implementation->factory1 = f1;
876 implementation->factory2 = f2;
880 void cppuhelper::ServiceManager::disposing(std::unique_lock<std::mutex>& rGuard) {
881 std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
882 std::vector< css::uno::Reference< css::lang::XComponent > > comps;
883 Data clear;
885 for (const auto& rEntry : data_.namedImplementations)
887 assert(rEntry.second);
888 if (rEntry.second->shallDispose()) {
889 std::unique_lock g2(rEntry.second->mutex);
890 if (rEntry.second->disposeInstance.is()) {
891 sngls.push_back(rEntry.second->disposeInstance);
895 for (const auto& rEntry : data_.dynamicImplementations)
897 assert(rEntry.second);
898 if (rEntry.second->shallDispose()) {
899 std::unique_lock g2(rEntry.second->mutex);
900 if (rEntry.second->disposeInstance.is()) {
901 sngls.push_back(rEntry.second->disposeInstance);
904 if (rEntry.second->component.is()) {
905 comps.push_back(rEntry.second->component);
908 data_.namedImplementations.swap(clear.namedImplementations);
909 data_.dynamicImplementations.swap(clear.dynamicImplementations);
910 data_.services.swap(clear.services);
911 data_.singletons.swap(clear.singletons);
913 rGuard.unlock();
914 for (const auto& rxSngl : sngls)
916 try {
917 rxSngl->dispose();
918 } catch (css::uno::RuntimeException & e) {
919 SAL_WARN("cppuhelper", "Ignoring " << e << " while disposing singleton");
922 for (const auto& rxComp : comps)
924 removeEventListenerFromComponent(rxComp);
926 rGuard.lock();
929 void cppuhelper::ServiceManager::initialize(
930 css::uno::Sequence<css::uno::Any> const & aArguments)
932 OUString arg;
933 if (aArguments.getLength() != 1 || !(aArguments[0] >>= arg)
934 || arg != "preload")
936 throw css::lang::IllegalArgumentException(
937 u"invalid ServiceManager::initialize argument"_ustr,
938 css::uno::Reference<css::uno::XInterface>(), 0);
940 preloadImplementations();
943 OUString cppuhelper::ServiceManager::getImplementationName()
945 return
946 u"com.sun.star.comp.cppuhelper.bootstrap.ServiceManager"_ustr;
949 sal_Bool cppuhelper::ServiceManager::supportsService(
950 OUString const & ServiceName)
952 return cppu::supportsService(this, ServiceName);
955 css::uno::Sequence< OUString >
956 cppuhelper::ServiceManager::getSupportedServiceNames()
958 return { u"com.sun.star.lang.MultiServiceFactory"_ustr, u"com.sun.star.lang.ServiceManager"_ustr };
961 css::uno::Reference< css::uno::XInterface >
962 cppuhelper::ServiceManager::createInstance(
963 OUString const & aServiceSpecifier)
965 assert(context_.is());
966 return createInstanceWithContext(aServiceSpecifier, context_);
969 css::uno::Reference< css::uno::XInterface >
970 cppuhelper::ServiceManager::createInstanceWithArguments(
971 OUString const & ServiceSpecifier,
972 css::uno::Sequence< css::uno::Any > const & Arguments)
974 assert(context_.is());
975 return createInstanceWithArgumentsAndContext(
976 ServiceSpecifier, Arguments, context_);
979 css::uno::Sequence< OUString >
980 cppuhelper::ServiceManager::getAvailableServiceNames()
982 std::unique_lock g(m_aMutex);
983 if (m_bDisposed) {
984 return css::uno::Sequence< OUString >();
986 if (data_.services.size() > o3tl::make_unsigned(SAL_MAX_INT32)) {
987 throw css::uno::RuntimeException(
988 u"getAvailableServiceNames: too many services"_ustr,
989 static_cast< cppu::OWeakObject * >(this));
991 return comphelper::mapKeysToSequence(data_.services);
994 css::uno::Reference< css::uno::XInterface >
995 cppuhelper::ServiceManager::createInstanceWithContext(
996 OUString const & aServiceSpecifier,
997 css::uno::Reference< css::uno::XComponentContext > const & Context)
999 std::shared_ptr< Data::Implementation > impl(
1000 findServiceImplementation(Context, aServiceSpecifier));
1001 return impl == nullptr ? css::uno::Reference<css::uno::XInterface>()
1002 : impl->createInstance(Context, false);
1005 css::uno::Reference< css::uno::XInterface >
1006 cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
1007 OUString const & ServiceSpecifier,
1008 css::uno::Sequence< css::uno::Any > const & Arguments,
1009 css::uno::Reference< css::uno::XComponentContext > const & Context)
1011 std::shared_ptr< Data::Implementation > impl(
1012 findServiceImplementation(Context, ServiceSpecifier));
1013 return impl == nullptr ? css::uno::Reference<css::uno::XInterface>()
1014 : impl->createInstanceWithArguments(Context, false, Arguments);
1017 css::uno::Type cppuhelper::ServiceManager::getElementType()
1019 return css::uno::Type();
1022 sal_Bool cppuhelper::ServiceManager::hasElements()
1024 std::unique_lock g(m_aMutex);
1025 return
1026 !(data_.namedImplementations.empty()
1027 && data_.dynamicImplementations.empty());
1030 css::uno::Reference< css::container::XEnumeration >
1031 cppuhelper::ServiceManager::createEnumeration()
1033 throw css::uno::RuntimeException(
1034 u"ServiceManager createEnumeration: method not supported"_ustr,
1035 static_cast< cppu::OWeakObject * >(this));
1038 sal_Bool cppuhelper::ServiceManager::has(css::uno::Any const &)
1040 throw css::uno::RuntimeException(
1041 u"ServiceManager has: method not supported"_ustr,
1042 static_cast< cppu::OWeakObject * >(this));
1045 void cppuhelper::ServiceManager::insert(css::uno::Any const & aElement)
1047 css::uno::Sequence< css::beans::NamedValue > args;
1048 if (aElement >>= args) {
1049 std::vector< OUString > uris;
1050 css::uno::Reference< css::uno::XComponentContext > alienContext;
1051 for (const auto & arg : args) {
1052 if (arg.Name == "uri") {
1053 OUString uri;
1054 if (!(arg.Value >>= uri)) {
1055 throw css::lang::IllegalArgumentException(
1056 u"Bad uri argument"_ustr,
1057 static_cast< cppu::OWeakObject * >(this), 0);
1059 uris.push_back(uri);
1060 } else if (arg.Name == "component-context") {
1061 if (alienContext.is()) {
1062 throw css::lang::IllegalArgumentException(
1063 u"Multiple component-context arguments"_ustr,
1064 static_cast< cppu::OWeakObject * >(this), 0);
1066 if (!(arg.Value >>= alienContext) || !alienContext.is()) {
1067 throw css::lang::IllegalArgumentException(
1068 u"Bad component-context argument"_ustr,
1069 static_cast< cppu::OWeakObject * >(this), 0);
1071 } else {
1072 throw css::lang::IllegalArgumentException(
1073 "Bad argument " + arg.Name,
1074 static_cast< cppu::OWeakObject * >(this), 0);
1077 insertRdbFiles(uris, alienContext);
1078 return;
1080 css::uno::Reference< css::lang::XServiceInfo > info;
1081 if ((aElement >>= info) && info.is()) {
1082 insertLegacyFactory(info);
1083 return;
1086 throw css::lang::IllegalArgumentException(
1087 u"Bad insert element"_ustr, static_cast< cppu::OWeakObject * >(this), 0);
1090 void cppuhelper::ServiceManager::remove(css::uno::Any const & aElement)
1092 css::uno::Sequence< css::beans::NamedValue > args;
1093 if (aElement >>= args) {
1094 std::vector< OUString > uris;
1095 for (const auto & i : args) {
1096 if (i.Name != "uri") {
1097 throw css::lang::IllegalArgumentException(
1098 "Bad argument " + i.Name,
1099 static_cast< cppu::OWeakObject * >(this), 0);
1101 OUString uri;
1102 if (!(i.Value >>= uri)) {
1103 throw css::lang::IllegalArgumentException(
1104 u"Bad uri argument"_ustr,
1105 static_cast< cppu::OWeakObject * >(this), 0);
1107 uris.push_back(uri);
1109 removeRdbFiles(uris);
1110 return;
1112 css::uno::Reference< css::lang::XServiceInfo > info;
1113 if ((aElement >>= info) && info.is()) {
1114 if (!removeLegacyFactory(info, true)) {
1115 throw css::container::NoSuchElementException(
1116 u"Remove non-inserted factory object"_ustr,
1117 static_cast< cppu::OWeakObject * >(this));
1119 return;
1121 OUString impl;
1122 if (aElement >>= impl) {
1123 // For live-removal of extensions:
1124 removeImplementation(impl);
1125 return;
1127 throw css::lang::IllegalArgumentException(
1128 u"Bad remove element"_ustr, static_cast< cppu::OWeakObject * >(this), 0);
1131 css::uno::Reference< css::container::XEnumeration >
1132 cppuhelper::ServiceManager::createContentEnumeration(
1133 OUString const & aServiceName)
1135 boost::container::small_vector< std::shared_ptr< Data::Implementation >, 2 > impls;
1137 std::unique_lock g(m_aMutex);
1138 Data::ImplementationMap::const_iterator i(
1139 data_.services.find(aServiceName));
1140 if (i != data_.services.end()) {
1141 impls = i->second;
1144 std::vector< css::uno::Any > factories;
1145 for (const auto& rxImpl : impls)
1147 Data::Implementation * impl = rxImpl.get();
1148 assert(impl != nullptr);
1150 std::unique_lock g(m_aMutex);
1151 if (m_bDisposed) {
1152 factories.clear();
1153 break;
1155 if (impl->status == Data::Implementation::STATUS_NEW) {
1156 // Postpone actual implementation instantiation as long as
1157 // possible (so that e.g. opening LO's "Tools - Macros" menu
1158 // does not try to instantiate a JVM, which can lead to a
1159 // synchronous error dialog when no JVM is specified, and
1160 // showing the dialog while hovering over a menu can cause
1161 // trouble):
1162 impl->factory1 = new ImplementationWrapper(this, rxImpl);
1163 impl->status = Data::Implementation::STATUS_WRAPPER;
1165 if (impl->constructorFn != nullptr && !impl->factory1.is()) {
1166 impl->factory1 = new ImplementationWrapper(this, rxImpl);
1169 if (impl->factory1.is()) {
1170 factories.push_back(css::uno::Any(impl->factory1));
1171 } else {
1172 assert(impl->factory2.is());
1173 factories.push_back(css::uno::Any(impl->factory2));
1176 return new ContentEnumeration(std::move(factories));
1179 css::uno::Reference< css::beans::XPropertySetInfo >
1180 cppuhelper::ServiceManager::getPropertySetInfo()
1182 return this;
1185 void cppuhelper::ServiceManager::setPropertyValue(
1186 OUString const & aPropertyName, css::uno::Any const &)
1188 if (aPropertyName == "DefaultContext") {
1189 throw css::beans::PropertyVetoException(
1190 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1191 } else {
1192 throw css::beans::UnknownPropertyException(
1193 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1197 css::uno::Any cppuhelper::ServiceManager::getPropertyValue(
1198 OUString const & PropertyName)
1200 if (PropertyName != "DefaultContext") {
1201 throw css::beans::UnknownPropertyException(
1202 PropertyName, static_cast< cppu::OWeakObject * >(this));
1204 assert(context_.is());
1205 return css::uno::Any(context_);
1208 void cppuhelper::ServiceManager::addPropertyChangeListener(
1209 OUString const & aPropertyName,
1210 css::uno::Reference< css::beans::XPropertyChangeListener > const &
1211 xListener)
1213 if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1214 throw css::beans::UnknownPropertyException(
1215 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1217 // DefaultContext does not change, so just treat it as an event listener:
1218 return addEventListener(xListener);
1221 void cppuhelper::ServiceManager::removePropertyChangeListener(
1222 OUString const & aPropertyName,
1223 css::uno::Reference< css::beans::XPropertyChangeListener > const &
1224 aListener)
1226 if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1227 throw css::beans::UnknownPropertyException(
1228 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1230 // DefaultContext does not change, so just treat it as an event listener:
1231 return removeEventListener(aListener);
1234 void cppuhelper::ServiceManager::addVetoableChangeListener(
1235 OUString const & PropertyName,
1236 css::uno::Reference< css::beans::XVetoableChangeListener > const &
1237 aListener)
1239 if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1240 throw css::beans::UnknownPropertyException(
1241 PropertyName, static_cast< cppu::OWeakObject * >(this));
1243 // DefaultContext does not change, so just treat it as an event listener:
1244 return addEventListener(aListener);
1247 void cppuhelper::ServiceManager::removeVetoableChangeListener(
1248 OUString const & PropertyName,
1249 css::uno::Reference< css::beans::XVetoableChangeListener > const &
1250 aListener)
1252 if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1253 throw css::beans::UnknownPropertyException(
1254 PropertyName, static_cast< cppu::OWeakObject * >(this));
1256 // DefaultContext does not change, so just treat it as an event listener:
1257 return removeEventListener(aListener);
1260 css::uno::Sequence< css::beans::Property >
1261 cppuhelper::ServiceManager::getProperties() {
1262 return { getDefaultContextProperty() };
1265 css::beans::Property cppuhelper::ServiceManager::getPropertyByName(
1266 OUString const & aName)
1268 if (aName != "DefaultContext") {
1269 throw css::beans::UnknownPropertyException(
1270 aName, static_cast< cppu::OWeakObject * >(this));
1272 return getDefaultContextProperty();
1275 sal_Bool cppuhelper::ServiceManager::hasPropertyByName(
1276 OUString const & Name)
1278 return Name == "DefaultContext";
1281 cppuhelper::ServiceManager::~ServiceManager() {}
1283 void cppuhelper::ServiceManager::disposing(
1284 css::lang::EventObject const & Source)
1286 removeLegacyFactory(
1287 css::uno::Reference< css::lang::XServiceInfo >(
1288 Source.Source, css::uno::UNO_QUERY_THROW),
1289 false);
1292 void cppuhelper::ServiceManager::removeEventListenerFromComponent(
1293 css::uno::Reference< css::lang::XComponent > const & component)
1295 assert(component.is());
1296 try {
1297 component->removeEventListener(this);
1298 } catch (css::uno::RuntimeException & e) {
1299 SAL_INFO(
1300 "cppuhelper",
1301 "Ignored removeEventListener RuntimeException " + e.Message);
1305 void cppuhelper::ServiceManager::init(std::u16string_view rdbUris) {
1306 for (sal_Int32 i = 0; i != -1;) {
1307 std::u16string_view uri(o3tl::getToken(rdbUris, 0, ' ', i));
1308 if (uri.empty()) {
1309 continue;
1311 bool optional;
1312 bool directory;
1313 cppu::decodeRdbUri(&uri, &optional, &directory);
1314 if (directory) {
1315 readRdbDirectory(uri, optional);
1316 } else {
1317 readRdbFile(OUString(uri), optional);
1322 void cppuhelper::ServiceManager::readRdbDirectory(
1323 std::u16string_view uri, bool optional)
1325 osl::Directory dir = OUString(uri);
1326 switch (dir.open()) {
1327 case osl::FileBase::E_None:
1328 break;
1329 case osl::FileBase::E_NOENT:
1330 if (optional) {
1331 SAL_INFO("cppuhelper", "Ignored optional " << OUString(uri));
1332 return;
1334 [[fallthrough]];
1335 default:
1336 throw css::uno::DeploymentException(
1337 OUString::Concat("Cannot open directory ") + uri,
1338 static_cast< cppu::OWeakObject * >(this));
1340 for (;;) {
1341 OUString url;
1342 if (!cppu::nextDirectoryItem(dir, &url)) {
1343 break;
1345 readRdbFile(url, false);
1349 void cppuhelper::ServiceManager::readRdbFile(
1350 OUString const & uri, bool optional)
1352 try {
1353 Parser(
1354 uri, css::uno::Reference< css::uno::XComponentContext >(), &data_);
1355 } catch (css::container::NoSuchElementException &) {
1356 if (!optional) {
1357 throw css::uno::DeploymentException(
1358 uri + ": no such file",
1359 static_cast< cppu::OWeakObject * >(this));
1361 SAL_INFO("cppuhelper", "Ignored optional " << uri);
1363 #if !ENABLE_FUZZERS
1364 catch (css::registry::InvalidRegistryException & e) {
1365 if (!readLegacyRdbFile(uri)) {
1366 throw css::uno::DeploymentException(
1367 "InvalidRegistryException: " + e.Message,
1368 static_cast< cppu::OWeakObject * >(this));
1370 } catch (css::uno::RuntimeException &) {
1371 if (!readLegacyRdbFile(uri)) {
1372 throw;
1375 #endif
1378 #if !ENABLE_FUZZERS
1379 bool cppuhelper::ServiceManager::readLegacyRdbFile(OUString const & uri) {
1380 Registry reg;
1381 switch (reg.open(uri, RegAccessMode::READONLY)) {
1382 case RegError::NO_ERROR:
1383 break;
1384 case RegError::REGISTRY_NOT_EXISTS:
1385 case RegError::INVALID_REGISTRY:
1387 // Ignore empty rdb files (which are at least seen by subordinate
1388 // uno processes during extension registration; Registry::open can
1389 // fail on them if mmap(2) returns EINVAL for a zero length):
1390 osl::DirectoryItem item;
1391 if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
1392 osl::FileStatus status(osl_FileStatus_Mask_FileSize);
1393 if (item.getFileStatus(status) == osl::FileBase::E_None
1394 && status.getFileSize() == 0)
1396 return true;
1400 [[fallthrough]];
1401 default:
1402 return false;
1404 RegistryKey rootKey;
1405 if (reg.openRootKey(rootKey) != RegError::NO_ERROR) {
1406 throw css::uno::DeploymentException(
1407 "Failure reading legacy rdb file " + uri,
1408 static_cast< cppu::OWeakObject * >(this));
1410 RegistryKeyArray impls;
1411 switch (rootKey.openSubKeys(u"IMPLEMENTATIONS"_ustr, impls)) {
1412 case RegError::NO_ERROR:
1413 break;
1414 case RegError::KEY_NOT_EXISTS:
1415 return true;
1416 default:
1417 throw css::uno::DeploymentException(
1418 "Failure reading legacy rdb file " + uri,
1419 static_cast< cppu::OWeakObject * >(this));
1421 for (sal_uInt32 i = 0; i != impls.getLength(); ++i) {
1422 RegistryKey implKey(impls.getElement(i));
1423 assert(implKey.getName().match("/IMPLEMENTATIONS/"));
1424 OUString name(
1425 implKey.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1426 std::shared_ptr< Data::Implementation > impl =
1427 std::make_shared<Data::Implementation>(
1428 name, readLegacyRdbString(uri, implKey, u"UNO/ACTIVATOR"_ustr),
1429 readLegacyRdbString(uri, implKey, u"UNO/LOCATION"_ustr), "", "", "", false,
1430 css::uno::Reference< css::uno::XComponentContext >(), uri);
1431 if (!data_.namedImplementations.emplace(name, impl).second)
1433 throw css::registry::InvalidRegistryException(
1434 uri + ": duplicate <implementation name=\"" + name + "\">");
1436 readLegacyRdbStrings(
1437 uri, implKey, u"UNO/SERVICES"_ustr, &impl->services);
1438 for (const auto& rService : impl->services)
1440 data_.services[rService].push_back(impl);
1442 readLegacyRdbStrings(
1443 uri, implKey, u"UNO/SINGLETONS"_ustr, &impl->singletons);
1444 for (const auto& rSingleton : impl->singletons)
1446 data_.singletons[rSingleton].push_back(impl);
1449 return true;
1452 OUString cppuhelper::ServiceManager::readLegacyRdbString(
1453 std::u16string_view uri, RegistryKey & key, OUString const & path)
1455 RegistryKey subkey;
1456 RegValueType t;
1457 sal_uInt32 s(0);
1458 if (key.openKey(path, subkey) != RegError::NO_ERROR
1459 || subkey.getValueInfo(OUString(), &t, &s) != RegError::NO_ERROR
1460 || t != RegValueType::STRING
1461 || s == 0 || s > o3tl::make_unsigned(SAL_MAX_INT32))
1463 throw css::uno::DeploymentException(
1464 OUString::Concat("Failure reading legacy rdb file ") + uri,
1465 static_cast< cppu::OWeakObject * >(this));
1467 OUString val;
1468 std::vector< char > v(s); // assuming sal_uInt32 fits into vector::size_type
1469 if (subkey.getValue(OUString(), v.data()) != RegError::NO_ERROR
1470 || v.back() != '\0'
1471 || !rtl_convertStringToUString(
1472 &val.pData, v.data(), static_cast< sal_Int32 >(s - 1),
1473 RTL_TEXTENCODING_UTF8,
1474 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1475 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1476 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
1478 throw css::uno::DeploymentException(
1479 OUString::Concat("Failure reading legacy rdb file ") + uri,
1480 static_cast< cppu::OWeakObject * >(this));
1482 return val;
1485 void cppuhelper::ServiceManager::readLegacyRdbStrings(
1486 std::u16string_view uri, RegistryKey & key, OUString const & path,
1487 std::vector< OUString > * strings)
1489 assert(strings != nullptr);
1490 RegistryKey subkey;
1491 switch (key.openKey(path, subkey)) {
1492 case RegError::NO_ERROR:
1493 break;
1494 case RegError::KEY_NOT_EXISTS:
1495 return;
1496 default:
1497 throw css::uno::DeploymentException(
1498 OUString::Concat("Failure reading legacy rdb file ") + uri,
1499 static_cast< cppu::OWeakObject * >(this));
1501 OUString prefix(subkey.getName() + "/");
1502 RegistryKeyNames names;
1503 if (subkey.getKeyNames(OUString(), names) != RegError::NO_ERROR) {
1504 throw css::uno::DeploymentException(
1505 OUString::Concat("Failure reading legacy rdb file ") + uri,
1506 static_cast< cppu::OWeakObject * >(this));
1508 for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
1509 assert(names.getElement(i).match(prefix));
1510 strings->push_back(names.getElement(i).copy(prefix.getLength()));
1513 #endif
1515 void cppuhelper::ServiceManager::insertRdbFiles(
1516 std::vector< OUString > const & uris,
1517 css::uno::Reference< css::uno::XComponentContext > const & alienContext)
1519 Data extra;
1520 for (const auto& rUri : uris)
1522 try {
1523 Parser(rUri, alienContext, &extra);
1524 } catch (css::container::NoSuchElementException &) {
1525 throw css::lang::IllegalArgumentException(
1526 rUri + ": no such file", static_cast< cppu::OWeakObject * >(this),
1528 } catch (css::registry::InvalidRegistryException & e) {
1529 throw css::lang::IllegalArgumentException(
1530 "InvalidRegistryException: " + e.Message,
1531 static_cast< cppu::OWeakObject * >(this), 0);
1534 insertExtraData(extra);
1537 void cppuhelper::ServiceManager::insertLegacyFactory(
1538 css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo)
1540 assert(factoryInfo.is());
1541 OUString name(factoryInfo->getImplementationName());
1542 css::uno::Reference< css::lang::XSingleComponentFactory > f1(
1543 factoryInfo, css::uno::UNO_QUERY);
1544 css::uno::Reference< css::lang::XSingleServiceFactory > f2;
1545 if (!f1.is()) {
1546 f2.set(factoryInfo, css::uno::UNO_QUERY);
1547 if (!f2.is()) {
1548 throw css::lang::IllegalArgumentException(
1549 (u"Bad XServiceInfo argument implements neither"
1550 " XSingleComponentFactory nor XSingleServiceFactory"_ustr),
1551 static_cast< cppu::OWeakObject * >(this), 0);
1554 css::uno::Reference< css::lang::XComponent > comp(
1555 factoryInfo, css::uno::UNO_QUERY);
1556 std::shared_ptr< Data::Implementation > impl =
1557 std::make_shared<Data::Implementation>(name, f1, f2, comp);
1558 Data extra;
1559 if (!name.isEmpty()) {
1560 extra.namedImplementations.emplace(name, impl);
1562 extra.dynamicImplementations.emplace(factoryInfo, impl);
1563 const css::uno::Sequence< OUString > services(
1564 factoryInfo->getSupportedServiceNames());
1565 for (const auto & i : services) {
1566 impl->services.push_back(i);
1567 extra.services[i].push_back(impl);
1569 if (insertExtraData(extra) && comp.is()) {
1570 comp->addEventListener(this);
1574 bool cppuhelper::ServiceManager::insertExtraData(Data const & extra) {
1576 std::unique_lock g(m_aMutex);
1577 if (m_bDisposed) {
1578 return false;
1580 auto i = std::find_if(extra.namedImplementations.begin(), extra.namedImplementations.end(),
1581 [this](const Data::NamedImplementations::value_type& rEntry) {
1582 return data_.namedImplementations.find(rEntry.first) != data_.namedImplementations.end(); });
1583 if (i != extra.namedImplementations.end())
1585 throw css::lang::IllegalArgumentException(
1586 "Insert duplicate implementation name " + i->first,
1587 static_cast< cppu::OWeakObject * >(this), 0);
1589 bool bDuplicate = std::any_of(extra.dynamicImplementations.begin(), extra.dynamicImplementations.end(),
1590 [this](const Data::DynamicImplementations::value_type& rEntry) {
1591 return data_.dynamicImplementations.find(rEntry.first) != data_.dynamicImplementations.end(); });
1592 if (bDuplicate)
1594 throw css::lang::IllegalArgumentException(
1595 u"Insert duplicate factory object"_ustr,
1596 static_cast< cppu::OWeakObject * >(this), 0);
1598 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1599 data_.namedImplementations.insert(
1600 extra.namedImplementations.begin(),
1601 extra.namedImplementations.end());
1602 data_.dynamicImplementations.insert(
1603 extra.dynamicImplementations.begin(),
1604 extra.dynamicImplementations.end());
1605 insertImplementationMap(&data_.services, extra.services);
1606 insertImplementationMap(&data_.singletons, extra.singletons);
1608 //TODO: Updating the component context singleton data should be part of the
1609 // atomic service manager update:
1610 if (extra.singletons.empty())
1611 return true;
1613 assert(context_.is());
1614 css::uno::Reference< css::container::XNameContainer > cont(
1615 context_, css::uno::UNO_QUERY_THROW);
1616 for (const auto& [rName, rImpls] : extra.singletons)
1618 OUString name("/singletons/" + rName);
1619 //TODO: Update should be atomic:
1620 try {
1621 cont->removeByName(name + "/arguments");
1622 } catch (const css::container::NoSuchElementException &) {}
1623 assert(!rImpls.empty());
1624 assert(rImpls[0]);
1625 SAL_INFO_IF(
1626 rImpls.size() > 1, "cppuhelper",
1627 "Arbitrarily choosing " << rImpls[0]->name
1628 << " among multiple implementations for singleton "
1629 << rName);
1630 try {
1631 cont->insertByName(
1632 name + "/service", css::uno::Any(rImpls[0]->name));
1633 } catch (css::container::ElementExistException &) {
1634 cont->replaceByName(
1635 name + "/service", css::uno::Any(rImpls[0]->name));
1637 try {
1638 cont->insertByName(name, css::uno::Any());
1639 } catch (css::container::ElementExistException &) {
1640 SAL_INFO("cppuhelper", "Overwriting singleton " << rName);
1641 cont->replaceByName(name, css::uno::Any());
1644 return true;
1647 void cppuhelper::ServiceManager::removeRdbFiles(
1648 std::vector< OUString > const & uris)
1650 // The underlying data structures make this function somewhat inefficient,
1651 // but the assumption is that it is rarely called (and that if it is called,
1652 // it is called with a uris vector of size one):
1653 std::vector< std::shared_ptr< Data::Implementation > > clear;
1655 std::unique_lock g(m_aMutex);
1656 for (const auto& rUri : uris)
1658 for (Data::NamedImplementations::iterator j(
1659 data_.namedImplementations.begin());
1660 j != data_.namedImplementations.end();)
1662 assert(j->second);
1663 if (j->second->rdbFile == rUri) {
1664 clear.push_back(j->second);
1665 //TODO: The below leaves data_ in an inconsistent state upon
1666 // exceptions:
1667 removeFromImplementationMap(
1668 &data_.services, j->second->services, j->second);
1669 removeFromImplementationMap(
1670 &data_.singletons, j->second->singletons,
1671 j->second);
1672 j = data_.namedImplementations.erase(j);
1673 } else {
1674 ++j;
1679 //TODO: Update the component context singleton data
1682 bool cppuhelper::ServiceManager::removeLegacyFactory(
1683 css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
1684 bool removeListener)
1686 assert(factoryInfo.is());
1687 std::shared_ptr< Data::Implementation > clear;
1688 css::uno::Reference< css::lang::XComponent > comp;
1690 std::unique_lock g(m_aMutex);
1691 Data::DynamicImplementations::iterator i(
1692 data_.dynamicImplementations.find(factoryInfo));
1693 if (i == data_.dynamicImplementations.end()) {
1694 return m_bDisposed;
1696 assert(i->second);
1697 clear = i->second;
1698 if (removeListener) {
1699 comp = i->second->component;
1701 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1702 removeFromImplementationMap(
1703 &data_.services, i->second->services, i->second);
1704 removeFromImplementationMap(
1705 &data_.singletons, i->second->singletons, i->second);
1706 if (!i->second->name.isEmpty()) {
1707 data_.namedImplementations.erase(i->second->name);
1709 data_.dynamicImplementations.erase(i);
1711 if (comp.is()) {
1712 removeEventListenerFromComponent(comp);
1714 return true;
1717 void cppuhelper::ServiceManager::removeImplementation(const OUString & name) {
1718 // The underlying data structures make this function somewhat inefficient,
1719 // but the assumption is that it is rarely called:
1720 std::shared_ptr< Data::Implementation > clear;
1722 std::unique_lock g(m_aMutex);
1723 if (m_bDisposed) {
1724 return;
1726 Data::NamedImplementations::iterator i(
1727 data_.namedImplementations.find(name));
1728 if (i == data_.namedImplementations.end()) {
1729 throw css::container::NoSuchElementException(
1730 "Remove non-inserted implementation " + name,
1731 static_cast< cppu::OWeakObject * >(this));
1733 assert(i->second);
1734 clear = i->second;
1735 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1736 removeFromImplementationMap(
1737 &data_.services, i->second->services, i->second);
1738 removeFromImplementationMap(
1739 &data_.singletons, i->second->singletons, i->second);
1740 auto j = std::find_if(data_.dynamicImplementations.begin(), data_.dynamicImplementations.end(),
1741 [&i](const Data::DynamicImplementations::value_type& rEntry) { return rEntry.second == i->second; });
1742 if (j != data_.dynamicImplementations.end())
1743 data_.dynamicImplementations.erase(j);
1744 data_.namedImplementations.erase(i);
1748 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
1749 cppuhelper::ServiceManager::findServiceImplementation(
1750 css::uno::Reference< css::uno::XComponentContext > const & context,
1751 OUString const & specifier)
1753 std::shared_ptr< Data::Implementation > impl;
1754 bool loaded;
1756 std::unique_lock g(m_aMutex);
1757 Data::ImplementationMap::const_iterator i(
1758 data_.services.find(specifier));
1759 if (i == data_.services.end()) {
1760 Data::NamedImplementations::const_iterator j(
1761 data_.namedImplementations.find(specifier));
1762 if (j == data_.namedImplementations.end()) {
1763 SAL_INFO("cppuhelper", "No implementation for " << specifier);
1764 return std::shared_ptr< Data::Implementation >();
1766 impl = j->second;
1767 } else {
1768 assert(!i->second.empty());
1769 SAL_INFO_IF(
1770 i->second.size() > 1, "cppuhelper",
1771 "Arbitrarily choosing " << i->second[0]->name
1772 << " among multiple implementations for " << i->first);
1773 impl = i->second[0];
1775 assert(impl);
1776 loaded = impl->status == Data::Implementation::STATUS_LOADED;
1778 if (!loaded) {
1779 loadImplementation(context, impl);
1781 return impl;
1784 /// Make a simpler unique name for preload / progress reporting.
1785 #ifndef DISABLE_DYNLOADING
1786 static OUString simplifyModule(std::u16string_view uri)
1788 sal_Int32 nIdx;
1789 OUStringBuffer edit(uri);
1790 if ((nIdx = edit.lastIndexOf('/')) > 0)
1791 edit.remove(0,nIdx+1);
1792 if ((nIdx = edit.lastIndexOf(':')) > 0)
1793 edit.remove(0,nIdx+1);
1794 if ((nIdx = edit.lastIndexOf("lo.so")) > 0)
1795 edit.truncate(nIdx);
1796 if ((nIdx = edit.lastIndexOf(".3")) > 0)
1797 edit.truncate(nIdx);
1798 if ((nIdx = edit.lastIndexOf("gcc3.so")) > 0)
1799 edit.truncate(nIdx);
1800 if ((nIdx = edit.lastIndexOf(".so")) > 0)
1801 edit.truncate(nIdx);
1802 if ((nIdx = edit.lastIndexOf("_uno")) > 0)
1803 edit.truncate(nIdx);
1804 if ((nIdx = edit.lastIndexOf(".jar")) > 0)
1805 edit.truncate(nIdx);
1806 if (edit.indexOf("lib") == 0)
1807 edit.remove(0,3);
1808 return edit.makeStringAndClear();
1810 #endif
1812 /// Used only by LibreOfficeKit when used by Online to pre-initialize
1813 void cppuhelper::ServiceManager::preloadImplementations() {
1814 #ifdef DISABLE_DYNLOADING
1815 abort();
1816 #else
1817 OUString aUri;
1818 std::unique_lock g(m_aMutex);
1819 css::uno::Environment aSourceEnv(css::uno::Environment::getCurrent());
1821 std::cerr << "preload:";
1822 std::vector<OUString> aReported;
1823 std::vector<OUString> aDisabled;
1824 OUStringBuffer aDisabledMsg;
1825 OUStringBuffer aMissingMsg;
1827 /// Allow external callers & testers to disable certain components
1828 const char *pDisable = getenv("UNODISABLELIBRARY");
1829 if (pDisable)
1831 OUString aDisable(pDisable, strlen(pDisable), RTL_TEXTENCODING_UTF8);
1832 for (sal_Int32 i = 0; i >= 0; )
1834 OUString tok( aDisable.getToken(0, ' ', i) );
1835 tok = tok.trim();
1836 if (!tok.isEmpty())
1837 aDisabled.push_back(tok);
1841 // loop all implementations
1842 for (const auto& rEntry : data_.namedImplementations)
1844 if (rEntry.second->loader != "com.sun.star.loader.SharedLibrary" ||
1845 rEntry.second->status == Data::Implementation::STATUS_LOADED)
1846 continue;
1848 OUString simplified;
1851 const OUString &aLibrary = rEntry.second->uri;
1853 if (aLibrary.isEmpty())
1854 continue;
1856 simplified = simplifyModule(aLibrary);
1858 bool bDisabled =
1859 std::find(aDisabled.begin(), aDisabled.end(), simplified) != aDisabled.end();
1861 if (std::find(aReported.begin(), aReported.end(), aLibrary) == aReported.end())
1863 if (bDisabled)
1865 aDisabledMsg.append(simplified + " ");
1867 else
1869 std::cerr << " " << simplified;
1870 std::cerr.flush();
1872 aReported.push_back(aLibrary);
1875 if (bDisabled)
1876 continue;
1878 // expand absolute URI implementation component library
1879 aUri = cppu::bootstrap_expandUri(aLibrary);
1881 catch (css::lang::IllegalArgumentException& aError)
1883 throw css::uno::DeploymentException(
1884 "Cannot expand URI" + rEntry.second->uri + ": " + aError.Message,
1885 static_cast< cppu::OWeakObject * >(this));
1888 // load component library
1889 osl::Module aModule(aUri, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL);
1891 if (!aModule.is())
1893 aMissingMsg.append(simplified + " ");
1896 if (aModule.is() &&
1897 !rEntry.second->environment.isEmpty())
1899 oslGenericFunction fpFactory;
1900 css::uno::Environment aTargetEnv;
1901 css::uno::Reference<css::uno::XInterface> xFactory;
1903 if(rEntry.second->constructorName.isEmpty())
1905 OUString aSymFactory;
1906 // expand full name component factory symbol
1907 if (rEntry.second->prefix == "direct")
1908 aSymFactory = rEntry.second->name.replace('.', '_') + "_" COMPONENT_GETFACTORY;
1909 else if (!rEntry.second->prefix.isEmpty())
1910 aSymFactory = rEntry.second->prefix + "_" COMPONENT_GETFACTORY;
1911 else
1912 aSymFactory = COMPONENT_GETFACTORY;
1914 // get function symbol component factory
1915 fpFactory = aModule.getFunctionSymbol(aSymFactory);
1916 if (fpFactory == nullptr)
1918 throw css::loader::CannotActivateFactoryException(
1919 ("no factory symbol \"" + aSymFactory + "\" in component library :" + aUri),
1920 css::uno::Reference<css::uno::XInterface>());
1923 aTargetEnv = cppuhelper::detail::getEnvironment(rEntry.second->environment, rEntry.second->name);
1924 component_getFactoryFunc fpComponentFactory = reinterpret_cast<component_getFactoryFunc>(fpFactory);
1926 if (aSourceEnv.get() == aTargetEnv.get())
1928 // invoke function component factory
1929 OString aImpl(OUStringToOString(rEntry.second->name, RTL_TEXTENCODING_ASCII_US));
1930 xFactory.set(css::uno::Reference<css::uno::XInterface>(static_cast<css::uno::XInterface *>(
1931 (*fpComponentFactory)(aImpl.getStr(), this, nullptr)), SAL_NO_ACQUIRE));
1934 else
1936 // get function symbol component factory
1937 aTargetEnv = cppuhelper::detail::getEnvironment(rEntry.second->environment, rEntry.second->name);
1938 fpFactory = (aSourceEnv.get() == aTargetEnv.get()) ?
1939 aModule.getFunctionSymbol(rEntry.second->constructorName) : nullptr;
1942 css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory;
1943 css::uno::Reference<css::lang::XSingleServiceFactory> xSSFactory;
1945 // query interface XSingleComponentFactory or XSingleServiceFactory
1946 if (xFactory.is())
1948 xSCFactory.set(xFactory, css::uno::UNO_QUERY);
1949 if (!xSCFactory.is())
1951 xSSFactory.set(xFactory, css::uno::UNO_QUERY);
1952 if (!xSSFactory.is())
1953 throw css::uno::DeploymentException(
1954 ("Implementation " + rEntry.second->name
1955 + " does not provide a constructor or factory"),
1956 static_cast< cppu::OWeakObject * >(this));
1960 if (!rEntry.second->constructorName.isEmpty() && fpFactory)
1961 rEntry.second->constructorFn = WrapperConstructorFn(reinterpret_cast<ImplementationConstructorFn *>(fpFactory));
1963 rEntry.second->factory1 = xSCFactory;
1964 rEntry.second->factory2 = xSSFactory;
1965 rEntry.second->status = Data::Implementation::STATUS_LOADED;
1969 // Some libraries use other (non-UNO) libraries requiring preinit
1970 oslGenericFunction fpPreload = aModule.getFunctionSymbol( "lok_preload_hook" );
1971 if (fpPreload)
1973 static std::vector<oslGenericFunction> aPreloaded;
1974 if (std::find(aPreloaded.begin(), aPreloaded.end(), fpPreload) == aPreloaded.end())
1976 aPreloaded.push_back(fpPreload);
1977 // unlock because we may be instantiating some services here
1978 g.unlock();
1979 fpPreload();
1980 g.lock();
1984 // leak aModule
1985 aModule.release();
1987 std::cerr << std::endl;
1989 if (aMissingMsg.getLength() > 0)
1991 OUString aMsg = aMissingMsg.makeStringAndClear();
1992 std::cerr << "Absent (often optional): " << aMsg << "\n";
1994 if (aDisabledMsg.getLength() > 0)
1996 OUString aMsg = aDisabledMsg.makeStringAndClear();
1997 std::cerr << "Disabled: " << aMsg << "\n";
1999 std::cerr.flush();
2001 // Various rather important uno mappings.
2002 static struct {
2003 OUString maFrom;
2004 OUString maTo;
2005 OUString maPurpose;
2006 } constexpr aMappingLoad[] = {
2007 { u"gcc3"_ustr, u"uno"_ustr, u""_ustr },
2008 { u"uno"_ustr, u"gcc3"_ustr, u""_ustr },
2011 static std::vector<css::uno::Mapping> maMaps;
2012 for (auto &it : aMappingLoad)
2014 maMaps.push_back(css::uno::Mapping(it.maFrom, it.maTo, it.maPurpose));
2016 #endif
2019 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */