bump product version to 7.2.5.1
[LibreOffice.git] / cppuhelper / source / servicemanager.cxx
blobd7eff0b74cf6dc37bef57d43fef7bd141348a1b5
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 <vector>
17 #include <com/sun/star/beans/NamedValue.hpp>
18 #include <com/sun/star/beans/PropertyAttribute.hpp>
19 #include <com/sun/star/container/ElementExistException.hpp>
20 #include <com/sun/star/container/XEnumeration.hpp>
21 #include <com/sun/star/container/XNameContainer.hpp>
22 #include <com/sun/star/lang/XInitialization.hpp>
23 #include <com/sun/star/lang/XServiceInfo.hpp>
24 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
25 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
26 #include <com/sun/star/loader/XImplementationLoader.hpp>
27 #include <com/sun/star/registry/InvalidRegistryException.hpp>
28 #include <com/sun/star/uno/DeploymentException.hpp>
29 #include <com/sun/star/uno/Reference.hxx>
30 #include <com/sun/star/uno/XComponentContext.hpp>
31 #include <comphelper/sequence.hxx>
32 #include <cppuhelper/bootstrap.hxx>
33 #include <cppuhelper/component_context.hxx>
34 #include <cppuhelper/implbase.hxx>
35 #include <cppuhelper/supportsservice.hxx>
36 #include <cppuhelper/factory.hxx>
37 #include <o3tl/safeint.hxx>
38 #include <osl/file.hxx>
39 #include <osl/module.hxx>
40 #include <rtl/ref.hxx>
41 #include <rtl/uri.hxx>
42 #include <rtl/ustring.hxx>
43 #include <rtl/ustrbuf.hxx>
44 #include <sal/log.hxx>
45 #include <uno/environment.hxx>
46 #include <uno/mapping.hxx>
48 #include "loadsharedlibcomponentfactory.hxx"
50 #include <registry/registry.hxx>
51 #include <xmlreader/xmlreader.hxx>
53 #include "paths.hxx"
54 #include "servicemanager.hxx"
56 namespace {
58 void insertImplementationMap(
59 cppuhelper::ServiceManager::Data::ImplementationMap * destination,
60 cppuhelper::ServiceManager::Data::ImplementationMap const & source)
62 assert(destination != nullptr);
63 for (const auto& [rName, rImpls] : source)
65 std::vector<
66 std::shared_ptr<
67 cppuhelper::ServiceManager::Data::Implementation > > & impls
68 = (*destination)[rName];
69 impls.insert(impls.end(), rImpls.begin(), rImpls.end());
73 void removeFromImplementationMap(
74 cppuhelper::ServiceManager::Data::ImplementationMap * map,
75 std::vector< OUString > const & elements,
76 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
77 const & implementation)
79 // The underlying data structures make this function somewhat inefficient,
80 // but the assumption is that it is rarely called:
81 assert(map != nullptr);
82 for (const auto& rElement : elements)
84 cppuhelper::ServiceManager::Data::ImplementationMap::iterator j(
85 map->find(rElement));
86 assert(j != map->end());
87 std::vector<
88 std::shared_ptr<
89 cppuhelper::ServiceManager::Data::Implementation > >::iterator
90 k(std::find(j->second.begin(), j->second.end(), implementation));
91 assert(k != j->second.end());
92 j->second.erase(k);
93 if (j->second.empty()) {
94 map->erase(j);
99 // For simplicity, this code keeps throwing
100 // css::registry::InvalidRegistryException for invalid XML rdbs (even though
101 // that does not fit the exception's name):
102 class Parser {
103 public:
104 Parser(
105 OUString const & uri,
106 css::uno::Reference< css::uno::XComponentContext > const & alienContext,
107 cppuhelper::ServiceManager::Data * data);
109 Parser(const Parser&) = delete;
110 const Parser& operator=(const Parser&) = delete;
112 private:
113 void handleComponent();
115 void handleImplementation();
117 void handleService();
119 void handleSingleton();
121 OUString getNameAttribute();
123 xmlreader::XmlReader reader_;
124 css::uno::Reference< css::uno::XComponentContext > alienContext_;
125 cppuhelper::ServiceManager::Data * data_;
126 OUString attrLoader_;
127 OUString attrUri_;
128 OUString attrEnvironment_;
129 OUString attrPrefix_;
130 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
131 implementation_;
134 Parser::Parser(
135 OUString const & uri,
136 css::uno::Reference< css::uno::XComponentContext > const & alienContext,
137 cppuhelper::ServiceManager::Data * data):
138 reader_(uri), alienContext_(alienContext), data_(data)
140 assert(data != nullptr);
141 int ucNsId = reader_.registerNamespaceIri(
142 xmlreader::Span(
143 RTL_CONSTASCII_STRINGPARAM(
144 "http://openoffice.org/2010/uno-components")));
145 enum State {
146 STATE_BEGIN, STATE_END, STATE_COMPONENTS, STATE_COMPONENT_INITIAL,
147 STATE_COMPONENT, STATE_IMPLEMENTATION, STATE_SERVICE, STATE_SINGLETON };
148 for (State state = STATE_BEGIN;;) {
149 xmlreader::Span name;
150 int nsId;
151 xmlreader::XmlReader::Result res = reader_.nextItem(
152 xmlreader::XmlReader::Text::NONE, &name, &nsId);
153 switch (state) {
154 case STATE_BEGIN:
155 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
156 && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
158 state = STATE_COMPONENTS;
159 break;
161 throw css::registry::InvalidRegistryException(
162 reader_.getUrl() + ": unexpected item in outer level");
163 case STATE_END:
164 if (res == xmlreader::XmlReader::Result::Done) {
165 return;
167 throw css::registry::InvalidRegistryException(
168 reader_.getUrl() + ": unexpected item in outer level");
169 case STATE_COMPONENTS:
170 if (res == xmlreader::XmlReader::Result::End) {
171 state = STATE_END;
172 break;
174 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
175 && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
177 handleComponent();
178 state = STATE_COMPONENT_INITIAL;
179 break;
181 throw css::registry::InvalidRegistryException(
182 reader_.getUrl() + ": unexpected item in <components>");
183 case STATE_COMPONENT:
184 if (res == xmlreader::XmlReader::Result::End) {
185 state = STATE_COMPONENTS;
186 break;
188 [[fallthrough]];
189 case STATE_COMPONENT_INITIAL:
190 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
191 && name.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
193 handleImplementation();
194 state = STATE_IMPLEMENTATION;
195 break;
197 throw css::registry::InvalidRegistryException(
198 reader_.getUrl() + ": unexpected item in <component>");
199 case STATE_IMPLEMENTATION:
200 if (res == xmlreader::XmlReader::Result::End) {
201 state = STATE_COMPONENT;
202 break;
204 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
205 && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
207 handleService();
208 state = STATE_SERVICE;
209 break;
211 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
212 && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
214 handleSingleton();
215 state = STATE_SINGLETON;
216 break;
218 throw css::registry::InvalidRegistryException(
219 reader_.getUrl() + ": unexpected item in <implementation>");
220 case STATE_SERVICE:
221 if (res == xmlreader::XmlReader::Result::End) {
222 state = STATE_IMPLEMENTATION;
223 break;
225 throw css::registry::InvalidRegistryException(
226 reader_.getUrl() + ": unexpected item in <service>");
227 case STATE_SINGLETON:
228 if (res == xmlreader::XmlReader::Result::End) {
229 state = STATE_IMPLEMENTATION;
230 break;
232 throw css::registry::InvalidRegistryException(
233 reader_.getUrl() + ": unexpected item in <service>");
238 void Parser::handleComponent() {
239 attrLoader_ = OUString();
240 attrUri_ = OUString();
241 attrEnvironment_ = OUString();
242 attrPrefix_ = OUString();
243 xmlreader::Span name;
244 int nsId;
245 while (reader_.nextAttribute(&nsId, &name)) {
246 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
247 && name.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
249 if (!attrLoader_.isEmpty()) {
250 throw css::registry::InvalidRegistryException(
251 reader_.getUrl()
252 + ": <component> has multiple \"loader\" attributes");
254 attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8();
255 if (attrLoader_.isEmpty()) {
256 throw css::registry::InvalidRegistryException(
257 reader_.getUrl()
258 + ": <component> has empty \"loader\" attribute");
260 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
261 && name.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
263 if (!attrUri_.isEmpty()) {
264 throw css::registry::InvalidRegistryException(
265 reader_.getUrl()
266 + ": <component> has multiple \"uri\" attributes");
268 attrUri_ = reader_.getAttributeValue(false).convertFromUtf8();
269 if (attrUri_.isEmpty()) {
270 throw css::registry::InvalidRegistryException(
271 reader_.getUrl()
272 + ": <component> has empty \"uri\" attribute");
274 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
275 && name.equals(RTL_CONSTASCII_STRINGPARAM("environment")))
277 if (!attrEnvironment_.isEmpty()) {
278 throw css::registry::InvalidRegistryException(
279 reader_.getUrl() +
280 ": <component> has multiple \"environment\" attributes");
282 attrEnvironment_ = reader_.getAttributeValue(false)
283 .convertFromUtf8();
284 if (attrEnvironment_.isEmpty()) {
285 throw css::registry::InvalidRegistryException(
286 reader_.getUrl() +
287 ": <component> has empty \"environment\" attribute");
289 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
290 && name.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
292 if (!attrPrefix_.isEmpty()) {
293 throw css::registry::InvalidRegistryException(
294 reader_.getUrl() +
295 ": <component> has multiple \"prefix\" attributes");
297 attrPrefix_ = reader_.getAttributeValue(false).convertFromUtf8();
298 if (attrPrefix_.isEmpty()) {
299 throw css::registry::InvalidRegistryException(
300 reader_.getUrl() +
301 ": <component> has empty \"prefix\" attribute");
303 } else {
304 throw css::registry::InvalidRegistryException(
305 reader_.getUrl() + ": unexpected attribute \""
306 + name.convertFromUtf8() + "\" in <component>");
309 if (attrLoader_.isEmpty()) {
310 throw css::registry::InvalidRegistryException(
311 reader_.getUrl() + ": <component> is missing \"loader\" attribute");
313 if (attrUri_.isEmpty()) {
314 throw css::registry::InvalidRegistryException(
315 reader_.getUrl() + ": <component> is missing \"uri\" attribute");
317 #ifndef DISABLE_DYNLOADING
318 try {
319 attrUri_ = rtl::Uri::convertRelToAbs(reader_.getUrl(), attrUri_);
320 } catch (const rtl::MalformedUriException & e) {
321 throw css::registry::InvalidRegistryException(
322 reader_.getUrl() + ": bad \"uri\" attribute: " + e.getMessage());
324 #endif
327 void Parser::handleImplementation() {
328 OUString attrName;
329 OUString attrConstructor;
330 bool attrSingleInstance = false;
331 xmlreader::Span name;
332 int nsId;
333 while (reader_.nextAttribute(&nsId, &name)) {
334 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
335 && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
337 if (!attrName.isEmpty()) {
338 throw css::registry::InvalidRegistryException(
339 reader_.getUrl()
340 + ": <implementation> has multiple \"name\" attributes");
342 attrName = reader_.getAttributeValue(false).convertFromUtf8();
343 if (attrName.isEmpty()) {
344 throw css::registry::InvalidRegistryException(
345 reader_.getUrl()
346 + ": <implementation> has empty \"name\" attribute");
348 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
349 && name.equals(RTL_CONSTASCII_STRINGPARAM("constructor")))
351 if (!attrConstructor.isEmpty()) {
352 throw css::registry::InvalidRegistryException(
353 reader_.getUrl()
354 + ": <implementation> has multiple \"constructor\""
355 " attributes");
357 attrConstructor = reader_.getAttributeValue(false)
358 .convertFromUtf8();
359 if (attrConstructor.isEmpty()) {
360 throw css::registry::InvalidRegistryException(
361 reader_.getUrl()
362 + ": element has empty \"constructor\" attribute");
364 if (attrEnvironment_.isEmpty()) {
365 throw css::registry::InvalidRegistryException(
366 reader_.getUrl()
367 + ": <implementation> has \"constructor\" attribute but"
368 " <component> has no \"environment\" attribute");
370 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
371 && name.equals(RTL_CONSTASCII_STRINGPARAM("single-instance")))
373 if (attrSingleInstance) {
374 throw css::registry::InvalidRegistryException(
375 reader_.getUrl()
376 + ": <implementation> has multiple \"single-instance\" attributes");
378 if (!reader_.getAttributeValue(false).equals(RTL_CONSTASCII_STRINGPARAM("true"))) {
379 throw css::registry::InvalidRegistryException(
380 reader_.getUrl() + ": <implementation> has bad \"single-instance\" attribute");
382 attrSingleInstance = true;
383 } else {
384 throw css::registry::InvalidRegistryException(
385 reader_.getUrl() + ": unexpected element attribute \""
386 + name.convertFromUtf8() + "\" in <implementation>");
389 if (attrName.isEmpty()) {
390 throw css::registry::InvalidRegistryException(
391 reader_.getUrl()
392 + ": <implementation> is missing \"name\" attribute");
394 implementation_ =
395 std::make_shared<cppuhelper::ServiceManager::Data::Implementation>(
396 attrName, attrLoader_, attrUri_, attrEnvironment_, attrConstructor,
397 attrPrefix_, attrSingleInstance, alienContext_, reader_.getUrl());
398 if (!data_->namedImplementations.emplace(attrName, implementation_).
399 second)
401 throw css::registry::InvalidRegistryException(
402 reader_.getUrl() + ": duplicate <implementation name=\"" + attrName
403 + "\">");
407 void Parser::handleService() {
408 OUString name(getNameAttribute());
409 implementation_->services.push_back(name);
410 data_->services[name].push_back(implementation_);
413 void Parser::handleSingleton() {
414 OUString name(getNameAttribute());
415 implementation_->singletons.push_back(name);
416 data_->singletons[name].push_back(implementation_);
419 OUString Parser::getNameAttribute() {
420 OUString attrName;
421 xmlreader::Span name;
422 int nsId;
423 while (reader_.nextAttribute(&nsId, &name)) {
424 if (nsId != xmlreader::XmlReader::NAMESPACE_NONE
425 || !name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
427 throw css::registry::InvalidRegistryException(
428 reader_.getUrl() + ": expected element attribute \"name\"");
430 if (!attrName.isEmpty()) {
431 throw css::registry::InvalidRegistryException(
432 reader_.getUrl()
433 + ": element has multiple \"name\" attributes");
435 attrName = reader_.getAttributeValue(false).convertFromUtf8();
436 if (attrName.isEmpty()) {
437 throw css::registry::InvalidRegistryException(
438 reader_.getUrl() + ": element has empty \"name\" attribute");
441 if (attrName.isEmpty()) {
442 throw css::registry::InvalidRegistryException(
443 reader_.getUrl() + ": element is missing \"name\" attribute");
445 return attrName;
448 class ContentEnumeration:
449 public cppu::WeakImplHelper< css::container::XEnumeration >
451 public:
452 explicit ContentEnumeration(std::vector< css::uno::Any > const & factories):
453 factories_(factories), iterator_(factories_.begin()) {}
455 ContentEnumeration(const ContentEnumeration&) = delete;
456 const ContentEnumeration& operator=(const ContentEnumeration&) = delete;
458 private:
459 virtual ~ContentEnumeration() override {}
461 virtual sal_Bool SAL_CALL hasMoreElements() override;
463 virtual css::uno::Any SAL_CALL nextElement() override;
465 osl::Mutex mutex_;
466 std::vector< css::uno::Any > factories_;
467 std::vector< css::uno::Any >::const_iterator iterator_;
470 sal_Bool ContentEnumeration::hasMoreElements()
472 osl::MutexGuard g(mutex_);
473 return iterator_ != factories_.end();
476 css::uno::Any ContentEnumeration::nextElement()
478 osl::MutexGuard g(mutex_);
479 if (iterator_ == factories_.end()) {
480 throw css::container::NoSuchElementException(
481 "Bootstrap service manager service enumerator has no more elements",
482 static_cast< cppu::OWeakObject * >(this));
484 return *iterator_++;
487 css::beans::Property getDefaultContextProperty() {
488 return css::beans::Property(
489 "DefaultContext", -1,
490 cppu::UnoType< css::uno::XComponentContext >::get(),
491 css::beans::PropertyAttribute::READONLY);
494 class SingletonFactory:
495 public cppu::WeakImplHelper<css::lang::XSingleComponentFactory>
497 public:
498 SingletonFactory(
499 rtl::Reference< cppuhelper::ServiceManager > const & manager,
500 std::shared_ptr<
501 cppuhelper::ServiceManager::Data::Implementation > const &
502 implementation):
503 manager_(manager), implementation_(implementation)
504 { assert(manager.is()); assert(implementation); }
506 SingletonFactory(const SingletonFactory&) = delete;
507 const SingletonFactory& operator=(const SingletonFactory&) = delete;
509 private:
510 virtual ~SingletonFactory() override {}
512 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
513 createInstanceWithContext(
514 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
516 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
517 createInstanceWithArgumentsAndContext(
518 css::uno::Sequence< css::uno::Any > const & Arguments,
519 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
521 rtl::Reference< cppuhelper::ServiceManager > manager_;
522 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
523 implementation_;
526 css::uno::Reference< css::uno::XInterface >
527 SingletonFactory::createInstanceWithContext(
528 css::uno::Reference< css::uno::XComponentContext > const & Context)
530 manager_->loadImplementation(Context, implementation_);
531 return implementation_->createInstance(Context, true);
534 css::uno::Reference< css::uno::XInterface >
535 SingletonFactory::createInstanceWithArgumentsAndContext(
536 css::uno::Sequence< css::uno::Any > const & Arguments,
537 css::uno::Reference< css::uno::XComponentContext > const & Context)
539 manager_->loadImplementation(Context, implementation_);
540 return implementation_->createInstanceWithArguments(
541 Context, true, Arguments);
544 class ImplementationWrapper:
545 public cppu::WeakImplHelper<
546 css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
547 css::lang::XServiceInfo >
549 public:
550 ImplementationWrapper(
551 rtl::Reference< cppuhelper::ServiceManager > const & manager,
552 std::shared_ptr<
553 cppuhelper::ServiceManager::Data::Implementation > const &
554 implementation):
555 manager_(manager), implementation_(implementation)
556 { assert(manager.is()); assert(implementation); }
558 ImplementationWrapper(const ImplementationWrapper&) = delete;
559 const ImplementationWrapper& operator=(const ImplementationWrapper&) = delete;
561 private:
562 virtual ~ImplementationWrapper() override {}
564 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
565 createInstanceWithContext(
566 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
568 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
569 createInstanceWithArgumentsAndContext(
570 css::uno::Sequence< css::uno::Any > const & Arguments,
571 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
573 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
574 createInstance() override;
576 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
577 createInstanceWithArguments(
578 css::uno::Sequence< css::uno::Any > const & Arguments) override;
580 virtual OUString SAL_CALL getImplementationName() override;
582 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
584 virtual css::uno::Sequence< OUString > SAL_CALL
585 getSupportedServiceNames() override;
587 rtl::Reference< cppuhelper::ServiceManager > manager_;
588 std::weak_ptr< cppuhelper::ServiceManager::Data::Implementation >
589 implementation_;
592 css::uno::Reference< css::uno::XInterface >
593 ImplementationWrapper::createInstanceWithContext(
594 css::uno::Reference< css::uno::XComponentContext > const & Context)
596 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
597 assert(impl);
598 manager_->loadImplementation(Context, impl);
599 return impl->createInstance(Context, false);
602 css::uno::Reference< css::uno::XInterface >
603 ImplementationWrapper::createInstanceWithArgumentsAndContext(
604 css::uno::Sequence< css::uno::Any > const & Arguments,
605 css::uno::Reference< css::uno::XComponentContext > const & Context)
607 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
608 assert(impl);
609 manager_->loadImplementation(Context, impl);
610 return impl->createInstanceWithArguments(
611 Context, false, Arguments);
614 css::uno::Reference< css::uno::XInterface >
615 ImplementationWrapper::createInstance()
617 return createInstanceWithContext(manager_->getContext());
620 css::uno::Reference< css::uno::XInterface >
621 ImplementationWrapper::createInstanceWithArguments(
622 css::uno::Sequence< css::uno::Any > const & Arguments)
624 return createInstanceWithArgumentsAndContext(
625 Arguments, manager_->getContext());
628 OUString ImplementationWrapper::getImplementationName()
630 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
631 assert(impl);
632 return impl->name;
635 sal_Bool ImplementationWrapper::supportsService(OUString const & ServiceName)
637 return cppu::supportsService(this, ServiceName);
640 css::uno::Sequence< OUString >
641 ImplementationWrapper::getSupportedServiceNames()
643 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
644 assert(impl);
645 if (impl->services.size()
646 > o3tl::make_unsigned(SAL_MAX_INT32))
648 throw css::uno::RuntimeException(
649 ("Implementation " + impl->name
650 + " supports too many services"),
651 static_cast< cppu::OWeakObject * >(this));
653 return comphelper::containerToSequence(impl->services);
658 css::uno::Reference<css::uno::XInterface>
659 cppuhelper::ServiceManager::Data::Implementation::createInstance(
660 css::uno::Reference<css::uno::XComponentContext> const & context,
661 bool singletonRequest)
663 css::uno::Reference<css::uno::XInterface> inst;
664 if (isSingleInstance) {
665 osl::MutexGuard g(mutex);
666 if (!singleInstance.is()) {
667 singleInstance = doCreateInstance(context);
669 inst = singleInstance;
670 } else {
671 inst = doCreateInstance(context);
673 updateDisposeInstance(singletonRequest, inst);
674 return inst;
677 css::uno::Reference<css::uno::XInterface>
678 cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
679 css::uno::Reference<css::uno::XComponentContext> const & context,
680 bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
682 css::uno::Reference<css::uno::XInterface> inst;
683 if (isSingleInstance) {
684 osl::MutexGuard g(mutex);
685 if (!singleInstance.is()) {
686 singleInstance = doCreateInstanceWithArguments(context, arguments);
688 inst = singleInstance;
689 } else {
690 inst = doCreateInstanceWithArguments(context, arguments);
692 updateDisposeInstance(singletonRequest, inst);
693 return inst;
696 css::uno::Reference<css::uno::XInterface>
697 cppuhelper::ServiceManager::Data::Implementation::doCreateInstance(
698 css::uno::Reference<css::uno::XComponentContext> const & context)
700 if (constructorFn) {
701 return css::uno::Reference<css::uno::XInterface>(
702 constructorFn(context.get(), css::uno::Sequence<css::uno::Any>()),
703 SAL_NO_ACQUIRE);
704 } else if (factory1.is()) {
705 return factory1->createInstanceWithContext(context);
706 } else {
707 assert(factory2.is());
708 return factory2->createInstance();
712 css::uno::Reference<css::uno::XInterface>
713 cppuhelper::ServiceManager::Data::Implementation::doCreateInstanceWithArguments(
714 css::uno::Reference<css::uno::XComponentContext> const & context,
715 css::uno::Sequence<css::uno::Any> const & arguments)
717 if (constructorFn) {
718 css::uno::Reference<css::uno::XInterface> inst(
719 constructorFn(context.get(), arguments), SAL_NO_ACQUIRE);
720 //HACK: The constructor will either observe arguments and return inst
721 // that does not implement XInitialization (or null), or ignore
722 // arguments and return inst that implements XInitialization; this
723 // should be removed again once XInitialization-based implementations
724 // have become rare:
725 css::uno::Reference<css::lang::XInitialization> init(
726 inst, css::uno::UNO_QUERY);
727 if (init.is()) {
728 init->initialize(arguments);
730 return inst;
731 } else if (factory1.is()) {
732 return factory1->createInstanceWithArgumentsAndContext(
733 arguments, context);
734 } else {
735 assert(factory2.is());
736 return factory2->createInstanceWithArguments(arguments);
740 void cppuhelper::ServiceManager::Data::Implementation::updateDisposeInstance(
741 bool singletonRequest,
742 css::uno::Reference<css::uno::XInterface> const & instance)
744 // This is an optimization, to only call dispose once (from the component
745 // context) on a singleton that is obtained both via the component context
746 // and via the service manager; however, there is a harmless race here that
747 // may cause two calls to dispose nevertheless (also, this calls dispose on
748 // at most one of the instances obtained via the service manager, in case
749 // the implementation hands out different instances):
750 if (singletonRequest) {
751 osl::MutexGuard g(mutex);
752 disposeInstance.clear();
753 dispose = false;
754 } else if (shallDispose()) {
755 css::uno::Reference<css::lang::XComponent> comp(
756 instance, css::uno::UNO_QUERY);
757 if (comp.is()) {
758 osl::MutexGuard g(mutex);
759 if (dispose) {
760 disposeInstance = comp;
766 void cppuhelper::ServiceManager::addSingletonContextEntries(
767 std::vector< cppu::ContextEntry_Init > * entries)
769 assert(entries != nullptr);
770 for (const auto& [rName, rImpls] : data_.singletons)
772 assert(!rImpls.empty());
773 assert(rImpls[0]);
774 SAL_INFO_IF(
775 rImpls.size() > 1, "cppuhelper",
776 "Arbitrarily choosing " << rImpls[0]->name
777 << " among multiple implementations for " << rName);
778 entries->push_back(
779 cppu::ContextEntry_Init(
780 "/singletons/" + rName,
781 css::uno::makeAny<
782 css::uno::Reference<css::lang::XSingleComponentFactory> >(
783 new SingletonFactory(this, rImpls[0])),
784 true));
788 void cppuhelper::ServiceManager::loadImplementation(
789 css::uno::Reference< css::uno::XComponentContext > const & context,
790 std::shared_ptr< Data::Implementation > const & implementation)
792 assert(implementation);
794 osl::MutexGuard g(rBHelper.rMutex);
795 if (implementation->status == Data::Implementation::STATUS_LOADED) {
796 return;
799 OUString uri;
800 try {
801 uri = cppu::bootstrap_expandUri(implementation->uri);
802 } catch (css::lang::IllegalArgumentException & e) {
803 throw css::uno::DeploymentException(
804 "Cannot expand URI" + implementation->uri + ": " + e.Message,
805 static_cast< cppu::OWeakObject * >(this));
807 cppuhelper::WrapperConstructorFn ctor;
808 css::uno::Reference< css::uno::XInterface > f0;
809 // Special handling of SharedLibrary loader, with support for environment,
810 // constructor, and prefix arguments:
811 if (!implementation->alienContext.is()
812 && implementation->loader == "com.sun.star.loader.SharedLibrary")
814 cppuhelper::detail::loadSharedLibComponentFactory(
815 uri, implementation->environment,
816 implementation->prefix, implementation->name,
817 implementation->constructorName, this, &ctor, &f0);
818 if (ctor) {
819 assert(!implementation->environment.isEmpty());
821 } else {
822 SAL_WARN_IF(
823 !implementation->environment.isEmpty(), "cppuhelper",
824 "Loader " << implementation->loader
825 << " and non-empty environment "
826 << implementation->environment);
827 SAL_WARN_IF(
828 !implementation->prefix.isEmpty(), "cppuhelper",
829 "Loader " << implementation->loader
830 << " and non-empty constructor "
831 << implementation->constructorName);
832 SAL_WARN_IF(
833 !implementation->prefix.isEmpty(), "cppuhelper",
834 "Loader " << implementation->loader
835 << " and non-empty prefix " << implementation->prefix);
836 css::uno::Reference< css::uno::XComponentContext > ctxt;
837 css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
838 if (implementation->alienContext.is()) {
839 ctxt = implementation->alienContext;
840 smgr.set(ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
841 } else {
842 assert(context.is());
843 ctxt = context;
844 smgr = this;
846 css::uno::Reference< css::loader::XImplementationLoader > loader(
847 smgr->createInstanceWithContext(implementation->loader, ctxt),
848 css::uno::UNO_QUERY_THROW);
849 f0 = loader->activate(
850 implementation->name, OUString(), uri,
851 css::uno::Reference< css::registry::XRegistryKey >());
853 css::uno::Reference<css::lang::XSingleComponentFactory> f1;
854 css::uno::Reference<css::lang::XSingleServiceFactory> f2;
855 if (!ctor) {
856 f1.set(f0, css::uno::UNO_QUERY);
857 if (!f1.is()) {
858 f2.set(f0, css::uno::UNO_QUERY);
859 if (!f2.is()) {
860 throw css::uno::DeploymentException(
861 ("Implementation " + implementation->name
862 + " does not provide a constructor or factory"),
863 static_cast< cppu::OWeakObject * >(this));
867 //TODO: There is a race here, as the relevant service factory can be removed
868 // while the mutex is unlocked and loading can thus fail, as the entity from
869 // which to load can disappear once the service factory is removed.
870 osl::MutexGuard g(rBHelper.rMutex);
871 if (!(isDisposed()
872 || implementation->status == Data::Implementation::STATUS_LOADED))
874 implementation->status = Data::Implementation::STATUS_LOADED;
875 implementation->constructorFn = ctor;
876 implementation->factory1 = f1;
877 implementation->factory2 = f2;
881 void cppuhelper::ServiceManager::disposing() {
882 std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
883 std::vector< css::uno::Reference< css::lang::XComponent > > comps;
884 Data clear;
886 osl::MutexGuard g(rBHelper.rMutex);
887 for (const auto& rEntry : data_.namedImplementations)
889 assert(rEntry.second);
890 if (rEntry.second->shallDispose()) {
891 osl::MutexGuard g2(rEntry.second->mutex);
892 if (rEntry.second->disposeInstance.is()) {
893 sngls.push_back(rEntry.second->disposeInstance);
897 for (const auto& rEntry : data_.dynamicImplementations)
899 assert(rEntry.second);
900 if (rEntry.second->shallDispose()) {
901 osl::MutexGuard g2(rEntry.second->mutex);
902 if (rEntry.second->disposeInstance.is()) {
903 sngls.push_back(rEntry.second->disposeInstance);
906 if (rEntry.second->component.is()) {
907 comps.push_back(rEntry.second->component);
910 data_.namedImplementations.swap(clear.namedImplementations);
911 data_.dynamicImplementations.swap(clear.dynamicImplementations);
912 data_.services.swap(clear.services);
913 data_.singletons.swap(clear.singletons);
915 for (const auto& rxSngl : sngls)
917 try {
918 rxSngl->dispose();
919 } catch (css::uno::RuntimeException & e) {
920 SAL_WARN("cppuhelper", "Ignoring " << e << " while disposing singleton");
923 for (const auto& rxComp : comps)
925 removeEventListenerFromComponent(rxComp);
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 "invalid ServiceManager::initialize argument",
938 css::uno::Reference<css::uno::XInterface>(), 0);
940 preloadImplementations();
943 OUString cppuhelper::ServiceManager::getImplementationName()
945 return
946 "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager";
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 { "com.sun.star.lang.MultiServiceFactory", "com.sun.star.lang.ServiceManager" };
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 osl::MutexGuard g(rBHelper.rMutex);
983 if (isDisposed()) {
984 return css::uno::Sequence< OUString >();
986 if (data_.services.size() > o3tl::make_unsigned(SAL_MAX_INT32)) {
987 throw css::uno::RuntimeException(
988 "getAvailableServiceNames: too many services",
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 osl::MutexGuard g(rBHelper.rMutex);
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 "ServiceManager createEnumeration: method not supported",
1035 static_cast< cppu::OWeakObject * >(this));
1038 sal_Bool cppuhelper::ServiceManager::has(css::uno::Any const &)
1040 throw css::uno::RuntimeException(
1041 "ServiceManager has: method not supported",
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 : std::as_const(args)) {
1052 if (arg.Name == "uri") {
1053 OUString uri;
1054 if (!(arg.Value >>= uri)) {
1055 throw css::lang::IllegalArgumentException(
1056 "Bad uri argument",
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 "Multiple component-context arguments",
1064 static_cast< cppu::OWeakObject * >(this), 0);
1066 if (!(arg.Value >>= alienContext) || !alienContext.is()) {
1067 throw css::lang::IllegalArgumentException(
1068 "Bad component-context argument",
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;
1085 // At least revisions up to 1.7 of LanguageTool.oxt (incl. the bundled 1.4.0 in
1086 // module languagetool) contain an (actively registered) factory that does not
1087 // implement XServiceInfo (see <http://sourceforge.net/tracker/?
1088 // func=detail&aid=3526635&group_id=110216&atid=655717> "SingletonFactory should
1089 // implement XServiceInfo"); the old OServiceManager::insert
1090 // (stoc/source/servicemanager/servicemanager.cxx) silently did not add such
1091 // broken factories to its m_ImplementationNameMap, so ignore them here for
1092 // backwards compatibility of live-insertion of extensions, too.
1094 // (The plan was that this warning would go away (and we would do the
1095 // throw instead) for the incompatible LO 4, but we changed our mind):
1096 css::uno::Reference< css::lang::XSingleComponentFactory > legacy;
1097 if ((aElement >>= legacy) && legacy.is()) {
1098 SAL_WARN(
1099 "cppuhelper",
1100 "Ignored XSingleComponentFactory not implementing XServiceInfo");
1101 return;
1104 throw css::lang::IllegalArgumentException(
1105 "Bad insert element", static_cast< cppu::OWeakObject * >(this), 0);
1108 void cppuhelper::ServiceManager::remove(css::uno::Any const & aElement)
1110 css::uno::Sequence< css::beans::NamedValue > args;
1111 if (aElement >>= args) {
1112 std::vector< OUString > uris;
1113 for (const auto & i : std::as_const(args)) {
1114 if (i.Name != "uri") {
1115 throw css::lang::IllegalArgumentException(
1116 "Bad argument " + i.Name,
1117 static_cast< cppu::OWeakObject * >(this), 0);
1119 OUString uri;
1120 if (!(i.Value >>= uri)) {
1121 throw css::lang::IllegalArgumentException(
1122 "Bad uri argument",
1123 static_cast< cppu::OWeakObject * >(this), 0);
1125 uris.push_back(uri);
1127 removeRdbFiles(uris);
1128 return;
1130 css::uno::Reference< css::lang::XServiceInfo > info;
1131 if ((aElement >>= info) && info.is()) {
1132 if (!removeLegacyFactory(info, true)) {
1133 throw css::container::NoSuchElementException(
1134 "Remove non-inserted factory object",
1135 static_cast< cppu::OWeakObject * >(this));
1137 return;
1139 OUString impl;
1140 if (aElement >>= impl) {
1141 // For live-removal of extensions:
1142 removeImplementation(impl);
1143 return;
1145 throw css::lang::IllegalArgumentException(
1146 "Bad remove element", static_cast< cppu::OWeakObject * >(this), 0);
1149 css::uno::Reference< css::container::XEnumeration >
1150 cppuhelper::ServiceManager::createContentEnumeration(
1151 OUString const & aServiceName)
1153 std::vector< std::shared_ptr< Data::Implementation > > impls;
1155 osl::MutexGuard g(rBHelper.rMutex);
1156 Data::ImplementationMap::const_iterator i(
1157 data_.services.find(aServiceName));
1158 if (i != data_.services.end()) {
1159 impls = i->second;
1162 std::vector< css::uno::Any > factories;
1163 for (const auto& rxImpl : impls)
1165 Data::Implementation * impl = rxImpl.get();
1166 assert(impl != nullptr);
1168 osl::MutexGuard g(rBHelper.rMutex);
1169 if (isDisposed()) {
1170 factories.clear();
1171 break;
1173 if (impl->status == Data::Implementation::STATUS_NEW) {
1174 // Postpone actual implementation instantiation as long as
1175 // possible (so that e.g. opening LO's "Tools - Macros" menu
1176 // does not try to instantiate a JVM, which can lead to a
1177 // synchronous error dialog when no JVM is specified, and
1178 // showing the dialog while hovering over a menu can cause
1179 // trouble):
1180 impl->factory1 = new ImplementationWrapper(this, rxImpl);
1181 impl->status = Data::Implementation::STATUS_WRAPPER;
1183 if (impl->constructorFn != nullptr && !impl->factory1.is()) {
1184 impl->factory1 = new ImplementationWrapper(this, rxImpl);
1187 if (impl->factory1.is()) {
1188 factories.push_back(css::uno::Any(impl->factory1));
1189 } else {
1190 assert(impl->factory2.is());
1191 factories.push_back(css::uno::Any(impl->factory2));
1194 return new ContentEnumeration(factories);
1197 css::uno::Reference< css::beans::XPropertySetInfo >
1198 cppuhelper::ServiceManager::getPropertySetInfo()
1200 return this;
1203 void cppuhelper::ServiceManager::setPropertyValue(
1204 OUString const & aPropertyName, css::uno::Any const &)
1206 if (aPropertyName == "DefaultContext") {
1207 throw css::beans::PropertyVetoException(
1208 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1209 } else {
1210 throw css::beans::UnknownPropertyException(
1211 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1215 css::uno::Any cppuhelper::ServiceManager::getPropertyValue(
1216 OUString const & PropertyName)
1218 if (PropertyName != "DefaultContext") {
1219 throw css::beans::UnknownPropertyException(
1220 PropertyName, static_cast< cppu::OWeakObject * >(this));
1222 assert(context_.is());
1223 return css::uno::Any(context_);
1226 void cppuhelper::ServiceManager::addPropertyChangeListener(
1227 OUString const & aPropertyName,
1228 css::uno::Reference< css::beans::XPropertyChangeListener > const &
1229 xListener)
1231 if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1232 throw css::beans::UnknownPropertyException(
1233 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1235 // DefaultContext does not change, so just treat it as an event listener:
1236 return addEventListener(xListener);
1239 void cppuhelper::ServiceManager::removePropertyChangeListener(
1240 OUString const & aPropertyName,
1241 css::uno::Reference< css::beans::XPropertyChangeListener > const &
1242 aListener)
1244 if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1245 throw css::beans::UnknownPropertyException(
1246 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1248 // DefaultContext does not change, so just treat it as an event listener:
1249 return removeEventListener(aListener);
1252 void cppuhelper::ServiceManager::addVetoableChangeListener(
1253 OUString const & PropertyName,
1254 css::uno::Reference< css::beans::XVetoableChangeListener > const &
1255 aListener)
1257 if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1258 throw css::beans::UnknownPropertyException(
1259 PropertyName, static_cast< cppu::OWeakObject * >(this));
1261 // DefaultContext does not change, so just treat it as an event listener:
1262 return addEventListener(aListener);
1265 void cppuhelper::ServiceManager::removeVetoableChangeListener(
1266 OUString const & PropertyName,
1267 css::uno::Reference< css::beans::XVetoableChangeListener > const &
1268 aListener)
1270 if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1271 throw css::beans::UnknownPropertyException(
1272 PropertyName, static_cast< cppu::OWeakObject * >(this));
1274 // DefaultContext does not change, so just treat it as an event listener:
1275 return removeEventListener(aListener);
1278 css::uno::Sequence< css::beans::Property >
1279 cppuhelper::ServiceManager::getProperties() {
1280 css::uno::Sequence< css::beans::Property > props(1);
1281 props[0] = getDefaultContextProperty();
1282 return props;
1285 css::beans::Property cppuhelper::ServiceManager::getPropertyByName(
1286 OUString const & aName)
1288 if (aName != "DefaultContext") {
1289 throw css::beans::UnknownPropertyException(
1290 aName, static_cast< cppu::OWeakObject * >(this));
1292 return getDefaultContextProperty();
1295 sal_Bool cppuhelper::ServiceManager::hasPropertyByName(
1296 OUString const & Name)
1298 return Name == "DefaultContext";
1301 cppuhelper::ServiceManager::~ServiceManager() {}
1303 void cppuhelper::ServiceManager::disposing(
1304 css::lang::EventObject const & Source)
1306 removeLegacyFactory(
1307 css::uno::Reference< css::lang::XServiceInfo >(
1308 Source.Source, css::uno::UNO_QUERY_THROW),
1309 false);
1312 void cppuhelper::ServiceManager::removeEventListenerFromComponent(
1313 css::uno::Reference< css::lang::XComponent > const & component)
1315 assert(component.is());
1316 try {
1317 component->removeEventListener(this);
1318 } catch (css::uno::RuntimeException & e) {
1319 SAL_INFO(
1320 "cppuhelper",
1321 "Ignored removeEventListener RuntimeException " + e.Message);
1325 void cppuhelper::ServiceManager::init(OUString const & rdbUris) {
1326 for (sal_Int32 i = 0; i != -1;) {
1327 OUString uri(rdbUris.getToken(0, ' ', i));
1328 if (uri.isEmpty()) {
1329 continue;
1331 bool optional;
1332 bool directory;
1333 cppu::decodeRdbUri(&uri, &optional, &directory);
1334 if (directory) {
1335 readRdbDirectory(uri, optional);
1336 } else {
1337 readRdbFile(uri, optional);
1342 void cppuhelper::ServiceManager::readRdbDirectory(
1343 OUString const & uri, bool optional)
1345 osl::Directory dir(uri);
1346 switch (dir.open()) {
1347 case osl::FileBase::E_None:
1348 break;
1349 case osl::FileBase::E_NOENT:
1350 if (optional) {
1351 SAL_INFO("cppuhelper", "Ignored optional " << uri);
1352 return;
1354 [[fallthrough]];
1355 default:
1356 throw css::uno::DeploymentException(
1357 "Cannot open directory " + uri,
1358 static_cast< cppu::OWeakObject * >(this));
1360 for (;;) {
1361 OUString url;
1362 if (!cppu::nextDirectoryItem(dir, &url)) {
1363 break;
1365 readRdbFile(url, false);
1369 void cppuhelper::ServiceManager::readRdbFile(
1370 OUString const & uri, bool optional)
1372 try {
1373 Parser(
1374 uri, css::uno::Reference< css::uno::XComponentContext >(), &data_);
1375 } catch (css::container::NoSuchElementException &) {
1376 if (!optional) {
1377 throw css::uno::DeploymentException(
1378 uri + ": no such file",
1379 static_cast< cppu::OWeakObject * >(this));
1381 SAL_INFO("cppuhelper", "Ignored optional " << uri);
1382 } catch (css::registry::InvalidRegistryException & e) {
1383 if (!readLegacyRdbFile(uri)) {
1384 throw css::uno::DeploymentException(
1385 "InvalidRegistryException: " + e.Message,
1386 static_cast< cppu::OWeakObject * >(this));
1388 } catch (css::uno::RuntimeException &) {
1389 if (!readLegacyRdbFile(uri)) {
1390 throw;
1395 bool cppuhelper::ServiceManager::readLegacyRdbFile(OUString const & uri) {
1396 Registry reg;
1397 switch (reg.open(uri, RegAccessMode::READONLY)) {
1398 case RegError::NO_ERROR:
1399 break;
1400 case RegError::REGISTRY_NOT_EXISTS:
1401 case RegError::INVALID_REGISTRY:
1403 // Ignore empty rdb files (which are at least seen by subordinate
1404 // uno processes during extension registration; Registry::open can
1405 // fail on them if mmap(2) returns EINVAL for a zero length):
1406 osl::DirectoryItem item;
1407 if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
1408 osl::FileStatus status(osl_FileStatus_Mask_FileSize);
1409 if (item.getFileStatus(status) == osl::FileBase::E_None
1410 && status.getFileSize() == 0)
1412 return true;
1416 [[fallthrough]];
1417 default:
1418 return false;
1420 RegistryKey rootKey;
1421 if (reg.openRootKey(rootKey) != RegError::NO_ERROR) {
1422 throw css::uno::DeploymentException(
1423 "Failure reading legacy rdb file " + uri,
1424 static_cast< cppu::OWeakObject * >(this));
1426 RegistryKeyArray impls;
1427 switch (rootKey.openSubKeys("IMPLEMENTATIONS", impls)) {
1428 case RegError::NO_ERROR:
1429 break;
1430 case RegError::KEY_NOT_EXISTS:
1431 return true;
1432 default:
1433 throw css::uno::DeploymentException(
1434 "Failure reading legacy rdb file " + uri,
1435 static_cast< cppu::OWeakObject * >(this));
1437 for (sal_uInt32 i = 0; i != impls.getLength(); ++i) {
1438 RegistryKey implKey(impls.getElement(i));
1439 assert(implKey.getName().match("/IMPLEMENTATIONS/"));
1440 OUString name(
1441 implKey.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1442 std::shared_ptr< Data::Implementation > impl =
1443 std::make_shared<Data::Implementation>(
1444 name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"),
1445 readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "", "", false,
1446 css::uno::Reference< css::uno::XComponentContext >(), uri);
1447 if (!data_.namedImplementations.emplace(name, impl).second)
1449 throw css::registry::InvalidRegistryException(
1450 uri + ": duplicate <implementation name=\"" + name + "\">");
1452 readLegacyRdbStrings(
1453 uri, implKey, "UNO/SERVICES", &impl->services);
1454 for (const auto& rService : impl->services)
1456 data_.services[rService].push_back(impl);
1458 readLegacyRdbStrings(
1459 uri, implKey, "UNO/SINGLETONS", &impl->singletons);
1460 for (const auto& rSingleton : impl->singletons)
1462 data_.singletons[rSingleton].push_back(impl);
1465 return true;
1468 OUString cppuhelper::ServiceManager::readLegacyRdbString(
1469 std::u16string_view uri, RegistryKey & key, OUString const & path)
1471 RegistryKey subkey;
1472 RegValueType t;
1473 sal_uInt32 s(0);
1474 if (key.openKey(path, subkey) != RegError::NO_ERROR
1475 || subkey.getValueInfo(OUString(), &t, &s) != RegError::NO_ERROR
1476 || t != RegValueType::STRING
1477 || s == 0 || s > o3tl::make_unsigned(SAL_MAX_INT32))
1479 throw css::uno::DeploymentException(
1480 OUString::Concat("Failure reading legacy rdb file ") + uri,
1481 static_cast< cppu::OWeakObject * >(this));
1483 OUString val;
1484 std::vector< char > v(s); // assuming sal_uInt32 fits into vector::size_type
1485 if (subkey.getValue(OUString(), v.data()) != RegError::NO_ERROR
1486 || v.back() != '\0'
1487 || !rtl_convertStringToUString(
1488 &val.pData, v.data(), static_cast< sal_Int32 >(s - 1),
1489 RTL_TEXTENCODING_UTF8,
1490 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1491 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1492 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
1494 throw css::uno::DeploymentException(
1495 OUString::Concat("Failure reading legacy rdb file ") + uri,
1496 static_cast< cppu::OWeakObject * >(this));
1498 return val;
1501 void cppuhelper::ServiceManager::readLegacyRdbStrings(
1502 std::u16string_view uri, RegistryKey & key, OUString const & path,
1503 std::vector< OUString > * strings)
1505 assert(strings != nullptr);
1506 RegistryKey subkey;
1507 switch (key.openKey(path, subkey)) {
1508 case RegError::NO_ERROR:
1509 break;
1510 case RegError::KEY_NOT_EXISTS:
1511 return;
1512 default:
1513 throw css::uno::DeploymentException(
1514 OUString::Concat("Failure reading legacy rdb file ") + uri,
1515 static_cast< cppu::OWeakObject * >(this));
1517 OUString prefix(subkey.getName() + "/");
1518 RegistryKeyNames names;
1519 if (subkey.getKeyNames(OUString(), names) != RegError::NO_ERROR) {
1520 throw css::uno::DeploymentException(
1521 OUString::Concat("Failure reading legacy rdb file ") + uri,
1522 static_cast< cppu::OWeakObject * >(this));
1524 for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
1525 assert(names.getElement(i).match(prefix));
1526 strings->push_back(names.getElement(i).copy(prefix.getLength()));
1530 void cppuhelper::ServiceManager::insertRdbFiles(
1531 std::vector< OUString > const & uris,
1532 css::uno::Reference< css::uno::XComponentContext > const & alienContext)
1534 Data extra;
1535 for (const auto& rUri : uris)
1537 try {
1538 Parser(rUri, alienContext, &extra);
1539 } catch (css::container::NoSuchElementException &) {
1540 throw css::lang::IllegalArgumentException(
1541 rUri + ": no such file", static_cast< cppu::OWeakObject * >(this),
1543 } catch (css::registry::InvalidRegistryException & e) {
1544 throw css::lang::IllegalArgumentException(
1545 "InvalidRegistryException: " + e.Message,
1546 static_cast< cppu::OWeakObject * >(this), 0);
1549 insertExtraData(extra);
1552 void cppuhelper::ServiceManager::insertLegacyFactory(
1553 css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo)
1555 assert(factoryInfo.is());
1556 OUString name(factoryInfo->getImplementationName());
1557 css::uno::Reference< css::lang::XSingleComponentFactory > f1(
1558 factoryInfo, css::uno::UNO_QUERY);
1559 css::uno::Reference< css::lang::XSingleServiceFactory > f2;
1560 if (!f1.is()) {
1561 f2.set(factoryInfo, css::uno::UNO_QUERY);
1562 if (!f2.is()) {
1563 throw css::lang::IllegalArgumentException(
1564 ("Bad XServiceInfo argument implements neither"
1565 " XSingleComponentFactory nor XSingleServiceFactory"),
1566 static_cast< cppu::OWeakObject * >(this), 0);
1569 css::uno::Reference< css::lang::XComponent > comp(
1570 factoryInfo, css::uno::UNO_QUERY);
1571 std::shared_ptr< Data::Implementation > impl =
1572 std::make_shared<Data::Implementation>(name, f1, f2, comp);
1573 Data extra;
1574 if (!name.isEmpty()) {
1575 extra.namedImplementations.emplace(name, impl);
1577 extra.dynamicImplementations.emplace(factoryInfo, impl);
1578 const css::uno::Sequence< OUString > services(
1579 factoryInfo->getSupportedServiceNames());
1580 for (const auto & i : services) {
1581 impl->services.push_back(i);
1582 extra.services[i].push_back(impl);
1584 if (insertExtraData(extra) && comp.is()) {
1585 comp->addEventListener(this);
1589 bool cppuhelper::ServiceManager::insertExtraData(Data const & extra) {
1591 osl::MutexGuard g(rBHelper.rMutex);
1592 if (isDisposed()) {
1593 return false;
1595 auto i = std::find_if(extra.namedImplementations.begin(), extra.namedImplementations.end(),
1596 [this](const Data::NamedImplementations::value_type& rEntry) {
1597 return data_.namedImplementations.find(rEntry.first) != data_.namedImplementations.end(); });
1598 if (i != extra.namedImplementations.end())
1600 throw css::lang::IllegalArgumentException(
1601 "Insert duplicate implementation name " + i->first,
1602 static_cast< cppu::OWeakObject * >(this), 0);
1604 bool bDuplicate = std::any_of(extra.dynamicImplementations.begin(), extra.dynamicImplementations.end(),
1605 [this](const Data::DynamicImplementations::value_type& rEntry) {
1606 return data_.dynamicImplementations.find(rEntry.first) != data_.dynamicImplementations.end(); });
1607 if (bDuplicate)
1609 throw css::lang::IllegalArgumentException(
1610 "Insert duplicate factory object",
1611 static_cast< cppu::OWeakObject * >(this), 0);
1613 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1614 data_.namedImplementations.insert(
1615 extra.namedImplementations.begin(),
1616 extra.namedImplementations.end());
1617 data_.dynamicImplementations.insert(
1618 extra.dynamicImplementations.begin(),
1619 extra.dynamicImplementations.end());
1620 insertImplementationMap(&data_.services, extra.services);
1621 insertImplementationMap(&data_.singletons, extra.singletons);
1623 //TODO: Updating the component context singleton data should be part of the
1624 // atomic service manager update:
1625 if (!extra.singletons.empty()) {
1626 assert(context_.is());
1627 css::uno::Reference< css::container::XNameContainer > cont(
1628 context_, css::uno::UNO_QUERY_THROW);
1629 for (const auto& [rName, rImpls] : extra.singletons)
1631 OUString name("/singletons/" + rName);
1632 //TODO: Update should be atomic:
1633 try {
1634 cont->removeByName(name + "/arguments");
1635 } catch (const css::container::NoSuchElementException &) {}
1636 assert(!rImpls.empty());
1637 assert(rImpls[0]);
1638 SAL_INFO_IF(
1639 rImpls.size() > 1, "cppuhelper",
1640 "Arbitrarily choosing " << rImpls[0]->name
1641 << " among multiple implementations for singleton "
1642 << rName);
1643 try {
1644 cont->insertByName(
1645 name + "/service", css::uno::Any(rImpls[0]->name));
1646 } catch (css::container::ElementExistException &) {
1647 cont->replaceByName(
1648 name + "/service", css::uno::Any(rImpls[0]->name));
1650 try {
1651 cont->insertByName(name, css::uno::Any());
1652 } catch (css::container::ElementExistException &) {
1653 SAL_INFO("cppuhelper", "Overwriting singleton " << rName);
1654 cont->replaceByName(name, css::uno::Any());
1658 return true;
1661 void cppuhelper::ServiceManager::removeRdbFiles(
1662 std::vector< OUString > const & uris)
1664 // The underlying data structures make this function somewhat inefficient,
1665 // but the assumption is that it is rarely called (and that if it is called,
1666 // it is called with a uris vector of size one):
1667 std::vector< std::shared_ptr< Data::Implementation > > clear;
1669 osl::MutexGuard g(rBHelper.rMutex);
1670 for (const auto& rUri : uris)
1672 for (Data::NamedImplementations::iterator j(
1673 data_.namedImplementations.begin());
1674 j != data_.namedImplementations.end();)
1676 assert(j->second);
1677 if (j->second->rdbFile == rUri) {
1678 clear.push_back(j->second);
1679 //TODO: The below leaves data_ in an inconsistent state upon
1680 // exceptions:
1681 removeFromImplementationMap(
1682 &data_.services, j->second->services, j->second);
1683 removeFromImplementationMap(
1684 &data_.singletons, j->second->singletons,
1685 j->second);
1686 j = data_.namedImplementations.erase(j);
1687 } else {
1688 ++j;
1693 //TODO: Update the component context singleton data
1696 bool cppuhelper::ServiceManager::removeLegacyFactory(
1697 css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
1698 bool removeListener)
1700 assert(factoryInfo.is());
1701 std::shared_ptr< Data::Implementation > clear;
1702 css::uno::Reference< css::lang::XComponent > comp;
1704 osl::MutexGuard g(rBHelper.rMutex);
1705 Data::DynamicImplementations::iterator i(
1706 data_.dynamicImplementations.find(factoryInfo));
1707 if (i == data_.dynamicImplementations.end()) {
1708 return isDisposed();
1710 assert(i->second);
1711 clear = i->second;
1712 if (removeListener) {
1713 comp = i->second->component;
1715 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1716 removeFromImplementationMap(
1717 &data_.services, i->second->services, i->second);
1718 removeFromImplementationMap(
1719 &data_.singletons, i->second->singletons, i->second);
1720 if (!i->second->name.isEmpty()) {
1721 data_.namedImplementations.erase(i->second->name);
1723 data_.dynamicImplementations.erase(i);
1725 if (comp.is()) {
1726 removeEventListenerFromComponent(comp);
1728 return true;
1731 void cppuhelper::ServiceManager::removeImplementation(const OUString & name) {
1732 // The underlying data structures make this function somewhat inefficient,
1733 // but the assumption is that it is rarely called:
1734 std::shared_ptr< Data::Implementation > clear;
1736 osl::MutexGuard g(rBHelper.rMutex);
1737 if (isDisposed()) {
1738 return;
1740 Data::NamedImplementations::iterator i(
1741 data_.namedImplementations.find(name));
1742 if (i == data_.namedImplementations.end()) {
1743 throw css::container::NoSuchElementException(
1744 "Remove non-inserted implementation " + name,
1745 static_cast< cppu::OWeakObject * >(this));
1747 assert(i->second);
1748 clear = i->second;
1749 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1750 removeFromImplementationMap(
1751 &data_.services, i->second->services, i->second);
1752 removeFromImplementationMap(
1753 &data_.singletons, i->second->singletons, i->second);
1754 auto j = std::find_if(data_.dynamicImplementations.begin(), data_.dynamicImplementations.end(),
1755 [&i](const Data::DynamicImplementations::value_type& rEntry) { return rEntry.second == i->second; });
1756 if (j != data_.dynamicImplementations.end())
1757 data_.dynamicImplementations.erase(j);
1758 data_.namedImplementations.erase(i);
1762 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
1763 cppuhelper::ServiceManager::findServiceImplementation(
1764 css::uno::Reference< css::uno::XComponentContext > const & context,
1765 OUString const & specifier)
1767 std::shared_ptr< Data::Implementation > impl;
1768 bool loaded;
1770 osl::MutexGuard g(rBHelper.rMutex);
1771 Data::ImplementationMap::const_iterator i(
1772 data_.services.find(specifier));
1773 if (i == data_.services.end()) {
1774 Data::NamedImplementations::const_iterator j(
1775 data_.namedImplementations.find(specifier));
1776 if (j == data_.namedImplementations.end()) {
1777 SAL_INFO("cppuhelper", "No implementation for " << specifier);
1778 return std::shared_ptr< Data::Implementation >();
1780 impl = j->second;
1781 } else {
1782 assert(!i->second.empty());
1783 SAL_INFO_IF(
1784 i->second.size() > 1, "cppuhelper",
1785 "Arbitrarily choosing " << i->second[0]->name
1786 << " among multiple implementations for " << i->first);
1787 impl = i->second[0];
1789 assert(impl);
1790 loaded = impl->status == Data::Implementation::STATUS_LOADED;
1792 if (!loaded) {
1793 loadImplementation(context, impl);
1795 return impl;
1798 /// Make a simpler unique name for preload / progress reporting.
1799 #ifndef DISABLE_DYNLOADING
1800 static OUString simplifyModule(const OUString &uri)
1802 sal_Int32 nIdx;
1803 OUStringBuffer edit(uri);
1804 if ((nIdx = edit.lastIndexOf('/')) > 0)
1805 edit.remove(0,nIdx+1);
1806 if ((nIdx = edit.lastIndexOf(':')) > 0)
1807 edit.remove(0,nIdx+1);
1808 if ((nIdx = edit.lastIndexOf("lo.so")) > 0)
1809 edit.truncate(nIdx);
1810 if ((nIdx = edit.lastIndexOf(".3")) > 0)
1811 edit.truncate(nIdx);
1812 if ((nIdx = edit.lastIndexOf("gcc3.so")) > 0)
1813 edit.truncate(nIdx);
1814 if ((nIdx = edit.lastIndexOf(".so")) > 0)
1815 edit.truncate(nIdx);
1816 if ((nIdx = edit.lastIndexOf("_uno")) > 0)
1817 edit.truncate(nIdx);
1818 if ((nIdx = edit.lastIndexOf(".jar")) > 0)
1819 edit.truncate(nIdx);
1820 if (edit.indexOf("lib") == 0)
1821 edit.remove(0,3);
1822 return edit.makeStringAndClear();
1824 #endif
1826 /// Used only by LibreOfficeKit when used by Online to pre-initialize
1827 void cppuhelper::ServiceManager::preloadImplementations() {
1828 #ifdef DISABLE_DYNLOADING
1829 abort();
1830 #else
1831 OUString aUri;
1832 osl::MutexGuard g(rBHelper.rMutex);
1833 css::uno::Environment aSourceEnv(css::uno::Environment::getCurrent());
1835 std::cerr << "preload:";
1836 std::vector<OUString> aReported;
1837 std::vector<OUString> aDisabled;
1838 OUStringBuffer aDisabledMsg;
1839 OUStringBuffer aMissingMsg;
1841 /// Allow external callers & testers to disable certain components
1842 const char *pDisable = getenv("UNODISABLELIBRARY");
1843 if (pDisable)
1845 OUString aDisable(pDisable, strlen(pDisable), RTL_TEXTENCODING_UTF8);
1846 for (sal_Int32 i = 0; i >= 0; )
1848 OUString tok = aDisable.getToken(0, ' ', i);
1849 tok = tok.trim();
1850 if (!tok.isEmpty())
1851 aDisabled.push_back(tok);
1855 // loop all implementations
1856 for (const auto& rEntry : data_.namedImplementations)
1858 if (rEntry.second->loader != "com.sun.star.loader.SharedLibrary" ||
1859 rEntry.second->status == Data::Implementation::STATUS_LOADED)
1860 continue;
1862 OUString simplified;
1865 const OUString &aLibrary = rEntry.second->uri;
1867 if (aLibrary.isEmpty())
1868 continue;
1870 simplified = simplifyModule(aLibrary);
1872 bool bDisabled =
1873 std::find(aDisabled.begin(), aDisabled.end(), simplified) != aDisabled.end();
1875 if (std::find(aReported.begin(), aReported.end(), aLibrary) == aReported.end())
1877 if (bDisabled)
1879 aDisabledMsg.append(simplified);
1880 aDisabledMsg.append(" ");
1882 else
1884 std::cerr << " " << simplified;
1885 std::cerr.flush();
1887 aReported.push_back(aLibrary);
1890 if (bDisabled)
1891 continue;
1893 // expand absolute URI implementation component library
1894 aUri = cppu::bootstrap_expandUri(aLibrary);
1896 catch (css::lang::IllegalArgumentException& aError)
1898 throw css::uno::DeploymentException(
1899 "Cannot expand URI" + rEntry.second->uri + ": " + aError.Message,
1900 static_cast< cppu::OWeakObject * >(this));
1903 // load component library
1904 osl::Module aModule(aUri, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL);
1906 if (!aModule.is())
1908 aMissingMsg.append(simplified);
1909 aMissingMsg.append(" ");
1912 if (aModule.is() &&
1913 !rEntry.second->environment.isEmpty())
1915 oslGenericFunction fpFactory;
1916 css::uno::Environment aTargetEnv;
1917 css::uno::Reference<css::uno::XInterface> xFactory;
1919 if(rEntry.second->constructorName.isEmpty())
1921 OUString aSymFactory;
1922 // expand full name component factory symbol
1923 if (rEntry.second->prefix == "direct")
1924 aSymFactory = rEntry.second->name.replace('.', '_') + "_" COMPONENT_GETFACTORY;
1925 else if (!rEntry.second->prefix.isEmpty())
1926 aSymFactory = rEntry.second->prefix + "_" COMPONENT_GETFACTORY;
1927 else
1928 aSymFactory = COMPONENT_GETFACTORY;
1930 // get function symbol component factory
1931 fpFactory = aModule.getFunctionSymbol(aSymFactory);
1932 if (fpFactory == nullptr)
1934 throw css::loader::CannotActivateFactoryException(
1935 ("no factory symbol \"" + aSymFactory + "\" in component library :" + aUri),
1936 css::uno::Reference<css::uno::XInterface>());
1939 aTargetEnv = cppuhelper::detail::getEnvironment(rEntry.second->environment, rEntry.second->name);
1940 component_getFactoryFunc fpComponentFactory = reinterpret_cast<component_getFactoryFunc>(fpFactory);
1942 if (aSourceEnv.get() == aTargetEnv.get())
1944 // invoke function component factory
1945 OString aImpl(OUStringToOString(rEntry.second->name, RTL_TEXTENCODING_ASCII_US));
1946 xFactory.set(css::uno::Reference<css::uno::XInterface>(static_cast<css::uno::XInterface *>(
1947 (*fpComponentFactory)(aImpl.getStr(), this, nullptr)), SAL_NO_ACQUIRE));
1950 else
1952 // get function symbol component factory
1953 aTargetEnv = cppuhelper::detail::getEnvironment(rEntry.second->environment, rEntry.second->name);
1954 fpFactory = (aSourceEnv.get() == aTargetEnv.get()) ?
1955 aModule.getFunctionSymbol(rEntry.second->constructorName) : nullptr;
1958 css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory;
1959 css::uno::Reference<css::lang::XSingleServiceFactory> xSSFactory;
1961 // query interface XSingleComponentFactory or XSingleServiceFactory
1962 if (xFactory.is())
1964 xSCFactory.set(xFactory, css::uno::UNO_QUERY);
1965 if (!xSCFactory.is())
1967 xSSFactory.set(xFactory, css::uno::UNO_QUERY);
1968 if (!xSSFactory.is())
1969 throw css::uno::DeploymentException(
1970 ("Implementation " + rEntry.second->name
1971 + " does not provide a constructor or factory"),
1972 static_cast< cppu::OWeakObject * >(this));
1976 if (!rEntry.second->constructorName.isEmpty() && fpFactory)
1977 rEntry.second->constructorFn = WrapperConstructorFn(reinterpret_cast<ImplementationConstructorFn *>(fpFactory));
1979 rEntry.second->factory1 = xSCFactory;
1980 rEntry.second->factory2 = xSSFactory;
1981 rEntry.second->status = Data::Implementation::STATUS_LOADED;
1985 // Some libraries use other (non-UNO) libraries requiring preinit
1986 oslGenericFunction fpPreload = aModule.getFunctionSymbol( "lok_preload_hook" );
1987 if (fpPreload)
1989 static std::vector<oslGenericFunction> aPreloaded;
1990 if (std::find(aPreloaded.begin(), aPreloaded.end(), fpPreload) == aPreloaded.end())
1992 aPreloaded.push_back(fpPreload);
1993 fpPreload();
1997 // leak aModule
1998 aModule.release();
2000 std::cerr << std::endl;
2002 if (aMissingMsg.getLength() > 0)
2004 OUString aMsg = aMissingMsg.makeStringAndClear();
2005 std::cerr << "Absent (often optional): " << aMsg << "\n";
2007 if (aDisabledMsg.getLength() > 0)
2009 OUString aMsg = aDisabledMsg.makeStringAndClear();
2010 std::cerr << "Disabled: " << aMsg << "\n";
2012 std::cerr.flush();
2014 // Various rather important uno mappings.
2015 static struct {
2016 const char *mpFrom;
2017 const char *mpTo;
2018 const char *mpPurpose;
2019 } const aMappingLoad[] = {
2020 { "gcc3", "uno", "" },
2021 { "uno", "gcc3", "" },
2024 static std::vector<css::uno::Mapping> maMaps;
2025 for (auto &it : aMappingLoad)
2027 maMaps.push_back(css::uno::Mapping(
2028 OUString::createFromAscii(it.mpFrom),
2029 OUString::createFromAscii(it.mpTo),
2030 OUString::createFromAscii(it.mpPurpose)));
2032 #endif
2035 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */