Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / cppuhelper / source / servicemanager.cxx
blobdd7139af252f9fdf3e698cf18876ec7bd891351d
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 <cppuhelper/bootstrap.hxx>
32 #include <cppuhelper/component_context.hxx>
33 #include <cppuhelper/implbase.hxx>
34 #include <cppuhelper/supportsservice.hxx>
35 #include <cppuhelper/factory.hxx>
36 #include <cppuhelper/shlib.hxx>
37 #include <osl/file.hxx>
38 #include <osl/module.hxx>
39 #include <rtl/ref.hxx>
40 #include <rtl/uri.hxx>
41 #include <rtl/ustring.hxx>
42 #include <rtl/strbuf.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 (cppuhelper::ServiceManager::Data::ImplementationMap::const_iterator i(
64 source.begin());
65 i != source.end(); ++i)
67 std::vector<
68 std::shared_ptr<
69 cppuhelper::ServiceManager::Data::Implementation > > & impls
70 = (*destination)[i->first];
71 impls.insert(impls.end(), i->second.begin(), i->second.end());
75 void removeFromImplementationMap(
76 cppuhelper::ServiceManager::Data::ImplementationMap * map,
77 std::vector< rtl::OUString > const & elements,
78 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
79 const & implementation)
81 // The underlying data structures make this function somewhat inefficient,
82 // but the assumption is that it is rarely called:
83 assert(map != nullptr);
84 for (std::vector< rtl::OUString >::const_iterator i(elements.begin());
85 i != elements.end(); ++i)
87 cppuhelper::ServiceManager::Data::ImplementationMap::iterator j(
88 map->find(*i));
89 assert(j != map->end());
90 std::vector<
91 std::shared_ptr<
92 cppuhelper::ServiceManager::Data::Implementation > >::iterator
93 k(std::find(j->second.begin(), j->second.end(), implementation));
94 assert(k != j->second.end());
95 j->second.erase(k);
96 if (j->second.empty()) {
97 map->erase(j);
102 // For simplicity, this code keeps throwing
103 // css::registry::InvalidRegistryException for invalid XML rdbs (even though
104 // that does not fit the exception's name):
105 class Parser {
106 public:
107 Parser(
108 rtl::OUString const & uri,
109 css::uno::Reference< css::uno::XComponentContext > const & alienContext,
110 cppuhelper::ServiceManager::Data * data);
112 Parser(const Parser&) = delete;
113 const Parser& operator=(const Parser&) = delete;
115 private:
116 void handleComponent();
118 void handleImplementation();
120 void handleService();
122 void handleSingleton();
124 rtl::OUString getNameAttribute();
126 xmlreader::XmlReader reader_;
127 css::uno::Reference< css::uno::XComponentContext > alienContext_;
128 cppuhelper::ServiceManager::Data * data_;
129 rtl::OUString attrLoader_;
130 rtl::OUString attrUri_;
131 rtl::OUString attrEnvironment_;
132 rtl::OUString attrPrefix_;
133 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
134 implementation_;
137 Parser::Parser(
138 rtl::OUString const & uri,
139 css::uno::Reference< css::uno::XComponentContext > const & alienContext,
140 cppuhelper::ServiceManager::Data * data):
141 reader_(uri), alienContext_(alienContext), data_(data)
143 assert(data != nullptr);
144 int ucNsId = reader_.registerNamespaceIri(
145 xmlreader::Span(
146 RTL_CONSTASCII_STRINGPARAM(
147 "http://openoffice.org/2010/uno-components")));
148 enum State {
149 STATE_BEGIN, STATE_END, STATE_COMPONENTS, STATE_COMPONENT_INITIAL,
150 STATE_COMPONENT, STATE_IMPLEMENTATION, STATE_SERVICE, STATE_SINGLETON };
151 for (State state = STATE_BEGIN;;) {
152 xmlreader::Span name;
153 int nsId;
154 xmlreader::XmlReader::Result res = reader_.nextItem(
155 xmlreader::XmlReader::Text::NONE, &name, &nsId);
156 switch (state) {
157 case STATE_BEGIN:
158 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
159 && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
161 state = STATE_COMPONENTS;
162 break;
164 throw css::registry::InvalidRegistryException(
165 reader_.getUrl() + ": unexpected item in outer level");
166 case STATE_END:
167 if (res == xmlreader::XmlReader::Result::Done) {
168 return;
170 throw css::registry::InvalidRegistryException(
171 reader_.getUrl() + ": unexpected item in outer level");
172 case STATE_COMPONENTS:
173 if (res == xmlreader::XmlReader::Result::End) {
174 state = STATE_END;
175 break;
177 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
178 && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
180 handleComponent();
181 state = STATE_COMPONENT_INITIAL;
182 break;
184 throw css::registry::InvalidRegistryException(
185 reader_.getUrl() + ": unexpected item in <components>");
186 case STATE_COMPONENT:
187 if (res == xmlreader::XmlReader::Result::End) {
188 state = STATE_COMPONENTS;
189 break;
191 SAL_FALLTHROUGH;
192 case STATE_COMPONENT_INITIAL:
193 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
194 && name.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
196 handleImplementation();
197 state = STATE_IMPLEMENTATION;
198 break;
200 throw css::registry::InvalidRegistryException(
201 reader_.getUrl() + ": unexpected item in <component>");
202 case STATE_IMPLEMENTATION:
203 if (res == xmlreader::XmlReader::Result::End) {
204 state = STATE_COMPONENT;
205 break;
207 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
208 && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
210 handleService();
211 state = STATE_SERVICE;
212 break;
214 if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
215 && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
217 handleSingleton();
218 state = STATE_SINGLETON;
219 break;
221 throw css::registry::InvalidRegistryException(
222 reader_.getUrl() + ": unexpected item in <implementation>");
223 case STATE_SERVICE:
224 if (res == xmlreader::XmlReader::Result::End) {
225 state = STATE_IMPLEMENTATION;
226 break;
228 throw css::registry::InvalidRegistryException(
229 reader_.getUrl() + ": unexpected item in <service>");
230 case STATE_SINGLETON:
231 if (res == xmlreader::XmlReader::Result::End) {
232 state = STATE_IMPLEMENTATION;
233 break;
235 throw css::registry::InvalidRegistryException(
236 reader_.getUrl() + ": unexpected item in <service>");
241 void Parser::handleComponent() {
242 attrLoader_ = rtl::OUString();
243 attrUri_ = rtl::OUString();
244 attrEnvironment_ = rtl::OUString();
245 attrPrefix_ = rtl::OUString();
246 xmlreader::Span name;
247 int nsId;
248 while (reader_.nextAttribute(&nsId, &name)) {
249 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
250 && name.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
252 if (!attrLoader_.isEmpty()) {
253 throw css::registry::InvalidRegistryException(
254 reader_.getUrl()
255 + ": <component> has multiple \"loader\" attributes");
257 attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8();
258 if (attrLoader_.isEmpty()) {
259 throw css::registry::InvalidRegistryException(
260 reader_.getUrl()
261 + ": <component> has empty \"loader\" attribute");
263 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
264 && name.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
266 if (!attrUri_.isEmpty()) {
267 throw css::registry::InvalidRegistryException(
268 reader_.getUrl()
269 + ": <component> has multiple \"uri\" attributes");
271 attrUri_ = reader_.getAttributeValue(false).convertFromUtf8();
272 if (attrUri_.isEmpty()) {
273 throw css::registry::InvalidRegistryException(
274 reader_.getUrl()
275 + ": <component> has empty \"uri\" attribute");
277 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
278 && name.equals(RTL_CONSTASCII_STRINGPARAM("environment")))
280 if (!attrEnvironment_.isEmpty()) {
281 throw css::registry::InvalidRegistryException(
282 reader_.getUrl() +
283 ": <component> has multiple \"environment\" attributes");
285 attrEnvironment_ = reader_.getAttributeValue(false)
286 .convertFromUtf8();
287 if (attrEnvironment_.isEmpty()) {
288 throw css::registry::InvalidRegistryException(
289 reader_.getUrl() +
290 ": <component> has empty \"environment\" attribute");
292 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
293 && name.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
295 if (!attrPrefix_.isEmpty()) {
296 throw css::registry::InvalidRegistryException(
297 reader_.getUrl() +
298 ": <component> has multiple \"prefix\" attributes");
300 attrPrefix_ = reader_.getAttributeValue(false).convertFromUtf8();
301 if (attrPrefix_.isEmpty()) {
302 throw css::registry::InvalidRegistryException(
303 reader_.getUrl() +
304 ": <component> has empty \"prefix\" attribute");
306 } else {
307 throw css::registry::InvalidRegistryException(
308 reader_.getUrl() + ": unexpected attribute \""
309 + name.convertFromUtf8() + "\" in <component>");
312 if (attrLoader_.isEmpty()) {
313 throw css::registry::InvalidRegistryException(
314 reader_.getUrl() + ": <component> is missing \"loader\" attribute");
316 if (attrUri_.isEmpty()) {
317 throw css::registry::InvalidRegistryException(
318 reader_.getUrl() + ": <component> is missing \"uri\" attribute");
320 #ifndef DISABLE_DYNLOADING
321 try {
322 attrUri_ = rtl::Uri::convertRelToAbs(reader_.getUrl(), attrUri_);
323 } catch (const rtl::MalformedUriException & e) {
324 throw css::registry::InvalidRegistryException(
325 reader_.getUrl() + ": bad \"uri\" attribute: " + e.getMessage());
327 #endif
330 void Parser::handleImplementation() {
331 rtl::OUString attrName;
332 rtl::OUString attrConstructor;
333 xmlreader::Span name;
334 int nsId;
335 while (reader_.nextAttribute(&nsId, &name)) {
336 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
337 && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
339 if (!attrName.isEmpty()) {
340 throw css::registry::InvalidRegistryException(
341 reader_.getUrl()
342 + ": <implementation> has multiple \"name\" attributes");
344 attrName = reader_.getAttributeValue(false).convertFromUtf8();
345 if (attrName.isEmpty()) {
346 throw css::registry::InvalidRegistryException(
347 reader_.getUrl()
348 + ": <implementation> has empty \"name\" attribute");
350 } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
351 && name.equals(RTL_CONSTASCII_STRINGPARAM("constructor")))
353 if (!attrConstructor.isEmpty()) {
354 throw css::registry::InvalidRegistryException(
355 reader_.getUrl()
356 + ": <implementation> has multiple \"constructor\""
357 " attributes");
359 attrConstructor = reader_.getAttributeValue(false)
360 .convertFromUtf8();
361 if (attrConstructor.isEmpty()) {
362 throw css::registry::InvalidRegistryException(
363 reader_.getUrl()
364 + ": element has empty \"constructor\" attribute");
366 if (attrEnvironment_.isEmpty()) {
367 throw css::registry::InvalidRegistryException(
368 reader_.getUrl()
369 + ": <implementation> has \"constructor\" attribute but"
370 " <component> has no \"environment\" attribute");
372 } else {
373 throw css::registry::InvalidRegistryException(
374 reader_.getUrl() + ": unexpected element attribute \""
375 + name.convertFromUtf8() + "\" in <implementation>");
378 if (attrName.isEmpty()) {
379 throw css::registry::InvalidRegistryException(
380 reader_.getUrl()
381 + ": <implementation> is missing \"name\" attribute");
383 implementation_.reset(
384 new cppuhelper::ServiceManager::Data::Implementation(
385 attrName, attrLoader_, attrUri_, attrEnvironment_, attrConstructor,
386 attrPrefix_, alienContext_, reader_.getUrl()));
387 if (!data_->namedImplementations.emplace(attrName, implementation_).
388 second)
390 throw css::registry::InvalidRegistryException(
391 reader_.getUrl() + ": duplicate <implementation name=\"" + attrName
392 + "\">");
396 void Parser::handleService() {
397 rtl::OUString name(getNameAttribute());
398 implementation_->info->services.push_back(name);
399 data_->services[name].push_back(implementation_);
402 void Parser::handleSingleton() {
403 rtl::OUString name(getNameAttribute());
404 implementation_->info->singletons.push_back(name);
405 data_->singletons[name].push_back(implementation_);
408 rtl::OUString Parser::getNameAttribute() {
409 rtl::OUString attrName;
410 xmlreader::Span name;
411 int nsId;
412 while (reader_.nextAttribute(&nsId, &name)) {
413 if (nsId != xmlreader::XmlReader::NAMESPACE_NONE
414 || !name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
416 throw css::registry::InvalidRegistryException(
417 reader_.getUrl() + ": expected element attribute \"name\"");
419 if (!attrName.isEmpty()) {
420 throw css::registry::InvalidRegistryException(
421 reader_.getUrl()
422 + ": element has multiple \"name\" attributes");
424 attrName = reader_.getAttributeValue(false).convertFromUtf8();
425 if (attrName.isEmpty()) {
426 throw css::registry::InvalidRegistryException(
427 reader_.getUrl() + ": element has empty \"name\" attribute");
430 if (attrName.isEmpty()) {
431 throw css::registry::InvalidRegistryException(
432 reader_.getUrl() + ": element is missing \"name\" attribute");
434 return attrName;
437 class ContentEnumeration:
438 public cppu::WeakImplHelper< css::container::XEnumeration >
440 public:
441 explicit ContentEnumeration(std::vector< css::uno::Any > const & factories):
442 factories_(factories), iterator_(factories_.begin()) {}
444 ContentEnumeration(const ContentEnumeration&) = delete;
445 const ContentEnumeration& operator=(const ContentEnumeration&) = delete;
447 private:
448 virtual ~ContentEnumeration() override {}
450 virtual sal_Bool SAL_CALL hasMoreElements() override;
452 virtual css::uno::Any SAL_CALL nextElement() override;
454 osl::Mutex mutex_;
455 std::vector< css::uno::Any > factories_;
456 std::vector< css::uno::Any >::const_iterator iterator_;
459 sal_Bool ContentEnumeration::hasMoreElements()
461 osl::MutexGuard g(mutex_);
462 return iterator_ != factories_.end();
465 css::uno::Any ContentEnumeration::nextElement()
467 osl::MutexGuard g(mutex_);
468 if (iterator_ == factories_.end()) {
469 throw css::container::NoSuchElementException(
470 "Bootstrap service manager service enumerator has no more elements",
471 static_cast< cppu::OWeakObject * >(this));
473 return *iterator_++;
476 css::beans::Property getDefaultContextProperty() {
477 return css::beans::Property(
478 "DefaultContext", -1,
479 cppu::UnoType< css::uno::XComponentContext >::get(),
480 css::beans::PropertyAttribute::READONLY);
483 class SingletonFactory:
484 public cppu::WeakImplHelper<css::lang::XSingleComponentFactory>
486 public:
487 SingletonFactory(
488 rtl::Reference< cppuhelper::ServiceManager > const & manager,
489 std::shared_ptr<
490 cppuhelper::ServiceManager::Data::Implementation > const &
491 implementation):
492 manager_(manager), implementation_(implementation)
493 { assert(manager.is()); assert(implementation.get() != nullptr); }
495 SingletonFactory(const SingletonFactory&) = delete;
496 const SingletonFactory& operator=(const SingletonFactory&) = delete;
498 private:
499 virtual ~SingletonFactory() override {}
501 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
502 createInstanceWithContext(
503 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
505 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
506 createInstanceWithArgumentsAndContext(
507 css::uno::Sequence< css::uno::Any > const & Arguments,
508 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
510 rtl::Reference< cppuhelper::ServiceManager > manager_;
511 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
512 implementation_;
515 css::uno::Reference< css::uno::XInterface >
516 SingletonFactory::createInstanceWithContext(
517 css::uno::Reference< css::uno::XComponentContext > const & Context)
519 manager_->loadImplementation(Context, implementation_);
520 return implementation_->createInstance(Context, true);
523 css::uno::Reference< css::uno::XInterface >
524 SingletonFactory::createInstanceWithArgumentsAndContext(
525 css::uno::Sequence< css::uno::Any > const & Arguments,
526 css::uno::Reference< css::uno::XComponentContext > const & Context)
528 manager_->loadImplementation(Context, implementation_);
529 return implementation_->createInstanceWithArguments(
530 Context, true, Arguments);
533 class ImplementationWrapper:
534 public cppu::WeakImplHelper<
535 css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
536 css::lang::XServiceInfo >
538 public:
539 ImplementationWrapper(
540 rtl::Reference< cppuhelper::ServiceManager > const & manager,
541 std::shared_ptr<
542 cppuhelper::ServiceManager::Data::Implementation > const &
543 implementation):
544 manager_(manager), implementation_(implementation)
545 { assert(manager.is()); assert(implementation.get() != nullptr); }
547 ImplementationWrapper(const ImplementationWrapper&) = delete;
548 const ImplementationWrapper& operator=(const ImplementationWrapper&) = delete;
550 private:
551 virtual ~ImplementationWrapper() override {}
553 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
554 createInstanceWithContext(
555 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
557 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
558 createInstanceWithArgumentsAndContext(
559 css::uno::Sequence< css::uno::Any > const & Arguments,
560 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
562 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
563 createInstance() override;
565 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
566 createInstanceWithArguments(
567 css::uno::Sequence< css::uno::Any > const & Arguments) override;
569 virtual rtl::OUString SAL_CALL getImplementationName() override;
571 virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName) override;
573 virtual css::uno::Sequence< rtl::OUString > SAL_CALL
574 getSupportedServiceNames() override;
576 rtl::Reference< cppuhelper::ServiceManager > manager_;
577 std::weak_ptr< cppuhelper::ServiceManager::Data::Implementation >
578 implementation_;
581 css::uno::Reference< css::uno::XInterface >
582 ImplementationWrapper::createInstanceWithContext(
583 css::uno::Reference< css::uno::XComponentContext > const & Context)
585 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
586 assert(impl);
587 manager_->loadImplementation(Context, impl);
588 return impl->createInstance(Context, false);
591 css::uno::Reference< css::uno::XInterface >
592 ImplementationWrapper::createInstanceWithArgumentsAndContext(
593 css::uno::Sequence< css::uno::Any > const & Arguments,
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->createInstanceWithArguments(
600 Context, false, Arguments);
603 css::uno::Reference< css::uno::XInterface >
604 ImplementationWrapper::createInstance()
606 return createInstanceWithContext(manager_->getContext());
609 css::uno::Reference< css::uno::XInterface >
610 ImplementationWrapper::createInstanceWithArguments(
611 css::uno::Sequence< css::uno::Any > const & Arguments)
613 return createInstanceWithArgumentsAndContext(
614 Arguments, manager_->getContext());
617 rtl::OUString ImplementationWrapper::getImplementationName()
619 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
620 assert(impl);
621 return impl->info->name;
624 sal_Bool ImplementationWrapper::supportsService(rtl::OUString const & ServiceName)
626 return cppu::supportsService(this, ServiceName);
629 css::uno::Sequence< rtl::OUString >
630 ImplementationWrapper::getSupportedServiceNames()
632 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
633 assert(impl);
634 if (impl->info->services.size()
635 > static_cast< sal_uInt32 >(SAL_MAX_INT32))
637 throw css::uno::RuntimeException(
638 ("Implementation " + impl->info->name
639 + " supports too many services"),
640 static_cast< cppu::OWeakObject * >(this));
642 css::uno::Sequence< rtl::OUString > names(
643 static_cast< sal_Int32 >(impl->info->services.size()));
644 sal_Int32 i = 0;
645 for (std::vector< rtl::OUString >::const_iterator j(
646 impl->info->services.begin());
647 j != impl->info->services.end(); ++j)
649 names[i++] = *j;
651 return names;
656 css::uno::Reference<css::uno::XInterface>
657 cppuhelper::ServiceManager::Data::Implementation::createInstance(
658 css::uno::Reference<css::uno::XComponentContext> const & context,
659 bool singletonRequest)
661 css::uno::Reference<css::uno::XInterface> inst;
662 if (constructor) {
663 inst.set(
664 constructor(context.get(), css::uno::Sequence<css::uno::Any>()),
665 SAL_NO_ACQUIRE);
666 } else if (factory1.is()) {
667 inst = factory1->createInstanceWithContext(context);
668 } else {
669 assert(factory2.is());
670 inst = factory2->createInstance();
672 updateDisposeSingleton(singletonRequest, inst);
673 return inst;
676 css::uno::Reference<css::uno::XInterface>
677 cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
678 css::uno::Reference<css::uno::XComponentContext> const & context,
679 bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
681 css::uno::Reference<css::uno::XInterface> inst;
682 if (constructor) {
683 inst.set(constructor(context.get(), arguments), SAL_NO_ACQUIRE);
684 //HACK: The constructor will either observe arguments and return inst
685 // that does not implement XInitialization (or null), or ignore
686 // arguments and return inst that implements XInitialization; this
687 // should be removed again once XInitialization-based implementations
688 // have become rare:
689 css::uno::Reference<css::lang::XInitialization> init(
690 inst, css::uno::UNO_QUERY);
691 if (init.is()) {
692 init->initialize(arguments);
694 } else if (factory1.is()) {
695 inst = factory1->createInstanceWithArgumentsAndContext(
696 arguments, context);
697 } else {
698 assert(factory2.is());
699 inst = factory2->createInstanceWithArguments(arguments);
701 updateDisposeSingleton(singletonRequest, inst);
702 return inst;
705 void cppuhelper::ServiceManager::Data::Implementation::updateDisposeSingleton(
706 bool singletonRequest,
707 css::uno::Reference<css::uno::XInterface> const & instance)
709 // This is an optimization, to only call dispose once (from the component
710 // context) on a singleton that is obtained both via the component context
711 // and via the service manager; however, there is a harmless race here that
712 // may cause two calls to dispose nevertheless (also, this calls dispose on
713 // at most one of the instances obtained via the service manager, in case
714 // the implementation hands out different instances):
715 if (singletonRequest) {
716 osl::MutexGuard g(mutex);
717 disposeSingleton.clear();
718 dispose = false;
719 } else if (!info->singletons.empty()) {
720 css::uno::Reference<css::lang::XComponent> comp(
721 instance, css::uno::UNO_QUERY);
722 if (comp.is()) {
723 osl::MutexGuard g(mutex);
724 if (dispose) {
725 disposeSingleton = comp;
731 void cppuhelper::ServiceManager::addSingletonContextEntries(
732 std::vector< cppu::ContextEntry_Init > * entries)
734 assert(entries != nullptr);
735 for (Data::ImplementationMap::const_iterator i(data_.singletons.begin());
736 i != data_.singletons.end(); ++i)
738 assert(!i->second.empty());
739 assert(i->second[0].get() != nullptr);
740 SAL_INFO_IF(
741 i->second.size() > 1, "cppuhelper",
742 "Arbitrarily choosing " << i->second[0]->info->name
743 << " among multiple implementations for " << i->first);
744 entries->push_back(
745 cppu::ContextEntry_Init(
746 "/singletons/" + i->first,
747 css::uno::makeAny<
748 css::uno::Reference<css::lang::XSingleComponentFactory> >(
749 new SingletonFactory(this, i->second[0])),
750 true));
754 void cppuhelper::ServiceManager::loadImplementation(
755 css::uno::Reference< css::uno::XComponentContext > const & context,
756 std::shared_ptr< Data::Implementation > const & implementation)
758 assert(implementation.get() != nullptr);
760 osl::MutexGuard g(rBHelper.rMutex);
761 if (implementation->status == Data::Implementation::STATUS_LOADED) {
762 return;
765 rtl::OUString uri;
766 try {
767 uri = cppu::bootstrap_expandUri(implementation->info->uri);
768 } catch (css::lang::IllegalArgumentException & e) {
769 throw css::uno::DeploymentException(
770 "Cannot expand URI" + implementation->info->uri + ": " + e.Message,
771 static_cast< cppu::OWeakObject * >(this));
773 cppuhelper::WrapperConstructorFn ctor;
774 css::uno::Reference< css::uno::XInterface > f0;
775 // Special handling of SharedLibrary loader, with support for environment,
776 // constructor, and prefix arguments:
777 if (!implementation->info->alienContext.is()
778 && implementation->info->loader == "com.sun.star.loader.SharedLibrary")
780 cppuhelper::detail::loadSharedLibComponentFactory(
781 uri, implementation->info->environment,
782 implementation->info->prefix, implementation->info->name,
783 implementation->info->constructor, this, &ctor, &f0);
784 if (ctor) {
785 assert(!implementation->info->environment.isEmpty());
787 } else {
788 SAL_WARN_IF(
789 !implementation->info->environment.isEmpty(), "cppuhelper",
790 "Loader " << implementation->info->loader
791 << " and non-empty environment "
792 << implementation->info->environment);
793 SAL_WARN_IF(
794 !implementation->info->prefix.isEmpty(), "cppuhelper",
795 "Loader " << implementation->info->loader
796 << " and non-empty constructor "
797 << implementation->info->constructor);
798 SAL_WARN_IF(
799 !implementation->info->prefix.isEmpty(), "cppuhelper",
800 "Loader " << implementation->info->loader
801 << " and non-empty prefix " << implementation->info->prefix);
802 css::uno::Reference< css::uno::XComponentContext > ctxt;
803 css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
804 if (implementation->info->alienContext.is()) {
805 ctxt = implementation->info->alienContext;
806 smgr.set(ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
807 } else {
808 assert(context.is());
809 ctxt = context;
810 smgr = this;
812 css::uno::Reference< css::loader::XImplementationLoader > loader(
813 smgr->createInstanceWithContext(implementation->info->loader, ctxt),
814 css::uno::UNO_QUERY_THROW);
815 f0 = loader->activate(
816 implementation->info->name, rtl::OUString(), uri,
817 css::uno::Reference< css::registry::XRegistryKey >());
819 css::uno::Reference<css::lang::XSingleComponentFactory> f1;
820 css::uno::Reference<css::lang::XSingleServiceFactory> f2;
821 if (!ctor) {
822 f1.set(f0, css::uno::UNO_QUERY);
823 if (!f1.is()) {
824 f2.set(f0, css::uno::UNO_QUERY);
825 if (!f2.is()) {
826 throw css::uno::DeploymentException(
827 ("Implementation " + implementation->info->name
828 + " does not provide a constructor or factory"),
829 static_cast< cppu::OWeakObject * >(this));
833 //TODO: There is a race here, as the relevant service factory can be removed
834 // while the mutex is unlocked and loading can thus fail, as the entity from
835 // which to load can disappear once the service factory is removed.
836 osl::MutexGuard g(rBHelper.rMutex);
837 if (!(isDisposed()
838 || implementation->status == Data::Implementation::STATUS_LOADED))
840 implementation->status = Data::Implementation::STATUS_LOADED;
841 implementation->constructor = ctor;
842 implementation->factory1 = f1;
843 implementation->factory2 = f2;
847 void cppuhelper::ServiceManager::disposing() {
848 std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
849 std::vector< css::uno::Reference< css::lang::XComponent > > comps;
850 Data clear;
852 osl::MutexGuard g(rBHelper.rMutex);
853 for (Data::NamedImplementations::const_iterator i(
854 data_.namedImplementations.begin());
855 i != data_.namedImplementations.end(); ++i)
857 assert(i->second.get() != nullptr);
858 if (!i->second->info->singletons.empty()) {
859 osl::MutexGuard g2(i->second->mutex);
860 if (i->second->disposeSingleton.is()) {
861 sngls.push_back(i->second->disposeSingleton);
865 for (Data::DynamicImplementations::const_iterator i(
866 data_.dynamicImplementations.begin());
867 i != data_.dynamicImplementations.end(); ++i)
869 assert(i->second.get() != nullptr);
870 if (!i->second->info->singletons.empty()) {
871 osl::MutexGuard g2(i->second->mutex);
872 if (i->second->disposeSingleton.is()) {
873 sngls.push_back(i->second->disposeSingleton);
876 if (i->second->component.is()) {
877 comps.push_back(i->second->component);
880 data_.namedImplementations.swap(clear.namedImplementations);
881 data_.dynamicImplementations.swap(clear.dynamicImplementations);
882 data_.services.swap(clear.services);
883 data_.singletons.swap(clear.singletons);
885 for (std::vector<
886 css::uno::Reference<css::lang::XComponent> >::const_iterator i(
887 sngls.begin());
888 i != sngls.end(); ++i)
890 try {
891 (*i)->dispose();
892 } catch (css::uno::RuntimeException & e) {
893 SAL_WARN("cppuhelper", "Ignoring " << e << " while disposing singleton");
896 for (std::vector<
897 css::uno::Reference< css::lang::XComponent > >::const_iterator i(
898 comps.begin());
899 i != comps.end(); ++i)
901 removeEventListenerFromComponent(*i);
905 void cppuhelper::ServiceManager::initialize(
906 css::uno::Sequence<css::uno::Any> const & aArguments)
908 OUString arg;
909 if (aArguments.getLength() != 1 || !(aArguments[0] >>= arg)
910 || arg != "preload")
912 throw css::lang::IllegalArgumentException(
913 "invalid ServiceManager::initialize argument",
914 css::uno::Reference<css::uno::XInterface>(), 0);
916 preloadImplementations();
919 rtl::OUString cppuhelper::ServiceManager::getImplementationName()
921 return rtl::OUString(
922 "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager");
925 sal_Bool cppuhelper::ServiceManager::supportsService(
926 rtl::OUString const & ServiceName)
928 return cppu::supportsService(this, ServiceName);
931 css::uno::Sequence< rtl::OUString >
932 cppuhelper::ServiceManager::getSupportedServiceNames()
934 css::uno::Sequence< rtl::OUString > names(2);
935 names[0] = "com.sun.star.lang.MultiServiceFactory";
936 names[1] = "com.sun.star.lang.ServiceManager";
937 return names;
940 css::uno::Reference< css::uno::XInterface >
941 cppuhelper::ServiceManager::createInstance(
942 rtl::OUString const & aServiceSpecifier)
944 assert(context_.is());
945 return createInstanceWithContext(aServiceSpecifier, context_);
948 css::uno::Reference< css::uno::XInterface >
949 cppuhelper::ServiceManager::createInstanceWithArguments(
950 rtl::OUString const & ServiceSpecifier,
951 css::uno::Sequence< css::uno::Any > const & Arguments)
953 assert(context_.is());
954 return createInstanceWithArgumentsAndContext(
955 ServiceSpecifier, Arguments, context_);
958 css::uno::Sequence< rtl::OUString >
959 cppuhelper::ServiceManager::getAvailableServiceNames()
961 osl::MutexGuard g(rBHelper.rMutex);
962 if (isDisposed()) {
963 return css::uno::Sequence< rtl::OUString >();
965 Data::ImplementationMap::size_type n = data_.services.size();
966 if (n > static_cast< sal_uInt32 >(SAL_MAX_INT32)) {
967 throw css::uno::RuntimeException(
968 "getAvailableServiceNames: too many services",
969 static_cast< cppu::OWeakObject * >(this));
971 css::uno::Sequence< rtl::OUString > names(static_cast< sal_Int32 >(n));
972 sal_Int32 i = 0;
973 for (Data::ImplementationMap::const_iterator j(data_.services.begin());
974 j != data_.services.end(); ++j)
976 names[i++] = j->first;
978 assert(i == names.getLength());
979 return names;
982 css::uno::Reference< css::uno::XInterface >
983 cppuhelper::ServiceManager::createInstanceWithContext(
984 rtl::OUString const & aServiceSpecifier,
985 css::uno::Reference< css::uno::XComponentContext > const & Context)
987 std::shared_ptr< Data::Implementation > impl(
988 findServiceImplementation(Context, aServiceSpecifier));
989 return impl.get() == nullptr
990 ? css::uno::Reference< css::uno::XInterface >()
991 : impl->createInstance(Context, false);
994 css::uno::Reference< css::uno::XInterface >
995 cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
996 rtl::OUString const & ServiceSpecifier,
997 css::uno::Sequence< css::uno::Any > const & Arguments,
998 css::uno::Reference< css::uno::XComponentContext > const & Context)
1000 std::shared_ptr< Data::Implementation > impl(
1001 findServiceImplementation(Context, ServiceSpecifier));
1002 return impl.get() == nullptr
1003 ? css::uno::Reference< css::uno::XInterface >()
1004 : impl->createInstanceWithArguments(Context, false, Arguments);
1007 css::uno::Type cppuhelper::ServiceManager::getElementType()
1009 return css::uno::Type();
1012 sal_Bool cppuhelper::ServiceManager::hasElements()
1014 osl::MutexGuard g(rBHelper.rMutex);
1015 return
1016 !(data_.namedImplementations.empty()
1017 && data_.dynamicImplementations.empty());
1020 css::uno::Reference< css::container::XEnumeration >
1021 cppuhelper::ServiceManager::createEnumeration()
1023 throw css::uno::RuntimeException(
1024 "ServiceManager createEnumeration: method not supported",
1025 static_cast< cppu::OWeakObject * >(this));
1028 sal_Bool cppuhelper::ServiceManager::has(css::uno::Any const &)
1030 throw css::uno::RuntimeException(
1031 "ServiceManager has: method not supported",
1032 static_cast< cppu::OWeakObject * >(this));
1035 void cppuhelper::ServiceManager::insert(css::uno::Any const & aElement)
1037 css::uno::Sequence< css::beans::NamedValue > args;
1038 if (aElement >>= args) {
1039 std::vector< rtl::OUString > uris;
1040 css::uno::Reference< css::uno::XComponentContext > alienContext;
1041 for (sal_Int32 i = 0; i < args.getLength(); ++i) {
1042 if (args[i].Name == "uri") {
1043 rtl::OUString uri;
1044 if (!(args[i].Value >>= uri)) {
1045 throw css::lang::IllegalArgumentException(
1046 "Bad uri argument",
1047 static_cast< cppu::OWeakObject * >(this), 0);
1049 uris.push_back(uri);
1050 } else if (args[i].Name == "component-context") {
1051 if (alienContext.is()) {
1052 throw css::lang::IllegalArgumentException(
1053 "Multiple component-context arguments",
1054 static_cast< cppu::OWeakObject * >(this), 0);
1056 if (!(args[i].Value >>= alienContext) || !alienContext.is()) {
1057 throw css::lang::IllegalArgumentException(
1058 "Bad component-context argument",
1059 static_cast< cppu::OWeakObject * >(this), 0);
1061 } else {
1062 throw css::lang::IllegalArgumentException(
1063 "Bad argument " + args[i].Name,
1064 static_cast< cppu::OWeakObject * >(this), 0);
1067 insertRdbFiles(uris, alienContext);
1068 return;
1070 css::uno::Reference< css::lang::XServiceInfo > info;
1071 if ((aElement >>= info) && info.is()) {
1072 insertLegacyFactory(info);
1073 return;
1075 // At least revisions up to 1.7 of LanguageTool.oxt (incl. the bundled 1.4.0 in
1076 // module languagetool) contain an (actively registered) factory that does not
1077 // implement XServiceInfo (see <http://sourceforge.net/tracker/?
1078 // func=detail&aid=3526635&group_id=110216&atid=655717> "SingletonFactory should
1079 // implement XServiceInfo"); the old OServiceManager::insert
1080 // (stoc/source/servicemanager/servicemanager.cxx) silently did not add such
1081 // broken factories to its m_ImplementationNameMap, so ignore them here for
1082 // backwards compatibility of live-insertion of extensions, too.
1084 // (The plan was that this warning would go away (and we would do the
1085 // throw instead) for the incompatible LO 4, but we changed our mind):
1086 css::uno::Reference< css::lang::XSingleComponentFactory > legacy;
1087 if ((aElement >>= legacy) && legacy.is()) {
1088 SAL_WARN(
1089 "cppuhelper",
1090 "Ignored XSingleComponentFactory not implementing XServiceInfo");
1091 return;
1094 throw css::lang::IllegalArgumentException(
1095 "Bad insert element", static_cast< cppu::OWeakObject * >(this), 0);
1098 void cppuhelper::ServiceManager::remove(css::uno::Any const & aElement)
1100 css::uno::Sequence< css::beans::NamedValue > args;
1101 if (aElement >>= args) {
1102 std::vector< rtl::OUString > uris;
1103 for (sal_Int32 i = 0; i < args.getLength(); ++i) {
1104 if (args[i].Name != "uri") {
1105 throw css::lang::IllegalArgumentException(
1106 "Bad argument " + args[i].Name,
1107 static_cast< cppu::OWeakObject * >(this), 0);
1108 } rtl::OUString uri;
1109 if (!(args[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 rtl::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 rtl::OUString const & aServiceName)
1142 std::vector< std::shared_ptr< Data::Implementation > > impls;
1144 osl::MutexGuard g(rBHelper.rMutex);
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 (std::vector<
1153 std::shared_ptr< Data::Implementation > >::const_iterator i(
1154 impls.begin());
1155 i != impls.end(); ++i)
1157 Data::Implementation * impl = i->get();
1158 assert(impl != nullptr);
1160 osl::MutexGuard g(rBHelper.rMutex);
1161 if (isDisposed()) {
1162 factories.clear();
1163 break;
1165 if (impl->status == Data::Implementation::STATUS_NEW) {
1166 // Postpone actual implementation instantiation as long as
1167 // possible (so that e.g. opening LO's "Tools - Macros" menu
1168 // does not try to instantiate a JVM, which can lead to a
1169 // synchronous error dialog when no JVM is specified, and
1170 // showing the dialog while hovering over a menu can cause
1171 // trouble):
1172 impl->factory1 = new ImplementationWrapper(this, *i);
1173 impl->status = Data::Implementation::STATUS_WRAPPER;
1175 if (impl->constructor != nullptr && !impl->factory1.is()) {
1176 impl->factory1 = new ImplementationWrapper(this, *i);
1179 if (impl->factory1.is()) {
1180 factories.push_back(css::uno::Any(impl->factory1));
1181 } else {
1182 assert(impl->factory2.is());
1183 factories.push_back(css::uno::Any(impl->factory2));
1186 return new ContentEnumeration(factories);
1189 css::uno::Reference< css::beans::XPropertySetInfo >
1190 cppuhelper::ServiceManager::getPropertySetInfo()
1192 return this;
1195 void cppuhelper::ServiceManager::setPropertyValue(
1196 rtl::OUString const & aPropertyName, css::uno::Any const &)
1198 if (aPropertyName == "DefaultContext") {
1199 throw css::beans::PropertyVetoException(
1200 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1201 } else {
1202 throw css::beans::UnknownPropertyException(
1203 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1207 css::uno::Any cppuhelper::ServiceManager::getPropertyValue(
1208 rtl::OUString const & PropertyName)
1210 if (PropertyName != "DefaultContext") {
1211 throw css::beans::UnknownPropertyException(
1212 PropertyName, static_cast< cppu::OWeakObject * >(this));
1214 assert(context_.is());
1215 return css::uno::Any(context_);
1218 void cppuhelper::ServiceManager::addPropertyChangeListener(
1219 rtl::OUString const & aPropertyName,
1220 css::uno::Reference< css::beans::XPropertyChangeListener > const &
1221 xListener)
1223 if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1224 throw css::beans::UnknownPropertyException(
1225 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1227 // DefaultContext does not change, so just treat it as an event listener:
1228 return addEventListener(xListener);
1231 void cppuhelper::ServiceManager::removePropertyChangeListener(
1232 rtl::OUString const & aPropertyName,
1233 css::uno::Reference< css::beans::XPropertyChangeListener > const &
1234 aListener)
1236 if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1237 throw css::beans::UnknownPropertyException(
1238 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1240 // DefaultContext does not change, so just treat it as an event listener:
1241 return removeEventListener(aListener);
1244 void cppuhelper::ServiceManager::addVetoableChangeListener(
1245 rtl::OUString const & PropertyName,
1246 css::uno::Reference< css::beans::XVetoableChangeListener > const &
1247 aListener)
1249 if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1250 throw css::beans::UnknownPropertyException(
1251 PropertyName, static_cast< cppu::OWeakObject * >(this));
1253 // DefaultContext does not change, so just treat it as an event listener:
1254 return addEventListener(aListener);
1257 void cppuhelper::ServiceManager::removeVetoableChangeListener(
1258 rtl::OUString const & PropertyName,
1259 css::uno::Reference< css::beans::XVetoableChangeListener > const &
1260 aListener)
1262 if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1263 throw css::beans::UnknownPropertyException(
1264 PropertyName, static_cast< cppu::OWeakObject * >(this));
1266 // DefaultContext does not change, so just treat it as an event listener:
1267 return removeEventListener(aListener);
1270 css::uno::Sequence< css::beans::Property >
1271 cppuhelper::ServiceManager::getProperties() {
1272 css::uno::Sequence< css::beans::Property > props(1);
1273 props[0] = getDefaultContextProperty();
1274 return props;
1277 css::beans::Property cppuhelper::ServiceManager::getPropertyByName(
1278 rtl::OUString const & aName)
1280 if (aName != "DefaultContext") {
1281 throw css::beans::UnknownPropertyException(
1282 aName, static_cast< cppu::OWeakObject * >(this));
1284 return getDefaultContextProperty();
1287 sal_Bool cppuhelper::ServiceManager::hasPropertyByName(
1288 rtl::OUString const & Name)
1290 return Name == "DefaultContext";
1293 cppuhelper::ServiceManager::~ServiceManager() {}
1295 void cppuhelper::ServiceManager::disposing(
1296 css::lang::EventObject const & Source)
1298 removeLegacyFactory(
1299 css::uno::Reference< css::lang::XServiceInfo >(
1300 Source.Source, css::uno::UNO_QUERY_THROW),
1301 false);
1304 void cppuhelper::ServiceManager::removeEventListenerFromComponent(
1305 css::uno::Reference< css::lang::XComponent > const & component)
1307 assert(component.is());
1308 try {
1309 component->removeEventListener(this);
1310 } catch (css::uno::RuntimeException & e) {
1311 SAL_INFO(
1312 "cppuhelper",
1313 "Ignored removeEventListener RuntimeException " + e.Message);
1317 void cppuhelper::ServiceManager::init(rtl::OUString const & rdbUris) {
1318 for (sal_Int32 i = 0; i != -1;) {
1319 rtl::OUString uri(rdbUris.getToken(0, ' ', i));
1320 if (uri.isEmpty()) {
1321 continue;
1323 bool optional;
1324 bool directory;
1325 cppu::decodeRdbUri(&uri, &optional, &directory);
1326 if (directory) {
1327 readRdbDirectory(uri, optional);
1328 } else {
1329 readRdbFile(uri, optional);
1334 void cppuhelper::ServiceManager::readRdbDirectory(
1335 rtl::OUString const & uri, bool optional)
1337 osl::Directory dir(uri);
1338 switch (dir.open()) {
1339 case osl::FileBase::E_None:
1340 break;
1341 case osl::FileBase::E_NOENT:
1342 if (optional) {
1343 SAL_INFO("cppuhelper", "Ignored optional " << uri);
1344 return;
1346 SAL_FALLTHROUGH;
1347 default:
1348 throw css::uno::DeploymentException(
1349 "Cannot open directory " + uri,
1350 static_cast< cppu::OWeakObject * >(this));
1352 for (;;) {
1353 rtl::OUString url;
1354 if (!cppu::nextDirectoryItem(dir, &url)) {
1355 break;
1357 readRdbFile(url, false);
1361 void cppuhelper::ServiceManager::readRdbFile(
1362 rtl::OUString const & uri, bool optional)
1364 try {
1365 Parser(
1366 uri, css::uno::Reference< css::uno::XComponentContext >(), &data_);
1367 } catch (css::container::NoSuchElementException &) {
1368 if (!optional) {
1369 throw css::uno::DeploymentException(
1370 uri + ": no such file",
1371 static_cast< cppu::OWeakObject * >(this));
1373 SAL_INFO("cppuhelper", "Ignored optional " << uri);
1374 } catch (css::registry::InvalidRegistryException & e) {
1375 if (!readLegacyRdbFile(uri)) {
1376 throw css::uno::DeploymentException(
1377 "InvalidRegistryException: " + e.Message,
1378 static_cast< cppu::OWeakObject * >(this));
1380 } catch (css::uno::RuntimeException &) {
1381 if (!readLegacyRdbFile(uri)) {
1382 throw;
1387 bool cppuhelper::ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) {
1388 Registry reg;
1389 switch (reg.open(uri, RegAccessMode::READONLY)) {
1390 case RegError::NO_ERROR:
1391 break;
1392 case RegError::REGISTRY_NOT_EXISTS:
1393 case RegError::INVALID_REGISTRY:
1395 // Ignore empty rdb files (which are at least seen by subordinate
1396 // uno processes during extension registration; Registry::open can
1397 // fail on them if mmap(2) returns EINVAL for a zero length):
1398 osl::DirectoryItem item;
1399 if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
1400 osl::FileStatus status(osl_FileStatus_Mask_FileSize);
1401 if (item.getFileStatus(status) == osl::FileBase::E_None
1402 && status.getFileSize() == 0)
1404 return true;
1408 SAL_FALLTHROUGH;
1409 default:
1410 return false;
1412 RegistryKey rootKey;
1413 if (reg.openRootKey(rootKey) != RegError::NO_ERROR) {
1414 throw css::uno::DeploymentException(
1415 "Failure reading legacy rdb file " + uri,
1416 static_cast< cppu::OWeakObject * >(this));
1418 RegistryKeyArray impls;
1419 switch (rootKey.openSubKeys("IMPLEMENTATIONS", impls)) {
1420 case RegError::NO_ERROR:
1421 break;
1422 case RegError::KEY_NOT_EXISTS:
1423 return true;
1424 default:
1425 throw css::uno::DeploymentException(
1426 "Failure reading legacy rdb file " + uri,
1427 static_cast< cppu::OWeakObject * >(this));
1429 for (sal_uInt32 i = 0; i != impls.getLength(); ++i) {
1430 RegistryKey implKey(impls.getElement(i));
1431 assert(implKey.getName().match("/IMPLEMENTATIONS/"));
1432 rtl::OUString name(
1433 implKey.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1434 std::shared_ptr< Data::Implementation > impl(
1435 new Data::Implementation(
1436 name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"),
1437 readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "", "",
1438 css::uno::Reference< css::uno::XComponentContext >(), uri));
1439 if (!data_.namedImplementations.emplace(name, impl).second)
1441 throw css::registry::InvalidRegistryException(
1442 uri + ": duplicate <implementation name=\"" + name + "\">");
1444 readLegacyRdbStrings(
1445 uri, implKey, "UNO/SERVICES", &impl->info->services);
1446 for (std::vector< rtl::OUString >::const_iterator j(
1447 impl->info->services.begin());
1448 j != impl->info->services.end(); ++j)
1450 data_.services[*j].push_back(impl);
1452 readLegacyRdbStrings(
1453 uri, implKey, "UNO/SINGLETONS", &impl->info->singletons);
1454 for (std::vector< rtl::OUString >::const_iterator j(
1455 impl->info->singletons.begin());
1456 j != impl->info->singletons.end(); ++j)
1458 data_.singletons[*j].push_back(impl);
1461 return true;
1464 rtl::OUString cppuhelper::ServiceManager::readLegacyRdbString(
1465 rtl::OUString const & uri, RegistryKey & key, rtl::OUString const & path)
1467 RegistryKey subkey;
1468 RegValueType t;
1469 sal_uInt32 s(0);
1470 if (key.openKey(path, subkey) != RegError::NO_ERROR
1471 || subkey.getValueInfo(rtl::OUString(), &t, &s) != RegError::NO_ERROR
1472 || t != RegValueType::STRING
1473 || s == 0 || s > static_cast< sal_uInt32 >(SAL_MAX_INT32))
1475 throw css::uno::DeploymentException(
1476 "Failure reading legacy rdb file " + uri,
1477 static_cast< cppu::OWeakObject * >(this));
1479 rtl::OUString val;
1480 std::vector< char > v(s); // assuming sal_uInt32 fits into vector::size_type
1481 if (subkey.getValue(rtl::OUString(), &v[0]) != RegError::NO_ERROR
1482 || v.back() != '\0'
1483 || !rtl_convertStringToUString(
1484 &val.pData, &v[0], static_cast< sal_Int32 >(s - 1),
1485 RTL_TEXTENCODING_UTF8,
1486 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1487 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1488 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
1490 throw css::uno::DeploymentException(
1491 "Failure reading legacy rdb file " + uri,
1492 static_cast< cppu::OWeakObject * >(this));
1494 return val;
1497 void cppuhelper::ServiceManager::readLegacyRdbStrings(
1498 rtl::OUString const & uri, RegistryKey & key, rtl::OUString const & path,
1499 std::vector< rtl::OUString > * strings)
1501 assert(strings != nullptr);
1502 RegistryKey subkey;
1503 switch (key.openKey(path, subkey)) {
1504 case RegError::NO_ERROR:
1505 break;
1506 case RegError::KEY_NOT_EXISTS:
1507 return;
1508 default:
1509 throw css::uno::DeploymentException(
1510 "Failure reading legacy rdb file " + uri,
1511 static_cast< cppu::OWeakObject * >(this));
1513 rtl::OUString prefix(subkey.getName() + "/");
1514 RegistryKeyNames names;
1515 if (subkey.getKeyNames(rtl::OUString(), names) != RegError::NO_ERROR) {
1516 throw css::uno::DeploymentException(
1517 "Failure reading legacy rdb file " + uri,
1518 static_cast< cppu::OWeakObject * >(this));
1520 for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
1521 assert(names.getElement(i).match(prefix));
1522 strings->push_back(names.getElement(i).copy(prefix.getLength()));
1526 void cppuhelper::ServiceManager::insertRdbFiles(
1527 std::vector< rtl::OUString > const & uris,
1528 css::uno::Reference< css::uno::XComponentContext > const & alienContext)
1530 Data extra;
1531 for (std::vector< rtl::OUString >::const_iterator i(uris.begin());
1532 i != uris.end(); ++i)
1534 try {
1535 Parser(*i, alienContext, &extra);
1536 } catch (css::container::NoSuchElementException &) {
1537 throw css::lang::IllegalArgumentException(
1538 *i + ": no such file", static_cast< cppu::OWeakObject * >(this),
1540 } catch (css::registry::InvalidRegistryException & e) {
1541 throw css::lang::IllegalArgumentException(
1542 "InvalidRegistryException: " + e.Message,
1543 static_cast< cppu::OWeakObject * >(this), 0);
1546 insertExtraData(extra);
1549 void cppuhelper::ServiceManager::insertLegacyFactory(
1550 css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo)
1552 assert(factoryInfo.is());
1553 rtl::OUString name(factoryInfo->getImplementationName());
1554 css::uno::Reference< css::lang::XSingleComponentFactory > f1(
1555 factoryInfo, css::uno::UNO_QUERY);
1556 css::uno::Reference< css::lang::XSingleServiceFactory > f2;
1557 if (!f1.is()) {
1558 f2.set(factoryInfo, css::uno::UNO_QUERY);
1559 if (!f2.is()) {
1560 throw css::lang::IllegalArgumentException(
1561 ("Bad XServiceInfo argument implements neither"
1562 " XSingleComponentFactory nor XSingleServiceFactory"),
1563 static_cast< cppu::OWeakObject * >(this), 0);
1566 css::uno::Reference< css::lang::XComponent > comp(
1567 factoryInfo, css::uno::UNO_QUERY);
1568 std::shared_ptr< Data::Implementation > impl(
1569 new Data::Implementation(name, f1, f2, comp));
1570 Data extra;
1571 if (!name.isEmpty()) {
1572 extra.namedImplementations.emplace(name, impl);
1574 extra.dynamicImplementations.emplace(factoryInfo, impl);
1575 css::uno::Sequence< rtl::OUString > services(
1576 factoryInfo->getSupportedServiceNames());
1577 for (sal_Int32 i = 0; i != services.getLength(); ++i) {
1578 impl->info->services.push_back(services[i]);
1579 extra.services[services[i]].push_back(impl);
1581 if (insertExtraData(extra) && comp.is()) {
1582 comp->addEventListener(this);
1586 bool cppuhelper::ServiceManager::insertExtraData(Data const & extra) {
1588 osl::MutexGuard g(rBHelper.rMutex);
1589 if (isDisposed()) {
1590 return false;
1592 for (Data::NamedImplementations::const_iterator i(
1593 extra.namedImplementations.begin());
1594 i != extra.namedImplementations.end(); ++i)
1596 if (data_.namedImplementations.find(i->first)
1597 != data_.namedImplementations.end())
1599 throw css::lang::IllegalArgumentException(
1600 "Insert duplicate implementation name " + i->first,
1601 static_cast< cppu::OWeakObject * >(this), 0);
1604 for (Data::DynamicImplementations::const_iterator i(
1605 extra.dynamicImplementations.begin());
1606 i != extra.dynamicImplementations.end(); ++i)
1608 if (data_.dynamicImplementations.find(i->first)
1609 != data_.dynamicImplementations.end())
1611 throw css::lang::IllegalArgumentException(
1612 "Insert duplicate factory object",
1613 static_cast< cppu::OWeakObject * >(this), 0);
1616 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1617 data_.namedImplementations.insert(
1618 extra.namedImplementations.begin(),
1619 extra.namedImplementations.end());
1620 data_.dynamicImplementations.insert(
1621 extra.dynamicImplementations.begin(),
1622 extra.dynamicImplementations.end());
1623 insertImplementationMap(&data_.services, extra.services);
1624 insertImplementationMap(&data_.singletons, extra.singletons);
1626 //TODO: Updating the component context singleton data should be part of the
1627 // atomic service manager update:
1628 if (!extra.singletons.empty()) {
1629 assert(context_.is());
1630 css::uno::Reference< css::container::XNameContainer > cont(
1631 context_, css::uno::UNO_QUERY_THROW);
1632 for (Data::ImplementationMap::const_iterator i(
1633 extra.singletons.begin());
1634 i != extra.singletons.end(); ++i)
1636 rtl::OUString name("/singletons/" + i->first);
1637 //TODO: Update should be atomic:
1638 try {
1639 cont->removeByName(name + "/arguments");
1640 } catch (const css::container::NoSuchElementException &) {}
1641 assert(!i->second.empty());
1642 assert(i->second[0].get() != nullptr);
1643 SAL_INFO_IF(
1644 i->second.size() > 1, "cppuhelper",
1645 "Arbitrarily choosing " << i->second[0]->info->name
1646 << " among multiple implementations for singleton "
1647 << i->first);
1648 try {
1649 cont->insertByName(
1650 name + "/service", css::uno::Any(i->second[0]->info->name));
1651 } catch (css::container::ElementExistException &) {
1652 cont->replaceByName(
1653 name + "/service", css::uno::Any(i->second[0]->info->name));
1655 try {
1656 cont->insertByName(name, css::uno::Any());
1657 } catch (css::container::ElementExistException &) {
1658 SAL_INFO("cppuhelper", "Overwriting singleton " << i->first);
1659 cont->replaceByName(name, css::uno::Any());
1663 return true;
1666 void cppuhelper::ServiceManager::removeRdbFiles(
1667 std::vector< rtl::OUString > const & uris)
1669 // The underlying data structures make this function somewhat inefficient,
1670 // but the assumption is that it is rarely called (and that if it is called,
1671 // it is called with a uris vector of size one):
1672 std::vector< std::shared_ptr< Data::Implementation > > clear;
1674 osl::MutexGuard g(rBHelper.rMutex);
1675 for (std::vector< rtl::OUString >::const_iterator i(uris.begin());
1676 i != uris.end(); ++i)
1678 for (Data::NamedImplementations::iterator j(
1679 data_.namedImplementations.begin());
1680 j != data_.namedImplementations.end();)
1682 assert(j->second.get() != nullptr);
1683 if (j->second->info->rdbFile == *i) {
1684 clear.push_back(j->second);
1685 //TODO: The below leaves data_ in an inconsistent state upon
1686 // exceptions:
1687 removeFromImplementationMap(
1688 &data_.services, j->second->info->services, j->second);
1689 removeFromImplementationMap(
1690 &data_.singletons, j->second->info->singletons,
1691 j->second);
1692 j = data_.namedImplementations.erase(j);
1693 } else {
1694 ++j;
1699 //TODO: Update the component context singleton data
1702 bool cppuhelper::ServiceManager::removeLegacyFactory(
1703 css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
1704 bool removeListener)
1706 assert(factoryInfo.is());
1707 std::shared_ptr< Data::Implementation > clear;
1708 css::uno::Reference< css::lang::XComponent > comp;
1710 osl::MutexGuard g(rBHelper.rMutex);
1711 Data::DynamicImplementations::iterator i(
1712 data_.dynamicImplementations.find(factoryInfo));
1713 if (i == data_.dynamicImplementations.end()) {
1714 return isDisposed();
1716 assert(i->second.get() != nullptr);
1717 clear = i->second;
1718 if (removeListener) {
1719 comp = i->second->component;
1721 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1722 removeFromImplementationMap(
1723 &data_.services, i->second->info->services, i->second);
1724 removeFromImplementationMap(
1725 &data_.singletons, i->second->info->singletons, i->second);
1726 if (!i->second->info->name.isEmpty()) {
1727 data_.namedImplementations.erase(i->second->info->name);
1729 data_.dynamicImplementations.erase(i);
1731 if (comp.is()) {
1732 removeEventListenerFromComponent(comp);
1734 return true;
1737 void cppuhelper::ServiceManager::removeImplementation(const rtl::OUString & name) {
1738 // The underlying data structures make this function somewhat inefficient,
1739 // but the assumption is that it is rarely called:
1740 std::shared_ptr< Data::Implementation > clear;
1742 osl::MutexGuard g(rBHelper.rMutex);
1743 if (isDisposed()) {
1744 return;
1746 Data::NamedImplementations::iterator i(
1747 data_.namedImplementations.find(name));
1748 if (i == data_.namedImplementations.end()) {
1749 throw css::container::NoSuchElementException(
1750 "Remove non-inserted implementation " + name,
1751 static_cast< cppu::OWeakObject * >(this));
1753 assert(i->second.get() != nullptr);
1754 clear = i->second;
1755 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1756 removeFromImplementationMap(
1757 &data_.services, i->second->info->services, i->second);
1758 removeFromImplementationMap(
1759 &data_.singletons, i->second->info->singletons, i->second);
1760 for (Data::DynamicImplementations::iterator j(
1761 data_.dynamicImplementations.begin());
1762 j != data_.dynamicImplementations.end(); ++j)
1764 if (j->second == i->second) {
1765 data_.dynamicImplementations.erase(j);
1766 break;
1769 data_.namedImplementations.erase(i);
1773 std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
1774 cppuhelper::ServiceManager::findServiceImplementation(
1775 css::uno::Reference< css::uno::XComponentContext > const & context,
1776 rtl::OUString const & specifier)
1778 std::shared_ptr< Data::Implementation > impl;
1779 bool loaded;
1781 osl::MutexGuard g(rBHelper.rMutex);
1782 Data::ImplementationMap::const_iterator i(
1783 data_.services.find(specifier));
1784 if (i == data_.services.end()) {
1785 Data::NamedImplementations::const_iterator j(
1786 data_.namedImplementations.find(specifier));
1787 if (j == data_.namedImplementations.end()) {
1788 SAL_INFO("cppuhelper", "No implementation for " << specifier);
1789 return std::shared_ptr< Data::Implementation >();
1791 impl = j->second;
1792 } else {
1793 assert(!i->second.empty());
1794 SAL_INFO_IF(
1795 i->second.size() > 1, "cppuhelper",
1796 "Arbitrarily choosing " << i->second[0]->info->name
1797 << " among multiple implementations for " << i->first);
1798 impl = i->second[0];
1800 assert(impl.get() != nullptr);
1801 loaded = impl->status == Data::Implementation::STATUS_LOADED;
1803 if (!loaded) {
1804 loadImplementation(context, impl);
1806 return impl;
1809 /// Make a simpler unique name for preload / progress reporting.
1810 #ifndef DISABLE_DYNLOADING
1811 static rtl::OUString simplifyModule(const rtl::OUString &uri)
1813 sal_Int32 nIdx;
1814 OUStringBuffer edit(uri);
1815 if ((nIdx = edit.lastIndexOf('/')) > 0)
1816 edit.remove(0,nIdx+1);
1817 if ((nIdx = edit.lastIndexOf(':')) > 0)
1818 edit.remove(0,nIdx+1);
1819 if ((nIdx = edit.lastIndexOf("lo.so")) > 0)
1820 edit.truncate(nIdx);
1821 if ((nIdx = edit.lastIndexOf(".3")) > 0)
1822 edit.truncate(nIdx);
1823 if ((nIdx = edit.lastIndexOf("gcc3.so")) > 0)
1824 edit.truncate(nIdx);
1825 if ((nIdx = edit.lastIndexOf(".so")) > 0)
1826 edit.truncate(nIdx);
1827 if ((nIdx = edit.lastIndexOf("_uno")) > 0)
1828 edit.truncate(nIdx);
1829 if ((nIdx = edit.lastIndexOf(".jar")) > 0)
1830 edit.truncate(nIdx);
1831 if (edit.indexOf("lib") == 0)
1832 edit.remove(0,3);
1833 return edit.makeStringAndClear();
1835 #endif
1837 /// Used only by LibreOfficeKit when used by Online to pre-initialize
1838 void cppuhelper::ServiceManager::preloadImplementations() {
1839 #ifdef DISABLE_DYNLOADING
1840 abort();
1841 #else
1842 rtl::OUString aUri;
1843 osl::MutexGuard g(rBHelper.rMutex);
1844 css::uno::Environment aSourceEnv(css::uno::Environment::getCurrent());
1846 std::cerr << "preload:";
1847 std::vector<OUString> aReported;
1849 // loop all implementations
1850 for (Data::NamedImplementations::const_iterator iterator(
1851 data_.namedImplementations.begin());
1852 iterator != data_.namedImplementations.end(); ++iterator)
1856 const rtl::OUString &aLibrary = iterator->second->info->uri;
1858 if (aLibrary.isEmpty())
1859 continue;
1861 if (std::find(aReported.begin(), aReported.end(), aLibrary) == aReported.end())
1863 std::cerr << " " << simplifyModule(aLibrary);
1864 std::cerr.flush();
1865 aReported.push_back(aLibrary);
1868 // expand absolute URI implementation component library
1869 aUri = cppu::bootstrap_expandUri(aLibrary);
1871 catch (css::lang::IllegalArgumentException& aError)
1873 throw css::uno::DeploymentException(
1874 "Cannot expand URI" + iterator->second->info->uri + ": " + aError.Message,
1875 static_cast< cppu::OWeakObject * >(this));
1878 if (iterator->second->info->loader == "com.sun.star.loader.SharedLibrary" &&
1879 iterator->second->status != Data::Implementation::STATUS_LOADED)
1881 // Blacklist some components that are known to fail
1882 if (iterator->second->info->name == "com.sun.star.comp.configuration.backend.KDE4Backend")
1884 std::cerr << ":skipping";
1885 std::cerr.flush();
1886 continue;
1889 // load component library
1890 osl::Module aModule(aUri, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL);
1892 if (!aModule.is())
1894 std::cerr << ":failed" << std::endl;
1895 std::cerr.flush();
1898 if (aModule.is() &&
1899 !iterator->second->info->environment.isEmpty())
1901 OUString aSymFactory;
1902 oslGenericFunction fpFactory;
1903 css::uno::Environment aTargetEnv;
1904 css::uno::Reference<css::uno::XInterface> xFactory;
1906 if(iterator->second->info->constructor.isEmpty())
1908 // expand full name component factory symbol
1909 if (iterator->second->info->prefix == "direct")
1910 aSymFactory = iterator->second->info->name.replace('.', '_') + "_" COMPONENT_GETFACTORY;
1911 else if (!iterator->second->info->prefix.isEmpty())
1912 aSymFactory = iterator->second->info->prefix + "_" COMPONENT_GETFACTORY;
1913 else
1914 aSymFactory = COMPONENT_GETFACTORY;
1916 // get function symbol component factory
1917 fpFactory = aModule.getFunctionSymbol(aSymFactory);
1918 if (fpFactory == nullptr)
1920 throw css::loader::CannotActivateFactoryException(
1921 ("no factory symbol \"" + aSymFactory + "\" in component library :" + aUri),
1922 css::uno::Reference<css::uno::XInterface>());
1925 aTargetEnv = cppuhelper::detail::getEnvironment(iterator->second->info->environment, iterator->second->info->name);
1926 component_getFactoryFunc fpComponentFactory = reinterpret_cast<component_getFactoryFunc>(fpFactory);
1928 if (aSourceEnv.get() == aTargetEnv.get())
1930 // invoke function component factory
1931 OString aImpl(rtl::OUStringToOString(iterator->second->info->name, RTL_TEXTENCODING_ASCII_US));
1932 xFactory.set(css::uno::Reference<css::uno::XInterface>(static_cast<css::uno::XInterface *>(
1933 (*fpComponentFactory)(aImpl.getStr(), this, nullptr)), SAL_NO_ACQUIRE));
1936 else
1938 // get function symbol component factory
1939 aTargetEnv = cppuhelper::detail::getEnvironment(iterator->second->info->environment, iterator->second->info->name);
1940 if (aSourceEnv.get() == aTargetEnv.get())
1942 fpFactory = aModule.getFunctionSymbol(iterator->second->info->constructor);
1944 else
1946 fpFactory = nullptr;
1950 css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory;
1951 css::uno::Reference<css::lang::XSingleServiceFactory> xSSFactory;
1953 // query interface XSingleComponentFactory or XSingleServiceFactory
1954 if (xFactory.is())
1956 xSCFactory.set(xFactory, css::uno::UNO_QUERY);
1957 if (!xSCFactory.is())
1959 xSSFactory.set(xFactory, css::uno::UNO_QUERY);
1960 if (!xSSFactory.is())
1962 throw css::uno::DeploymentException(
1963 ("Implementation " + iterator->second->info->name
1964 + " does not provide a constructor or factory"),
1965 static_cast< cppu::OWeakObject * >(this));
1970 if (!iterator->second->info->constructor.isEmpty() && fpFactory)
1971 iterator->second->constructor = WrapperConstructorFn(reinterpret_cast<ImplementationConstructorFn *>(fpFactory));
1973 iterator->second->factory1 = xSCFactory;
1974 iterator->second->factory2 = xSSFactory;
1975 iterator->second->status = Data::Implementation::STATUS_LOADED;
1979 // Some libraries use other (non-UNO) libraries requiring preinit
1980 oslGenericFunction fpPreload = aModule.getFunctionSymbol( "lok_preload_hook" );
1981 if (fpPreload)
1983 static std::vector<oslGenericFunction> aPreloaded;
1984 if (std::find(aPreloaded.begin(), aPreloaded.end(), fpPreload) == aPreloaded.end())
1986 aPreloaded.push_back(fpPreload);
1987 fpPreload();
1991 // leak aModule
1992 aModule.release();
1995 std::cerr << std::endl;
1997 // Various rather important uno mappings.
1998 struct {
1999 const char *mpFrom;
2000 const char *mpTo;
2001 const char *mpPurpose;
2002 } const aMappingLoad[] = {
2003 { "gcc3", "uno", "" },
2004 { "uno", "gcc3", "" },
2007 static std::vector<css::uno::Mapping> maMaps;
2008 for (auto &it : aMappingLoad)
2010 maMaps.push_back(css::uno::Mapping(
2011 OUString::createFromAscii(it.mpFrom),
2012 OUString::createFromAscii(it.mpTo),
2013 OUString::createFromAscii(it.mpPurpose)));
2015 #endif
2018 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */