Remove exec bits from docx
[LibreOffice.git] / cppuhelper / source / servicemanager.cxx
blob1e9c2dbbc1922057d7f20d7e86dc696f9eba8f6a
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 std::vector<
72 std::shared_ptr<
73 cppuhelper::ServiceManager::Data::Implementation > > & impls
74 = (*destination)[rName];
75 impls.insert(impls.end(), rImpls.begin(), rImpls.end());
79 void removeFromImplementationMap(
80 cppuhelper::ServiceManager::Data::ImplementationMap * map,
81 std::vector< OUString > const & elements,
82 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
83 const & implementation)
85 // The underlying data structures make this function somewhat inefficient,
86 // but the assumption is that it is rarely called:
87 assert(map != nullptr);
88 for (const auto& rElement : elements)
90 cppuhelper::ServiceManager::Data::ImplementationMap::iterator j(
91 map->find(rElement));
92 assert(j != map->end());
93 std::vector<
94 std::shared_ptr<
95 cppuhelper::ServiceManager::Data::Implementation > >::iterator
96 k(std::find(j->second.begin(), j->second.end(), implementation));
97 assert(k != j->second.end());
98 j->second.erase(k);
99 if (j->second.empty()) {
100 map->erase(j);
105 // For simplicity, this code keeps throwing
106 // css::registry::InvalidRegistryException for invalid XML rdbs (even though
107 // that does not fit the exception's name):
108 class Parser {
109 public:
110 Parser(
111 OUString const & uri,
112 css::uno::Reference< css::uno::XComponentContext > alienContext,
113 cppuhelper::ServiceManager::Data * data);
115 Parser(const Parser&) = delete;
116 const Parser& operator=(const Parser&) = delete;
118 private:
119 void handleComponent();
121 void handleImplementation();
123 void handleService();
125 void handleSingleton();
127 OUString getNameAttribute();
129 xmlreader::XmlReader reader_;
130 css::uno::Reference< css::uno::XComponentContext > alienContext_;
131 cppuhelper::ServiceManager::Data * data_;
132 OUString attrLoader_;
133 OUString attrUri_;
134 OUString attrEnvironment_;
135 OUString attrPrefix_;
136 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
137 implementation_;
140 Parser::Parser(
141 OUString const & uri,
142 css::uno::Reference< css::uno::XComponentContext > alienContext,
143 cppuhelper::ServiceManager::Data * data):
144 reader_(uri), alienContext_(std::move(alienContext)), data_(data)
146 assert(data != nullptr);
147 int ucNsId = reader_.registerNamespaceIri(
148 xmlreader::Span(
149 RTL_CONSTASCII_STRINGPARAM(
150 "http://openoffice.org/2010/uno-components")));
151 enum State {
152 STATE_BEGIN, STATE_END, STATE_COMPONENTS, STATE_COMPONENT_INITIAL,
153 STATE_COMPONENT, STATE_IMPLEMENTATION, STATE_SERVICE, STATE_SINGLETON };
154 for (State state = STATE_BEGIN;;) {
155 xmlreader::Span name;
156 int nsId;
157 xmlreader::XmlReader::Result res = reader_.nextItem(
158 xmlreader::XmlReader::Text::NONE, &name, &nsId);
159 switch (state) {
160 case STATE_BEGIN:
161 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
162 && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
164 state = STATE_COMPONENTS;
165 break;
167 throw css::registry::InvalidRegistryException(
168 reader_.getUrl() + ": unexpected item in outer level");
169 case STATE_END:
170 if (res == xmlreader::XmlReader::Result::Done) {
171 return;
173 throw css::registry::InvalidRegistryException(
174 reader_.getUrl() + ": unexpected item in outer level");
175 case STATE_COMPONENTS:
176 if (res == xmlreader::XmlReader::Result::End) {
177 state = STATE_END;
178 break;
180 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
181 && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
183 handleComponent();
184 state = STATE_COMPONENT_INITIAL;
185 break;
187 throw css::registry::InvalidRegistryException(
188 reader_.getUrl() + ": unexpected item in <components>");
189 case STATE_COMPONENT:
190 if (res == xmlreader::XmlReader::Result::End) {
191 state = STATE_COMPONENTS;
192 break;
194 [[fallthrough]];
195 case STATE_COMPONENT_INITIAL:
196 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
197 && name.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
199 handleImplementation();
200 state = STATE_IMPLEMENTATION;
201 break;
203 throw css::registry::InvalidRegistryException(
204 reader_.getUrl() + ": unexpected item in <component>");
205 case STATE_IMPLEMENTATION:
206 if (res == xmlreader::XmlReader::Result::End) {
207 state = STATE_COMPONENT;
208 break;
210 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
211 && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
213 handleService();
214 state = STATE_SERVICE;
215 break;
217 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
218 && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
220 handleSingleton();
221 state = STATE_SINGLETON;
222 break;
224 throw css::registry::InvalidRegistryException(
225 reader_.getUrl() + ": unexpected item in <implementation>");
226 case STATE_SERVICE:
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>");
233 case STATE_SINGLETON:
234 if (res == xmlreader::XmlReader::Result::End) {
235 state = STATE_IMPLEMENTATION;
236 break;
238 throw css::registry::InvalidRegistryException(
239 reader_.getUrl() + ": unexpected item in <service>");
244 void Parser::handleComponent() {
245 attrLoader_ = OUString();
246 attrUri_ = OUString();
247 attrEnvironment_ = OUString();
248 attrPrefix_ = OUString();
249 xmlreader::Span name;
250 int nsId;
251 while (reader_.nextAttribute(&nsId, &name)) {
252 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
253 && name.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
255 if (!attrLoader_.isEmpty()) {
256 throw css::registry::InvalidRegistryException(
257 reader_.getUrl()
258 + ": <component> has multiple \"loader\" attributes");
260 attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8();
261 if (attrLoader_.isEmpty()) {
262 throw css::registry::InvalidRegistryException(
263 reader_.getUrl()
264 + ": <component> has empty \"loader\" attribute");
266 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
267 && name.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
269 if (!attrUri_.isEmpty()) {
270 throw css::registry::InvalidRegistryException(
271 reader_.getUrl()
272 + ": <component> has multiple \"uri\" attributes");
274 attrUri_ = reader_.getAttributeValue(false).convertFromUtf8();
275 if (attrUri_.isEmpty()) {
276 throw css::registry::InvalidRegistryException(
277 reader_.getUrl()
278 + ": <component> has empty \"uri\" attribute");
280 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
281 && name.equals(RTL_CONSTASCII_STRINGPARAM("environment")))
283 if (!attrEnvironment_.isEmpty()) {
284 throw css::registry::InvalidRegistryException(
285 reader_.getUrl() +
286 ": <component> has multiple \"environment\" attributes");
288 attrEnvironment_ = reader_.getAttributeValue(false)
289 .convertFromUtf8();
290 if (attrEnvironment_.isEmpty()) {
291 throw css::registry::InvalidRegistryException(
292 reader_.getUrl() +
293 ": <component> has empty \"environment\" attribute");
295 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
296 && name.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
298 if (!attrPrefix_.isEmpty()) {
299 throw css::registry::InvalidRegistryException(
300 reader_.getUrl() +
301 ": <component> has multiple \"prefix\" attributes");
303 attrPrefix_ = reader_.getAttributeValue(false).convertFromUtf8();
304 if (attrPrefix_.isEmpty()) {
305 throw css::registry::InvalidRegistryException(
306 reader_.getUrl() +
307 ": <component> has empty \"prefix\" attribute");
309 } else {
310 throw css::registry::InvalidRegistryException(
311 reader_.getUrl() + ": unexpected attribute \""
312 + name.convertFromUtf8() + "\" in <component>");
315 if (attrLoader_.isEmpty()) {
316 throw css::registry::InvalidRegistryException(
317 reader_.getUrl() + ": <component> is missing \"loader\" attribute");
319 if (attrUri_.isEmpty()) {
320 throw css::registry::InvalidRegistryException(
321 reader_.getUrl() + ": <component> is missing \"uri\" attribute");
323 #ifndef DISABLE_DYNLOADING
324 try {
325 attrUri_ = rtl::Uri::convertRelToAbs(reader_.getUrl(), attrUri_);
326 } catch (const rtl::MalformedUriException & e) {
327 throw css::registry::InvalidRegistryException(
328 reader_.getUrl() + ": bad \"uri\" attribute: " + e.getMessage());
330 #endif
333 void Parser::handleImplementation() {
334 OUString attrName;
335 OUString attrConstructor;
336 bool attrSingleInstance = false;
337 xmlreader::Span name;
338 int nsId;
339 while (reader_.nextAttribute(&nsId, &name)) {
340 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
341 && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
343 if (!attrName.isEmpty()) {
344 throw css::registry::InvalidRegistryException(
345 reader_.getUrl()
346 + ": <implementation> has multiple \"name\" attributes");
348 attrName = reader_.getAttributeValue(false).convertFromUtf8();
349 if (attrName.isEmpty()) {
350 throw css::registry::InvalidRegistryException(
351 reader_.getUrl()
352 + ": <implementation> has empty \"name\" attribute");
354 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
355 && name.equals(RTL_CONSTASCII_STRINGPARAM("constructor")))
357 if (!attrConstructor.isEmpty()) {
358 throw css::registry::InvalidRegistryException(
359 reader_.getUrl()
360 + ": <implementation> has multiple \"constructor\""
361 " attributes");
363 attrConstructor = reader_.getAttributeValue(false)
364 .convertFromUtf8();
365 if (attrConstructor.isEmpty()) {
366 throw css::registry::InvalidRegistryException(
367 reader_.getUrl()
368 + ": element has empty \"constructor\" attribute");
370 if (attrEnvironment_.isEmpty()) {
371 throw css::registry::InvalidRegistryException(
372 reader_.getUrl()
373 + ": <implementation> has \"constructor\" attribute but"
374 " <component> has no \"environment\" attribute");
376 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
377 && name.equals(RTL_CONSTASCII_STRINGPARAM("single-instance")))
379 if (attrSingleInstance) {
380 throw css::registry::InvalidRegistryException(
381 reader_.getUrl()
382 + ": <implementation> has multiple \"single-instance\" attributes");
384 if (!reader_.getAttributeValue(false).equals(RTL_CONSTASCII_STRINGPARAM("true"))) {
385 throw css::registry::InvalidRegistryException(
386 reader_.getUrl() + ": <implementation> has bad \"single-instance\" attribute");
388 attrSingleInstance = true;
389 } else {
390 throw css::registry::InvalidRegistryException(
391 reader_.getUrl() + ": unexpected element attribute \""
392 + name.convertFromUtf8() + "\" in <implementation>");
395 if (attrName.isEmpty()) {
396 throw css::registry::InvalidRegistryException(
397 reader_.getUrl()
398 + ": <implementation> is missing \"name\" attribute");
400 implementation_ =
401 std::make_shared<cppuhelper::ServiceManager::Data::Implementation>(
402 attrName, attrLoader_, attrUri_, attrEnvironment_, attrConstructor,
403 attrPrefix_, attrSingleInstance, alienContext_, reader_.getUrl());
404 if (!data_->namedImplementations.emplace(attrName, implementation_).
405 second)
407 throw css::registry::InvalidRegistryException(
408 reader_.getUrl() + ": duplicate <implementation name=\"" + attrName
409 + "\">");
413 void Parser::handleService() {
414 OUString name(getNameAttribute());
415 implementation_->services.push_back(name);
416 data_->services[name].push_back(implementation_);
419 void Parser::handleSingleton() {
420 OUString name(getNameAttribute());
421 implementation_->singletons.push_back(name);
422 data_->singletons[name].push_back(implementation_);
425 OUString Parser::getNameAttribute() {
426 OUString attrName;
427 xmlreader::Span name;
428 int nsId;
429 while (reader_.nextAttribute(&nsId, &name)) {
430 if (nsId != xmlreader::XmlReader::NAMESPACE_NONE
431 || !name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
433 throw css::registry::InvalidRegistryException(
434 reader_.getUrl() + ": expected element attribute \"name\"");
436 if (!attrName.isEmpty()) {
437 throw css::registry::InvalidRegistryException(
438 reader_.getUrl()
439 + ": element has multiple \"name\" attributes");
441 attrName = reader_.getAttributeValue(false).convertFromUtf8();
442 if (attrName.isEmpty()) {
443 throw css::registry::InvalidRegistryException(
444 reader_.getUrl() + ": element has empty \"name\" attribute");
447 if (attrName.isEmpty()) {
448 throw css::registry::InvalidRegistryException(
449 reader_.getUrl() + ": element is missing \"name\" attribute");
451 return attrName;
454 class ContentEnumeration:
455 public cppu::WeakImplHelper< css::container::XEnumeration >
457 public:
458 explicit ContentEnumeration(std::vector< css::uno::Any >&& factories):
459 factories_(std::move(factories)), iterator_(factories_.begin()) {}
461 ContentEnumeration(const ContentEnumeration&) = delete;
462 const ContentEnumeration& operator=(const ContentEnumeration&) = delete;
464 private:
465 virtual ~ContentEnumeration() override {}
467 virtual sal_Bool SAL_CALL hasMoreElements() override;
469 virtual css::uno::Any SAL_CALL nextElement() override;
471 std::mutex mutex_;
472 std::vector< css::uno::Any > factories_;
473 std::vector< css::uno::Any >::const_iterator iterator_;
476 sal_Bool ContentEnumeration::hasMoreElements()
478 std::scoped_lock g(mutex_);
479 return iterator_ != factories_.end();
482 css::uno::Any ContentEnumeration::nextElement()
484 std::scoped_lock g(mutex_);
485 if (iterator_ == factories_.end()) {
486 throw css::container::NoSuchElementException(
487 "Bootstrap service manager service enumerator has no more elements",
488 static_cast< cppu::OWeakObject * >(this));
490 return *iterator_++;
493 css::beans::Property getDefaultContextProperty() {
494 return css::beans::Property(
495 "DefaultContext", -1,
496 cppu::UnoType< css::uno::XComponentContext >::get(),
497 css::beans::PropertyAttribute::READONLY);
500 class SingletonFactory:
501 public cppu::WeakImplHelper<css::lang::XSingleComponentFactory>
503 public:
504 SingletonFactory(
505 rtl::Reference< cppuhelper::ServiceManager > const & manager,
506 std::shared_ptr<
507 cppuhelper::ServiceManager::Data::Implementation > const &
508 implementation):
509 manager_(manager), implementation_(implementation)
510 { assert(manager.is()); assert(implementation); }
512 SingletonFactory(const SingletonFactory&) = delete;
513 const SingletonFactory& operator=(const SingletonFactory&) = delete;
515 private:
516 virtual ~SingletonFactory() override {}
518 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
519 createInstanceWithContext(
520 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
522 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
523 createInstanceWithArgumentsAndContext(
524 css::uno::Sequence< css::uno::Any > const & Arguments,
525 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
527 rtl::Reference< cppuhelper::ServiceManager > manager_;
528 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
529 implementation_;
532 css::uno::Reference< css::uno::XInterface >
533 SingletonFactory::createInstanceWithContext(
534 css::uno::Reference< css::uno::XComponentContext > const & Context)
536 manager_->loadImplementation(Context, implementation_);
537 return implementation_->createInstance(Context, true);
540 css::uno::Reference< css::uno::XInterface >
541 SingletonFactory::createInstanceWithArgumentsAndContext(
542 css::uno::Sequence< css::uno::Any > const & Arguments,
543 css::uno::Reference< css::uno::XComponentContext > const & Context)
545 manager_->loadImplementation(Context, implementation_);
546 return implementation_->createInstanceWithArguments(
547 Context, true, Arguments);
550 class ImplementationWrapper:
551 public cppu::WeakImplHelper<
552 css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
553 css::lang::XServiceInfo >
555 public:
556 ImplementationWrapper(
557 rtl::Reference< cppuhelper::ServiceManager > const & manager,
558 std::shared_ptr<
559 cppuhelper::ServiceManager::Data::Implementation > const &
560 implementation):
561 manager_(manager), implementation_(implementation)
562 { assert(manager.is()); assert(implementation); }
564 ImplementationWrapper(const ImplementationWrapper&) = delete;
565 const ImplementationWrapper& operator=(const ImplementationWrapper&) = delete;
567 private:
568 virtual ~ImplementationWrapper() override {}
570 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
571 createInstanceWithContext(
572 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
574 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
575 createInstanceWithArgumentsAndContext(
576 css::uno::Sequence< css::uno::Any > const & Arguments,
577 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
579 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
580 createInstance() override;
582 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
583 createInstanceWithArguments(
584 css::uno::Sequence< css::uno::Any > const & Arguments) override;
586 virtual OUString SAL_CALL getImplementationName() override;
588 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
590 virtual css::uno::Sequence< OUString > SAL_CALL
591 getSupportedServiceNames() override;
593 rtl::Reference< cppuhelper::ServiceManager > manager_;
594 std::weak_ptr< cppuhelper::ServiceManager::Data::Implementation >
595 implementation_;
598 css::uno::Reference< css::uno::XInterface >
599 ImplementationWrapper::createInstanceWithContext(
600 css::uno::Reference< css::uno::XComponentContext > const & Context)
602 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
603 assert(impl);
604 manager_->loadImplementation(Context, impl);
605 return impl->createInstance(Context, false);
608 css::uno::Reference< css::uno::XInterface >
609 ImplementationWrapper::createInstanceWithArgumentsAndContext(
610 css::uno::Sequence< css::uno::Any > const & Arguments,
611 css::uno::Reference< css::uno::XComponentContext > const & Context)
613 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
614 assert(impl);
615 manager_->loadImplementation(Context, impl);
616 return impl->createInstanceWithArguments(
617 Context, false, Arguments);
620 css::uno::Reference< css::uno::XInterface >
621 ImplementationWrapper::createInstance()
623 return createInstanceWithContext(manager_->getContext());
626 css::uno::Reference< css::uno::XInterface >
627 ImplementationWrapper::createInstanceWithArguments(
628 css::uno::Sequence< css::uno::Any > const & Arguments)
630 return createInstanceWithArgumentsAndContext(
631 Arguments, manager_->getContext());
634 OUString ImplementationWrapper::getImplementationName()
636 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
637 assert(impl);
638 return impl->name;
641 sal_Bool ImplementationWrapper::supportsService(OUString const & ServiceName)
643 return cppu::supportsService(this, ServiceName);
646 css::uno::Sequence< OUString >
647 ImplementationWrapper::getSupportedServiceNames()
649 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
650 assert(impl);
651 if (impl->services.size()
652 > o3tl::make_unsigned(SAL_MAX_INT32))
654 throw css::uno::RuntimeException(
655 ("Implementation " + impl->name
656 + " supports too many services"),
657 static_cast< cppu::OWeakObject * >(this));
659 return comphelper::containerToSequence(impl->services);
664 css::uno::Reference<css::uno::XInterface>
665 cppuhelper::ServiceManager::Data::Implementation::createInstance(
666 css::uno::Reference<css::uno::XComponentContext> const & context,
667 bool singletonRequest)
669 css::uno::Reference<css::uno::XInterface> inst;
670 if (isSingleInstance) {
671 std::unique_lock g(mutex);
672 if (!singleInstance.is()) {
673 singleInstance = doCreateInstance(context);
675 inst = singleInstance;
676 } else {
677 inst = doCreateInstance(context);
679 updateDisposeInstance(singletonRequest, inst);
680 return inst;
683 css::uno::Reference<css::uno::XInterface>
684 cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
685 css::uno::Reference<css::uno::XComponentContext> const & context,
686 bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
688 css::uno::Reference<css::uno::XInterface> inst;
689 if (isSingleInstance) {
690 std::unique_lock g(mutex);
691 if (!singleInstance.is()) {
692 singleInstance = doCreateInstanceWithArguments(context, arguments);
694 inst = singleInstance;
695 } else {
696 inst = doCreateInstanceWithArguments(context, arguments);
698 updateDisposeInstance(singletonRequest, inst);
699 return inst;
702 css::uno::Reference<css::uno::XInterface>
703 cppuhelper::ServiceManager::Data::Implementation::doCreateInstance(
704 css::uno::Reference<css::uno::XComponentContext> const & context)
706 if (constructorFn) {
707 return css::uno::Reference<css::uno::XInterface>(
708 constructorFn(context.get(), css::uno::Sequence<css::uno::Any>()),
709 SAL_NO_ACQUIRE);
710 } else if (factory1.is()) {
711 return factory1->createInstanceWithContext(context);
712 } else {
713 assert(factory2.is());
714 return factory2->createInstance();
718 css::uno::Reference<css::uno::XInterface>
719 cppuhelper::ServiceManager::Data::Implementation::doCreateInstanceWithArguments(
720 css::uno::Reference<css::uno::XComponentContext> const & context,
721 css::uno::Sequence<css::uno::Any> const & arguments)
723 if (constructorFn) {
724 css::uno::Reference<css::uno::XInterface> inst(
725 constructorFn(context.get(), arguments), SAL_NO_ACQUIRE);
726 //HACK: The constructor will either observe arguments and return inst
727 // that does not implement XInitialization (or null), or ignore
728 // arguments and return inst that implements XInitialization; this
729 // should be removed again once XInitialization-based implementations
730 // have become rare:
731 css::uno::Reference<css::lang::XInitialization> init(
732 inst, css::uno::UNO_QUERY);
733 if (init.is()) {
734 init->initialize(arguments);
736 return inst;
737 } else if (factory1.is()) {
738 return factory1->createInstanceWithArgumentsAndContext(
739 arguments, context);
740 } else {
741 assert(factory2.is());
742 return factory2->createInstanceWithArguments(arguments);
746 void cppuhelper::ServiceManager::Data::Implementation::updateDisposeInstance(
747 bool singletonRequest,
748 css::uno::Reference<css::uno::XInterface> const & instance)
750 // This is an optimization, to only call dispose once (from the component
751 // context) on a singleton that is obtained both via the component context
752 // and via the service manager; however, there is a harmless race here that
753 // may cause two calls to dispose nevertheless (also, this calls dispose on
754 // at most one of the instances obtained via the service manager, in case
755 // the implementation hands out different instances):
756 if (singletonRequest) {
757 std::unique_lock g(mutex);
758 disposeInstance.clear();
759 dispose = false;
760 } else if (shallDispose()) {
761 css::uno::Reference<css::lang::XComponent> comp(
762 instance, css::uno::UNO_QUERY);
763 if (comp.is()) {
764 std::unique_lock g(mutex);
765 if (dispose) {
766 disposeInstance = comp;
772 void cppuhelper::ServiceManager::addSingletonContextEntries(
773 std::vector< cppu::ContextEntry_Init > * entries)
775 assert(entries != nullptr);
776 for (const auto& [rName, rImpls] : data_.singletons)
778 assert(!rImpls.empty());
779 assert(rImpls[0]);
780 SAL_INFO_IF(
781 rImpls.size() > 1, "cppuhelper",
782 "Arbitrarily choosing " << rImpls[0]->name
783 << " among multiple implementations for " << rName);
784 entries->push_back(
785 cppu::ContextEntry_Init(
786 "/singletons/" + rName,
787 css::uno::Any(
788 css::uno::Reference<css::lang::XSingleComponentFactory>(
789 new SingletonFactory(this, rImpls[0]))),
790 true));
794 void cppuhelper::ServiceManager::loadImplementation(
795 css::uno::Reference< css::uno::XComponentContext > const & context,
796 std::shared_ptr< Data::Implementation > const & implementation)
798 assert(implementation);
800 std::unique_lock g(m_aMutex);
801 if (implementation->status == Data::Implementation::STATUS_LOADED) {
802 return;
805 OUString uri;
806 try {
807 uri = cppu::bootstrap_expandUri(implementation->uri);
808 } catch (css::lang::IllegalArgumentException & e) {
809 throw css::uno::DeploymentException(
810 "Cannot expand URI" + implementation->uri + ": " + e.Message,
811 static_cast< cppu::OWeakObject * >(this));
813 cppuhelper::WrapperConstructorFn ctor;
814 css::uno::Reference< css::uno::XInterface > f0;
815 // Special handling of SharedLibrary loader, with support for environment,
816 // constructor, and prefix arguments:
817 if (!implementation->alienContext.is()
818 && implementation->loader == "com.sun.star.loader.SharedLibrary")
820 cppuhelper::detail::loadSharedLibComponentFactory(
821 uri, implementation->environment,
822 implementation->prefix, implementation->name,
823 implementation->constructorName, this, &ctor, &f0);
824 if (ctor) {
825 assert(!implementation->environment.isEmpty());
827 } else {
828 SAL_WARN_IF(
829 !implementation->environment.isEmpty(), "cppuhelper",
830 "Loader " << implementation->loader
831 << " and non-empty environment "
832 << implementation->environment);
833 SAL_WARN_IF(
834 !implementation->prefix.isEmpty(), "cppuhelper",
835 "Loader " << implementation->loader
836 << " and non-empty constructor "
837 << implementation->constructorName);
838 SAL_WARN_IF(
839 !implementation->prefix.isEmpty(), "cppuhelper",
840 "Loader " << implementation->loader
841 << " and non-empty prefix " << implementation->prefix);
842 css::uno::Reference< css::uno::XComponentContext > ctxt;
843 css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
844 if (implementation->alienContext.is()) {
845 ctxt = implementation->alienContext;
846 smgr.set(ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
847 } else {
848 assert(context.is());
849 ctxt = context;
850 smgr = this;
852 css::uno::Reference< css::loader::XImplementationLoader > loader(
853 smgr->createInstanceWithContext(implementation->loader, ctxt),
854 css::uno::UNO_QUERY_THROW);
855 f0 = loader->activate(
856 implementation->name, OUString(), uri,
857 css::uno::Reference< css::registry::XRegistryKey >());
859 css::uno::Reference<css::lang::XSingleComponentFactory> f1;
860 css::uno::Reference<css::lang::XSingleServiceFactory> f2;
861 if (!ctor) {
862 f1.set(f0, css::uno::UNO_QUERY);
863 if (!f1.is()) {
864 f2.set(f0, css::uno::UNO_QUERY);
865 if (!f2.is()) {
866 throw css::uno::DeploymentException(
867 ("Implementation " + implementation->name
868 + " does not provide a constructor or factory"),
869 static_cast< cppu::OWeakObject * >(this));
873 //TODO: There is a race here, as the relevant service factory can be removed
874 // while the mutex is unlocked and loading can thus fail, as the entity from
875 // which to load can disappear once the service factory is removed.
876 std::unique_lock g(m_aMutex);
877 if (!(m_bDisposed
878 || implementation->status == Data::Implementation::STATUS_LOADED))
880 implementation->status = Data::Implementation::STATUS_LOADED;
881 implementation->constructorFn = ctor;
882 implementation->factory1 = f1;
883 implementation->factory2 = f2;
887 void cppuhelper::ServiceManager::disposing(std::unique_lock<std::mutex>& rGuard) {
888 std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
889 std::vector< css::uno::Reference< css::lang::XComponent > > comps;
890 Data clear;
892 for (const auto& rEntry : data_.namedImplementations)
894 assert(rEntry.second);
895 if (rEntry.second->shallDispose()) {
896 std::unique_lock g2(rEntry.second->mutex);
897 if (rEntry.second->disposeInstance.is()) {
898 sngls.push_back(rEntry.second->disposeInstance);
902 for (const auto& rEntry : data_.dynamicImplementations)
904 assert(rEntry.second);
905 if (rEntry.second->shallDispose()) {
906 std::unique_lock g2(rEntry.second->mutex);
907 if (rEntry.second->disposeInstance.is()) {
908 sngls.push_back(rEntry.second->disposeInstance);
911 if (rEntry.second->component.is()) {
912 comps.push_back(rEntry.second->component);
915 data_.namedImplementations.swap(clear.namedImplementations);
916 data_.dynamicImplementations.swap(clear.dynamicImplementations);
917 data_.services.swap(clear.services);
918 data_.singletons.swap(clear.singletons);
920 rGuard.unlock();
921 for (const auto& rxSngl : sngls)
923 try {
924 rxSngl->dispose();
925 } catch (css::uno::RuntimeException & e) {
926 SAL_WARN("cppuhelper", "Ignoring " << e << " while disposing singleton");
929 for (const auto& rxComp : comps)
931 removeEventListenerFromComponent(rxComp);
933 rGuard.lock();
936 void cppuhelper::ServiceManager::initialize(
937 css::uno::Sequence<css::uno::Any> const & aArguments)
939 OUString arg;
940 if (aArguments.getLength() != 1 || !(aArguments[0] >>= arg)
941 || arg != "preload")
943 throw css::lang::IllegalArgumentException(
944 "invalid ServiceManager::initialize argument",
945 css::uno::Reference<css::uno::XInterface>(), 0);
947 preloadImplementations();
950 OUString cppuhelper::ServiceManager::getImplementationName()
952 return
953 "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager";
956 sal_Bool cppuhelper::ServiceManager::supportsService(
957 OUString const & ServiceName)
959 return cppu::supportsService(this, ServiceName);
962 css::uno::Sequence< OUString >
963 cppuhelper::ServiceManager::getSupportedServiceNames()
965 return { "com.sun.star.lang.MultiServiceFactory", "com.sun.star.lang.ServiceManager" };
968 css::uno::Reference< css::uno::XInterface >
969 cppuhelper::ServiceManager::createInstance(
970 OUString const & aServiceSpecifier)
972 assert(context_.is());
973 return createInstanceWithContext(aServiceSpecifier, context_);
976 css::uno::Reference< css::uno::XInterface >
977 cppuhelper::ServiceManager::createInstanceWithArguments(
978 OUString const & ServiceSpecifier,
979 css::uno::Sequence< css::uno::Any > const & Arguments)
981 assert(context_.is());
982 return createInstanceWithArgumentsAndContext(
983 ServiceSpecifier, Arguments, context_);
986 css::uno::Sequence< OUString >
987 cppuhelper::ServiceManager::getAvailableServiceNames()
989 std::unique_lock g(m_aMutex);
990 if (m_bDisposed) {
991 return css::uno::Sequence< OUString >();
993 if (data_.services.size() > o3tl::make_unsigned(SAL_MAX_INT32)) {
994 throw css::uno::RuntimeException(
995 "getAvailableServiceNames: too many services",
996 static_cast< cppu::OWeakObject * >(this));
998 return comphelper::mapKeysToSequence(data_.services);
1001 css::uno::Reference< css::uno::XInterface >
1002 cppuhelper::ServiceManager::createInstanceWithContext(
1003 OUString const & aServiceSpecifier,
1004 css::uno::Reference< css::uno::XComponentContext > const & Context)
1006 std::shared_ptr< Data::Implementation > impl(
1007 findServiceImplementation(Context, aServiceSpecifier));
1008 return impl == nullptr ? css::uno::Reference<css::uno::XInterface>()
1009 : impl->createInstance(Context, false);
1012 css::uno::Reference< css::uno::XInterface >
1013 cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
1014 OUString const & ServiceSpecifier,
1015 css::uno::Sequence< css::uno::Any > const & Arguments,
1016 css::uno::Reference< css::uno::XComponentContext > const & Context)
1018 std::shared_ptr< Data::Implementation > impl(
1019 findServiceImplementation(Context, ServiceSpecifier));
1020 return impl == nullptr ? css::uno::Reference<css::uno::XInterface>()
1021 : impl->createInstanceWithArguments(Context, false, Arguments);
1024 css::uno::Type cppuhelper::ServiceManager::getElementType()
1026 return css::uno::Type();
1029 sal_Bool cppuhelper::ServiceManager::hasElements()
1031 std::unique_lock g(m_aMutex);
1032 return
1033 !(data_.namedImplementations.empty()
1034 && data_.dynamicImplementations.empty());
1037 css::uno::Reference< css::container::XEnumeration >
1038 cppuhelper::ServiceManager::createEnumeration()
1040 throw css::uno::RuntimeException(
1041 "ServiceManager createEnumeration: method not supported",
1042 static_cast< cppu::OWeakObject * >(this));
1045 sal_Bool cppuhelper::ServiceManager::has(css::uno::Any const &)
1047 throw css::uno::RuntimeException(
1048 "ServiceManager has: method not supported",
1049 static_cast< cppu::OWeakObject * >(this));
1052 void cppuhelper::ServiceManager::insert(css::uno::Any const & aElement)
1054 css::uno::Sequence< css::beans::NamedValue > args;
1055 if (aElement >>= args) {
1056 std::vector< OUString > uris;
1057 css::uno::Reference< css::uno::XComponentContext > alienContext;
1058 for (const auto & arg : args) {
1059 if (arg.Name == "uri") {
1060 OUString uri;
1061 if (!(arg.Value >>= uri)) {
1062 throw css::lang::IllegalArgumentException(
1063 "Bad uri argument",
1064 static_cast< cppu::OWeakObject * >(this), 0);
1066 uris.push_back(uri);
1067 } else if (arg.Name == "component-context") {
1068 if (alienContext.is()) {
1069 throw css::lang::IllegalArgumentException(
1070 "Multiple component-context arguments",
1071 static_cast< cppu::OWeakObject * >(this), 0);
1073 if (!(arg.Value >>= alienContext) || !alienContext.is()) {
1074 throw css::lang::IllegalArgumentException(
1075 "Bad component-context argument",
1076 static_cast< cppu::OWeakObject * >(this), 0);
1078 } else {
1079 throw css::lang::IllegalArgumentException(
1080 "Bad argument " + arg.Name,
1081 static_cast< cppu::OWeakObject * >(this), 0);
1084 insertRdbFiles(uris, alienContext);
1085 return;
1087 css::uno::Reference< css::lang::XServiceInfo > info;
1088 if ((aElement >>= info) && info.is()) {
1089 insertLegacyFactory(info);
1090 return;
1093 throw css::lang::IllegalArgumentException(
1094 "Bad insert element", static_cast< cppu::OWeakObject * >(this), 0);
1097 void cppuhelper::ServiceManager::remove(css::uno::Any const & aElement)
1099 css::uno::Sequence< css::beans::NamedValue > args;
1100 if (aElement >>= args) {
1101 std::vector< OUString > uris;
1102 for (const auto & i : args) {
1103 if (i.Name != "uri") {
1104 throw css::lang::IllegalArgumentException(
1105 "Bad argument " + i.Name,
1106 static_cast< cppu::OWeakObject * >(this), 0);
1108 OUString uri;
1109 if (!(i.Value >>= uri)) {
1110 throw css::lang::IllegalArgumentException(
1111 "Bad uri argument",
1112 static_cast< cppu::OWeakObject * >(this), 0);
1114 uris.push_back(uri);
1116 removeRdbFiles(uris);
1117 return;
1119 css::uno::Reference< css::lang::XServiceInfo > info;
1120 if ((aElement >>= info) && info.is()) {
1121 if (!removeLegacyFactory(info, true)) {
1122 throw css::container::NoSuchElementException(
1123 "Remove non-inserted factory object",
1124 static_cast< cppu::OWeakObject * >(this));
1126 return;
1128 OUString impl;
1129 if (aElement >>= impl) {
1130 // For live-removal of extensions:
1131 removeImplementation(impl);
1132 return;
1134 throw css::lang::IllegalArgumentException(
1135 "Bad remove element", static_cast< cppu::OWeakObject * >(this), 0);
1138 css::uno::Reference< css::container::XEnumeration >
1139 cppuhelper::ServiceManager::createContentEnumeration(
1140 OUString const & aServiceName)
1142 std::vector< std::shared_ptr< Data::Implementation > > impls;
1144 std::unique_lock g(m_aMutex);
1145 Data::ImplementationMap::const_iterator i(
1146 data_.services.find(aServiceName));
1147 if (i != data_.services.end()) {
1148 impls = i->second;
1151 std::vector< css::uno::Any > factories;
1152 for (const auto& rxImpl : impls)
1154 Data::Implementation * impl = rxImpl.get();
1155 assert(impl != nullptr);
1157 std::unique_lock g(m_aMutex);
1158 if (m_bDisposed) {
1159 factories.clear();
1160 break;
1162 if (impl->status == Data::Implementation::STATUS_NEW) {
1163 // Postpone actual implementation instantiation as long as
1164 // possible (so that e.g. opening LO's "Tools - Macros" menu
1165 // does not try to instantiate a JVM, which can lead to a
1166 // synchronous error dialog when no JVM is specified, and
1167 // showing the dialog while hovering over a menu can cause
1168 // trouble):
1169 impl->factory1 = new ImplementationWrapper(this, rxImpl);
1170 impl->status = Data::Implementation::STATUS_WRAPPER;
1172 if (impl->constructorFn != nullptr && !impl->factory1.is()) {
1173 impl->factory1 = new ImplementationWrapper(this, rxImpl);
1176 if (impl->factory1.is()) {
1177 factories.push_back(css::uno::Any(impl->factory1));
1178 } else {
1179 assert(impl->factory2.is());
1180 factories.push_back(css::uno::Any(impl->factory2));
1183 return new ContentEnumeration(std::move(factories));
1186 css::uno::Reference< css::beans::XPropertySetInfo >
1187 cppuhelper::ServiceManager::getPropertySetInfo()
1189 return this;
1192 void cppuhelper::ServiceManager::setPropertyValue(
1193 OUString const & aPropertyName, css::uno::Any const &)
1195 if (aPropertyName == "DefaultContext") {
1196 throw css::beans::PropertyVetoException(
1197 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1198 } else {
1199 throw css::beans::UnknownPropertyException(
1200 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1204 css::uno::Any cppuhelper::ServiceManager::getPropertyValue(
1205 OUString const & PropertyName)
1207 if (PropertyName != "DefaultContext") {
1208 throw css::beans::UnknownPropertyException(
1209 PropertyName, static_cast< cppu::OWeakObject * >(this));
1211 assert(context_.is());
1212 return css::uno::Any(context_);
1215 void cppuhelper::ServiceManager::addPropertyChangeListener(
1216 OUString const & aPropertyName,
1217 css::uno::Reference< css::beans::XPropertyChangeListener > const &
1218 xListener)
1220 if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1221 throw css::beans::UnknownPropertyException(
1222 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1224 // DefaultContext does not change, so just treat it as an event listener:
1225 return addEventListener(xListener);
1228 void cppuhelper::ServiceManager::removePropertyChangeListener(
1229 OUString const & aPropertyName,
1230 css::uno::Reference< css::beans::XPropertyChangeListener > const &
1231 aListener)
1233 if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1234 throw css::beans::UnknownPropertyException(
1235 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1237 // DefaultContext does not change, so just treat it as an event listener:
1238 return removeEventListener(aListener);
1241 void cppuhelper::ServiceManager::addVetoableChangeListener(
1242 OUString const & PropertyName,
1243 css::uno::Reference< css::beans::XVetoableChangeListener > const &
1244 aListener)
1246 if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1247 throw css::beans::UnknownPropertyException(
1248 PropertyName, static_cast< cppu::OWeakObject * >(this));
1250 // DefaultContext does not change, so just treat it as an event listener:
1251 return addEventListener(aListener);
1254 void cppuhelper::ServiceManager::removeVetoableChangeListener(
1255 OUString const & PropertyName,
1256 css::uno::Reference< css::beans::XVetoableChangeListener > const &
1257 aListener)
1259 if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1260 throw css::beans::UnknownPropertyException(
1261 PropertyName, static_cast< cppu::OWeakObject * >(this));
1263 // DefaultContext does not change, so just treat it as an event listener:
1264 return removeEventListener(aListener);
1267 css::uno::Sequence< css::beans::Property >
1268 cppuhelper::ServiceManager::getProperties() {
1269 return { getDefaultContextProperty() };
1272 css::beans::Property cppuhelper::ServiceManager::getPropertyByName(
1273 OUString const & aName)
1275 if (aName != "DefaultContext") {
1276 throw css::beans::UnknownPropertyException(
1277 aName, static_cast< cppu::OWeakObject * >(this));
1279 return getDefaultContextProperty();
1282 sal_Bool cppuhelper::ServiceManager::hasPropertyByName(
1283 OUString const & Name)
1285 return Name == "DefaultContext";
1288 cppuhelper::ServiceManager::~ServiceManager() {}
1290 void cppuhelper::ServiceManager::disposing(
1291 css::lang::EventObject const & Source)
1293 removeLegacyFactory(
1294 css::uno::Reference< css::lang::XServiceInfo >(
1295 Source.Source, css::uno::UNO_QUERY_THROW),
1296 false);
1299 void cppuhelper::ServiceManager::removeEventListenerFromComponent(
1300 css::uno::Reference< css::lang::XComponent > const & component)
1302 assert(component.is());
1303 try {
1304 component->removeEventListener(this);
1305 } catch (css::uno::RuntimeException & e) {
1306 SAL_INFO(
1307 "cppuhelper",
1308 "Ignored removeEventListener RuntimeException " + e.Message);
1312 void cppuhelper::ServiceManager::init(std::u16string_view rdbUris) {
1313 for (sal_Int32 i = 0; i != -1;) {
1314 std::u16string_view uri(o3tl::getToken(rdbUris, 0, ' ', i));
1315 if (uri.empty()) {
1316 continue;
1318 bool optional;
1319 bool directory;
1320 cppu::decodeRdbUri(&uri, &optional, &directory);
1321 if (directory) {
1322 readRdbDirectory(uri, optional);
1323 } else {
1324 readRdbFile(OUString(uri), optional);
1329 void cppuhelper::ServiceManager::readRdbDirectory(
1330 std::u16string_view uri, bool optional)
1332 osl::Directory dir = OUString(uri);
1333 switch (dir.open()) {
1334 case osl::FileBase::E_None:
1335 break;
1336 case osl::FileBase::E_NOENT:
1337 if (optional) {
1338 SAL_INFO("cppuhelper", "Ignored optional " << OUString(uri));
1339 return;
1341 [[fallthrough]];
1342 default:
1343 throw css::uno::DeploymentException(
1344 OUString::Concat("Cannot open directory ") + uri,
1345 static_cast< cppu::OWeakObject * >(this));
1347 for (;;) {
1348 OUString url;
1349 if (!cppu::nextDirectoryItem(dir, &url)) {
1350 break;
1352 readRdbFile(url, false);
1356 void cppuhelper::ServiceManager::readRdbFile(
1357 OUString const & uri, bool optional)
1359 try {
1360 Parser(
1361 uri, css::uno::Reference< css::uno::XComponentContext >(), &data_);
1362 } catch (css::container::NoSuchElementException &) {
1363 if (!optional) {
1364 throw css::uno::DeploymentException(
1365 uri + ": no such file",
1366 static_cast< cppu::OWeakObject * >(this));
1368 SAL_INFO("cppuhelper", "Ignored optional " << uri);
1370 #if !ENABLE_FUZZERS
1371 catch (css::registry::InvalidRegistryException & e) {
1372 if (!readLegacyRdbFile(uri)) {
1373 throw css::uno::DeploymentException(
1374 "InvalidRegistryException: " + e.Message,
1375 static_cast< cppu::OWeakObject * >(this));
1377 } catch (css::uno::RuntimeException &) {
1378 if (!readLegacyRdbFile(uri)) {
1379 throw;
1382 #endif
1385 #if !ENABLE_FUZZERS
1386 bool cppuhelper::ServiceManager::readLegacyRdbFile(OUString const & uri) {
1387 Registry reg;
1388 switch (reg.open(uri, RegAccessMode::READONLY)) {
1389 case RegError::NO_ERROR:
1390 break;
1391 case RegError::REGISTRY_NOT_EXISTS:
1392 case RegError::INVALID_REGISTRY:
1394 // Ignore empty rdb files (which are at least seen by subordinate
1395 // uno processes during extension registration; Registry::open can
1396 // fail on them if mmap(2) returns EINVAL for a zero length):
1397 osl::DirectoryItem item;
1398 if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
1399 osl::FileStatus status(osl_FileStatus_Mask_FileSize);
1400 if (item.getFileStatus(status) == osl::FileBase::E_None
1401 && status.getFileSize() == 0)
1403 return true;
1407 [[fallthrough]];
1408 default:
1409 return false;
1411 RegistryKey rootKey;
1412 if (reg.openRootKey(rootKey) != RegError::NO_ERROR) {
1413 throw css::uno::DeploymentException(
1414 "Failure reading legacy rdb file " + uri,
1415 static_cast< cppu::OWeakObject * >(this));
1417 RegistryKeyArray impls;
1418 switch (rootKey.openSubKeys("IMPLEMENTATIONS", impls)) {
1419 case RegError::NO_ERROR:
1420 break;
1421 case RegError::KEY_NOT_EXISTS:
1422 return true;
1423 default:
1424 throw css::uno::DeploymentException(
1425 "Failure reading legacy rdb file " + uri,
1426 static_cast< cppu::OWeakObject * >(this));
1428 for (sal_uInt32 i = 0; i != impls.getLength(); ++i) {
1429 RegistryKey implKey(impls.getElement(i));
1430 assert(implKey.getName().match("/IMPLEMENTATIONS/"));
1431 OUString name(
1432 implKey.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1433 std::shared_ptr< Data::Implementation > impl =
1434 std::make_shared<Data::Implementation>(
1435 name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"),
1436 readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "", "", false,
1437 css::uno::Reference< css::uno::XComponentContext >(), uri);
1438 if (!data_.namedImplementations.emplace(name, impl).second)
1440 throw css::registry::InvalidRegistryException(
1441 uri + ": duplicate <implementation name=\"" + name + "\">");
1443 readLegacyRdbStrings(
1444 uri, implKey, "UNO/SERVICES", &impl->services);
1445 for (const auto& rService : impl->services)
1447 data_.services[rService].push_back(impl);
1449 readLegacyRdbStrings(
1450 uri, implKey, "UNO/SINGLETONS", &impl->singletons);
1451 for (const auto& rSingleton : impl->singletons)
1453 data_.singletons[rSingleton].push_back(impl);
1456 return true;
1459 OUString cppuhelper::ServiceManager::readLegacyRdbString(
1460 std::u16string_view uri, RegistryKey & key, OUString const & path)
1462 RegistryKey subkey;
1463 RegValueType t;
1464 sal_uInt32 s(0);
1465 if (key.openKey(path, subkey) != RegError::NO_ERROR
1466 || subkey.getValueInfo(OUString(), &t, &s) != RegError::NO_ERROR
1467 || t != RegValueType::STRING
1468 || s == 0 || s > o3tl::make_unsigned(SAL_MAX_INT32))
1470 throw css::uno::DeploymentException(
1471 OUString::Concat("Failure reading legacy rdb file ") + uri,
1472 static_cast< cppu::OWeakObject * >(this));
1474 OUString val;
1475 std::vector< char > v(s); // assuming sal_uInt32 fits into vector::size_type
1476 if (subkey.getValue(OUString(), v.data()) != RegError::NO_ERROR
1477 || v.back() != '\0'
1478 || !rtl_convertStringToUString(
1479 &val.pData, v.data(), static_cast< sal_Int32 >(s - 1),
1480 RTL_TEXTENCODING_UTF8,
1481 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1482 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1483 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
1485 throw css::uno::DeploymentException(
1486 OUString::Concat("Failure reading legacy rdb file ") + uri,
1487 static_cast< cppu::OWeakObject * >(this));
1489 return val;
1492 void cppuhelper::ServiceManager::readLegacyRdbStrings(
1493 std::u16string_view uri, RegistryKey & key, OUString const & path,
1494 std::vector< OUString > * strings)
1496 assert(strings != nullptr);
1497 RegistryKey subkey;
1498 switch (key.openKey(path, subkey)) {
1499 case RegError::NO_ERROR:
1500 break;
1501 case RegError::KEY_NOT_EXISTS:
1502 return;
1503 default:
1504 throw css::uno::DeploymentException(
1505 OUString::Concat("Failure reading legacy rdb file ") + uri,
1506 static_cast< cppu::OWeakObject * >(this));
1508 OUString prefix(subkey.getName() + "/");
1509 RegistryKeyNames names;
1510 if (subkey.getKeyNames(OUString(), names) != RegError::NO_ERROR) {
1511 throw css::uno::DeploymentException(
1512 OUString::Concat("Failure reading legacy rdb file ") + uri,
1513 static_cast< cppu::OWeakObject * >(this));
1515 for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
1516 assert(names.getElement(i).match(prefix));
1517 strings->push_back(names.getElement(i).copy(prefix.getLength()));
1520 #endif
1522 void cppuhelper::ServiceManager::insertRdbFiles(
1523 std::vector< OUString > const & uris,
1524 css::uno::Reference< css::uno::XComponentContext > const & alienContext)
1526 Data extra;
1527 for (const auto& rUri : uris)
1529 try {
1530 Parser(rUri, alienContext, &extra);
1531 } catch (css::container::NoSuchElementException &) {
1532 throw css::lang::IllegalArgumentException(
1533 rUri + ": no such file", static_cast< cppu::OWeakObject * >(this),
1535 } catch (css::registry::InvalidRegistryException & e) {
1536 throw css::lang::IllegalArgumentException(
1537 "InvalidRegistryException: " + e.Message,
1538 static_cast< cppu::OWeakObject * >(this), 0);
1541 insertExtraData(extra);
1544 void cppuhelper::ServiceManager::insertLegacyFactory(
1545 css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo)
1547 assert(factoryInfo.is());
1548 OUString name(factoryInfo->getImplementationName());
1549 css::uno::Reference< css::lang::XSingleComponentFactory > f1(
1550 factoryInfo, css::uno::UNO_QUERY);
1551 css::uno::Reference< css::lang::XSingleServiceFactory > f2;
1552 if (!f1.is()) {
1553 f2.set(factoryInfo, css::uno::UNO_QUERY);
1554 if (!f2.is()) {
1555 throw css::lang::IllegalArgumentException(
1556 ("Bad XServiceInfo argument implements neither"
1557 " XSingleComponentFactory nor XSingleServiceFactory"),
1558 static_cast< cppu::OWeakObject * >(this), 0);
1561 css::uno::Reference< css::lang::XComponent > comp(
1562 factoryInfo, css::uno::UNO_QUERY);
1563 std::shared_ptr< Data::Implementation > impl =
1564 std::make_shared<Data::Implementation>(name, f1, f2, comp);
1565 Data extra;
1566 if (!name.isEmpty()) {
1567 extra.namedImplementations.emplace(name, impl);
1569 extra.dynamicImplementations.emplace(factoryInfo, impl);
1570 const css::uno::Sequence< OUString > services(
1571 factoryInfo->getSupportedServiceNames());
1572 for (const auto & i : services) {
1573 impl->services.push_back(i);
1574 extra.services[i].push_back(impl);
1576 if (insertExtraData(extra) && comp.is()) {
1577 comp->addEventListener(this);
1581 bool cppuhelper::ServiceManager::insertExtraData(Data const & extra) {
1583 std::unique_lock g(m_aMutex);
1584 if (m_bDisposed) {
1585 return false;
1587 auto i = std::find_if(extra.namedImplementations.begin(), extra.namedImplementations.end(),
1588 [this](const Data::NamedImplementations::value_type& rEntry) {
1589 return data_.namedImplementations.find(rEntry.first) != data_.namedImplementations.end(); });
1590 if (i != extra.namedImplementations.end())
1592 throw css::lang::IllegalArgumentException(
1593 "Insert duplicate implementation name " + i->first,
1594 static_cast< cppu::OWeakObject * >(this), 0);
1596 bool bDuplicate = std::any_of(extra.dynamicImplementations.begin(), extra.dynamicImplementations.end(),
1597 [this](const Data::DynamicImplementations::value_type& rEntry) {
1598 return data_.dynamicImplementations.find(rEntry.first) != data_.dynamicImplementations.end(); });
1599 if (bDuplicate)
1601 throw css::lang::IllegalArgumentException(
1602 "Insert duplicate factory object",
1603 static_cast< cppu::OWeakObject * >(this), 0);
1605 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1606 data_.namedImplementations.insert(
1607 extra.namedImplementations.begin(),
1608 extra.namedImplementations.end());
1609 data_.dynamicImplementations.insert(
1610 extra.dynamicImplementations.begin(),
1611 extra.dynamicImplementations.end());
1612 insertImplementationMap(&data_.services, extra.services);
1613 insertImplementationMap(&data_.singletons, extra.singletons);
1615 //TODO: Updating the component context singleton data should be part of the
1616 // atomic service manager update:
1617 if (extra.singletons.empty())
1618 return true;
1620 assert(context_.is());
1621 css::uno::Reference< css::container::XNameContainer > cont(
1622 context_, css::uno::UNO_QUERY_THROW);
1623 for (const auto& [rName, rImpls] : extra.singletons)
1625 OUString name("/singletons/" + rName);
1626 //TODO: Update should be atomic:
1627 try {
1628 cont->removeByName(name + "/arguments");
1629 } catch (const css::container::NoSuchElementException &) {}
1630 assert(!rImpls.empty());
1631 assert(rImpls[0]);
1632 SAL_INFO_IF(
1633 rImpls.size() > 1, "cppuhelper",
1634 "Arbitrarily choosing " << rImpls[0]->name
1635 << " among multiple implementations for singleton "
1636 << rName);
1637 try {
1638 cont->insertByName(
1639 name + "/service", css::uno::Any(rImpls[0]->name));
1640 } catch (css::container::ElementExistException &) {
1641 cont->replaceByName(
1642 name + "/service", css::uno::Any(rImpls[0]->name));
1644 try {
1645 cont->insertByName(name, css::uno::Any());
1646 } catch (css::container::ElementExistException &) {
1647 SAL_INFO("cppuhelper", "Overwriting singleton " << rName);
1648 cont->replaceByName(name, css::uno::Any());
1651 return true;
1654 void cppuhelper::ServiceManager::removeRdbFiles(
1655 std::vector< OUString > const & uris)
1657 // The underlying data structures make this function somewhat inefficient,
1658 // but the assumption is that it is rarely called (and that if it is called,
1659 // it is called with a uris vector of size one):
1660 std::vector< std::shared_ptr< Data::Implementation > > clear;
1662 std::unique_lock g(m_aMutex);
1663 for (const auto& rUri : uris)
1665 for (Data::NamedImplementations::iterator j(
1666 data_.namedImplementations.begin());
1667 j != data_.namedImplementations.end();)
1669 assert(j->second);
1670 if (j->second->rdbFile == rUri) {
1671 clear.push_back(j->second);
1672 //TODO: The below leaves data_ in an inconsistent state upon
1673 // exceptions:
1674 removeFromImplementationMap(
1675 &data_.services, j->second->services, j->second);
1676 removeFromImplementationMap(
1677 &data_.singletons, j->second->singletons,
1678 j->second);
1679 j = data_.namedImplementations.erase(j);
1680 } else {
1681 ++j;
1686 //TODO: Update the component context singleton data
1689 bool cppuhelper::ServiceManager::removeLegacyFactory(
1690 css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
1691 bool removeListener)
1693 assert(factoryInfo.is());
1694 std::shared_ptr< Data::Implementation > clear;
1695 css::uno::Reference< css::lang::XComponent > comp;
1697 std::unique_lock g(m_aMutex);
1698 Data::DynamicImplementations::iterator i(
1699 data_.dynamicImplementations.find(factoryInfo));
1700 if (i == data_.dynamicImplementations.end()) {
1701 return m_bDisposed;
1703 assert(i->second);
1704 clear = i->second;
1705 if (removeListener) {
1706 comp = i->second->component;
1708 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1709 removeFromImplementationMap(
1710 &data_.services, i->second->services, i->second);
1711 removeFromImplementationMap(
1712 &data_.singletons, i->second->singletons, i->second);
1713 if (!i->second->name.isEmpty()) {
1714 data_.namedImplementations.erase(i->second->name);
1716 data_.dynamicImplementations.erase(i);
1718 if (comp.is()) {
1719 removeEventListenerFromComponent(comp);
1721 return true;
1724 void cppuhelper::ServiceManager::removeImplementation(const OUString & name) {
1725 // The underlying data structures make this function somewhat inefficient,
1726 // but the assumption is that it is rarely called:
1727 std::shared_ptr< Data::Implementation > clear;
1729 std::unique_lock g(m_aMutex);
1730 if (m_bDisposed) {
1731 return;
1733 Data::NamedImplementations::iterator i(
1734 data_.namedImplementations.find(name));
1735 if (i == data_.namedImplementations.end()) {
1736 throw css::container::NoSuchElementException(
1737 "Remove non-inserted implementation " + name,
1738 static_cast< cppu::OWeakObject * >(this));
1740 assert(i->second);
1741 clear = i->second;
1742 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1743 removeFromImplementationMap(
1744 &data_.services, i->second->services, i->second);
1745 removeFromImplementationMap(
1746 &data_.singletons, i->second->singletons, i->second);
1747 auto j = std::find_if(data_.dynamicImplementations.begin(), data_.dynamicImplementations.end(),
1748 [&i](const Data::DynamicImplementations::value_type& rEntry) { return rEntry.second == i->second; });
1749 if (j != data_.dynamicImplementations.end())
1750 data_.dynamicImplementations.erase(j);
1751 data_.namedImplementations.erase(i);
1755 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
1756 cppuhelper::ServiceManager::findServiceImplementation(
1757 css::uno::Reference< css::uno::XComponentContext > const & context,
1758 OUString const & specifier)
1760 std::shared_ptr< Data::Implementation > impl;
1761 bool loaded;
1763 std::unique_lock g(m_aMutex);
1764 Data::ImplementationMap::const_iterator i(
1765 data_.services.find(specifier));
1766 if (i == data_.services.end()) {
1767 Data::NamedImplementations::const_iterator j(
1768 data_.namedImplementations.find(specifier));
1769 if (j == data_.namedImplementations.end()) {
1770 SAL_INFO("cppuhelper", "No implementation for " << specifier);
1771 return std::shared_ptr< Data::Implementation >();
1773 impl = j->second;
1774 } else {
1775 assert(!i->second.empty());
1776 SAL_INFO_IF(
1777 i->second.size() > 1, "cppuhelper",
1778 "Arbitrarily choosing " << i->second[0]->name
1779 << " among multiple implementations for " << i->first);
1780 impl = i->second[0];
1782 assert(impl);
1783 loaded = impl->status == Data::Implementation::STATUS_LOADED;
1785 if (!loaded) {
1786 loadImplementation(context, impl);
1788 return impl;
1791 /// Make a simpler unique name for preload / progress reporting.
1792 #ifndef DISABLE_DYNLOADING
1793 static OUString simplifyModule(std::u16string_view uri)
1795 sal_Int32 nIdx;
1796 OUStringBuffer edit(uri);
1797 if ((nIdx = edit.lastIndexOf('/')) > 0)
1798 edit.remove(0,nIdx+1);
1799 if ((nIdx = edit.lastIndexOf(':')) > 0)
1800 edit.remove(0,nIdx+1);
1801 if ((nIdx = edit.lastIndexOf("lo.so")) > 0)
1802 edit.truncate(nIdx);
1803 if ((nIdx = edit.lastIndexOf(".3")) > 0)
1804 edit.truncate(nIdx);
1805 if ((nIdx = edit.lastIndexOf("gcc3.so")) > 0)
1806 edit.truncate(nIdx);
1807 if ((nIdx = edit.lastIndexOf(".so")) > 0)
1808 edit.truncate(nIdx);
1809 if ((nIdx = edit.lastIndexOf("_uno")) > 0)
1810 edit.truncate(nIdx);
1811 if ((nIdx = edit.lastIndexOf(".jar")) > 0)
1812 edit.truncate(nIdx);
1813 if (edit.indexOf("lib") == 0)
1814 edit.remove(0,3);
1815 return edit.makeStringAndClear();
1817 #endif
1819 /// Used only by LibreOfficeKit when used by Online to pre-initialize
1820 void cppuhelper::ServiceManager::preloadImplementations() {
1821 #ifdef DISABLE_DYNLOADING
1822 abort();
1823 #else
1824 OUString aUri;
1825 std::unique_lock g(m_aMutex);
1826 css::uno::Environment aSourceEnv(css::uno::Environment::getCurrent());
1828 std::cerr << "preload:";
1829 std::vector<OUString> aReported;
1830 std::vector<OUString> aDisabled;
1831 OUStringBuffer aDisabledMsg;
1832 OUStringBuffer aMissingMsg;
1834 /// Allow external callers & testers to disable certain components
1835 const char *pDisable = getenv("UNODISABLELIBRARY");
1836 if (pDisable)
1838 OUString aDisable(pDisable, strlen(pDisable), RTL_TEXTENCODING_UTF8);
1839 for (sal_Int32 i = 0; i >= 0; )
1841 OUString tok( aDisable.getToken(0, ' ', i) );
1842 tok = tok.trim();
1843 if (!tok.isEmpty())
1844 aDisabled.push_back(tok);
1848 // loop all implementations
1849 for (const auto& rEntry : data_.namedImplementations)
1851 if (rEntry.second->loader != "com.sun.star.loader.SharedLibrary" ||
1852 rEntry.second->status == Data::Implementation::STATUS_LOADED)
1853 continue;
1855 OUString simplified;
1858 const OUString &aLibrary = rEntry.second->uri;
1860 if (aLibrary.isEmpty())
1861 continue;
1863 simplified = simplifyModule(aLibrary);
1865 bool bDisabled =
1866 std::find(aDisabled.begin(), aDisabled.end(), simplified) != aDisabled.end();
1868 if (std::find(aReported.begin(), aReported.end(), aLibrary) == aReported.end())
1870 if (bDisabled)
1872 aDisabledMsg.append(simplified + " ");
1874 else
1876 std::cerr << " " << simplified;
1877 std::cerr.flush();
1879 aReported.push_back(aLibrary);
1882 if (bDisabled)
1883 continue;
1885 // expand absolute URI implementation component library
1886 aUri = cppu::bootstrap_expandUri(aLibrary);
1888 catch (css::lang::IllegalArgumentException& aError)
1890 throw css::uno::DeploymentException(
1891 "Cannot expand URI" + rEntry.second->uri + ": " + aError.Message,
1892 static_cast< cppu::OWeakObject * >(this));
1895 // load component library
1896 osl::Module aModule(aUri, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL);
1898 if (!aModule.is())
1900 aMissingMsg.append(simplified + " ");
1903 if (aModule.is() &&
1904 !rEntry.second->environment.isEmpty())
1906 oslGenericFunction fpFactory;
1907 css::uno::Environment aTargetEnv;
1908 css::uno::Reference<css::uno::XInterface> xFactory;
1910 if(rEntry.second->constructorName.isEmpty())
1912 OUString aSymFactory;
1913 // expand full name component factory symbol
1914 if (rEntry.second->prefix == "direct")
1915 aSymFactory = rEntry.second->name.replace('.', '_') + "_" COMPONENT_GETFACTORY;
1916 else if (!rEntry.second->prefix.isEmpty())
1917 aSymFactory = rEntry.second->prefix + "_" COMPONENT_GETFACTORY;
1918 else
1919 aSymFactory = COMPONENT_GETFACTORY;
1921 // get function symbol component factory
1922 fpFactory = aModule.getFunctionSymbol(aSymFactory);
1923 if (fpFactory == nullptr)
1925 throw css::loader::CannotActivateFactoryException(
1926 ("no factory symbol \"" + aSymFactory + "\" in component library :" + aUri),
1927 css::uno::Reference<css::uno::XInterface>());
1930 aTargetEnv = cppuhelper::detail::getEnvironment(rEntry.second->environment, rEntry.second->name);
1931 component_getFactoryFunc fpComponentFactory = reinterpret_cast<component_getFactoryFunc>(fpFactory);
1933 if (aSourceEnv.get() == aTargetEnv.get())
1935 // invoke function component factory
1936 OString aImpl(OUStringToOString(rEntry.second->name, RTL_TEXTENCODING_ASCII_US));
1937 xFactory.set(css::uno::Reference<css::uno::XInterface>(static_cast<css::uno::XInterface *>(
1938 (*fpComponentFactory)(aImpl.getStr(), this, nullptr)), SAL_NO_ACQUIRE));
1941 else
1943 // get function symbol component factory
1944 aTargetEnv = cppuhelper::detail::getEnvironment(rEntry.second->environment, rEntry.second->name);
1945 fpFactory = (aSourceEnv.get() == aTargetEnv.get()) ?
1946 aModule.getFunctionSymbol(rEntry.second->constructorName) : nullptr;
1949 css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory;
1950 css::uno::Reference<css::lang::XSingleServiceFactory> xSSFactory;
1952 // query interface XSingleComponentFactory or XSingleServiceFactory
1953 if (xFactory.is())
1955 xSCFactory.set(xFactory, css::uno::UNO_QUERY);
1956 if (!xSCFactory.is())
1958 xSSFactory.set(xFactory, css::uno::UNO_QUERY);
1959 if (!xSSFactory.is())
1960 throw css::uno::DeploymentException(
1961 ("Implementation " + rEntry.second->name
1962 + " does not provide a constructor or factory"),
1963 static_cast< cppu::OWeakObject * >(this));
1967 if (!rEntry.second->constructorName.isEmpty() && fpFactory)
1968 rEntry.second->constructorFn = WrapperConstructorFn(reinterpret_cast<ImplementationConstructorFn *>(fpFactory));
1970 rEntry.second->factory1 = xSCFactory;
1971 rEntry.second->factory2 = xSSFactory;
1972 rEntry.second->status = Data::Implementation::STATUS_LOADED;
1976 // Some libraries use other (non-UNO) libraries requiring preinit
1977 oslGenericFunction fpPreload = aModule.getFunctionSymbol( "lok_preload_hook" );
1978 if (fpPreload)
1980 static std::vector<oslGenericFunction> aPreloaded;
1981 if (std::find(aPreloaded.begin(), aPreloaded.end(), fpPreload) == aPreloaded.end())
1983 aPreloaded.push_back(fpPreload);
1984 fpPreload();
1988 // leak aModule
1989 aModule.release();
1991 std::cerr << std::endl;
1993 if (aMissingMsg.getLength() > 0)
1995 OUString aMsg = aMissingMsg.makeStringAndClear();
1996 std::cerr << "Absent (often optional): " << aMsg << "\n";
1998 if (aDisabledMsg.getLength() > 0)
2000 OUString aMsg = aDisabledMsg.makeStringAndClear();
2001 std::cerr << "Disabled: " << aMsg << "\n";
2003 std::cerr.flush();
2005 // Various rather important uno mappings.
2006 static struct {
2007 const char *mpFrom;
2008 const char *mpTo;
2009 const char *mpPurpose;
2010 } const aMappingLoad[] = {
2011 { "gcc3", "uno", "" },
2012 { "uno", "gcc3", "" },
2015 static std::vector<css::uno::Mapping> maMaps;
2016 for (auto &it : aMappingLoad)
2018 maMaps.push_back(css::uno::Mapping(
2019 OUString::createFromAscii(it.mpFrom),
2020 OUString::createFromAscii(it.mpTo),
2021 OUString::createFromAscii(it.mpPurpose)));
2023 #endif
2026 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */