1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <sal/config.h>
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>
54 #include "servicemanager.hxx"
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(
65 i
!= source
.end(); ++i
)
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(
89 assert(j
!= map
->end());
92 cppuhelper::ServiceManager::Data::Implementation
> >::iterator
93 k(std::find(j
->second
.begin(), j
->second
.end(), implementation
));
94 assert(k
!= j
->second
.end());
96 if (j
->second
.empty()) {
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):
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;
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
>
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(
146 RTL_CONSTASCII_STRINGPARAM(
147 "http://openoffice.org/2010/uno-components")));
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
;
154 xmlreader::XmlReader::Result res
= reader_
.nextItem(
155 xmlreader::XmlReader::Text::NONE
, &name
, &nsId
);
158 if (res
== xmlreader::XmlReader::Result::Begin
&& nsId
== ucNsId
159 && name
.equals(RTL_CONSTASCII_STRINGPARAM("components")))
161 state
= STATE_COMPONENTS
;
164 throw css::registry::InvalidRegistryException(
165 reader_
.getUrl() + ": unexpected item in outer level");
167 if (res
== xmlreader::XmlReader::Result::Done
) {
170 throw css::registry::InvalidRegistryException(
171 reader_
.getUrl() + ": unexpected item in outer level");
172 case STATE_COMPONENTS
:
173 if (res
== xmlreader::XmlReader::Result::End
) {
177 if (res
== xmlreader::XmlReader::Result::Begin
&& nsId
== ucNsId
178 && name
.equals(RTL_CONSTASCII_STRINGPARAM("component")))
181 state
= STATE_COMPONENT_INITIAL
;
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
;
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
;
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
;
207 if (res
== xmlreader::XmlReader::Result::Begin
&& nsId
== ucNsId
208 && name
.equals(RTL_CONSTASCII_STRINGPARAM("service")))
211 state
= STATE_SERVICE
;
214 if (res
== xmlreader::XmlReader::Result::Begin
&& nsId
== ucNsId
215 && name
.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
218 state
= STATE_SINGLETON
;
221 throw css::registry::InvalidRegistryException(
222 reader_
.getUrl() + ": unexpected item in <implementation>");
224 if (res
== xmlreader::XmlReader::Result::End
) {
225 state
= STATE_IMPLEMENTATION
;
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
;
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
;
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(
255 + ": <component> has multiple \"loader\" attributes");
257 attrLoader_
= reader_
.getAttributeValue(false).convertFromUtf8();
258 if (attrLoader_
.isEmpty()) {
259 throw css::registry::InvalidRegistryException(
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(
269 + ": <component> has multiple \"uri\" attributes");
271 attrUri_
= reader_
.getAttributeValue(false).convertFromUtf8();
272 if (attrUri_
.isEmpty()) {
273 throw css::registry::InvalidRegistryException(
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(
283 ": <component> has multiple \"environment\" attributes");
285 attrEnvironment_
= reader_
.getAttributeValue(false)
287 if (attrEnvironment_
.isEmpty()) {
288 throw css::registry::InvalidRegistryException(
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(
298 ": <component> has multiple \"prefix\" attributes");
300 attrPrefix_
= reader_
.getAttributeValue(false).convertFromUtf8();
301 if (attrPrefix_
.isEmpty()) {
302 throw css::registry::InvalidRegistryException(
304 ": <component> has empty \"prefix\" attribute");
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
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());
330 void Parser::handleImplementation() {
331 rtl::OUString attrName
;
332 rtl::OUString attrConstructor
;
333 xmlreader::Span name
;
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(
342 + ": <implementation> has multiple \"name\" attributes");
344 attrName
= reader_
.getAttributeValue(false).convertFromUtf8();
345 if (attrName
.isEmpty()) {
346 throw css::registry::InvalidRegistryException(
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(
356 + ": <implementation> has multiple \"constructor\""
359 attrConstructor
= reader_
.getAttributeValue(false)
361 if (attrConstructor
.isEmpty()) {
362 throw css::registry::InvalidRegistryException(
364 + ": element has empty \"constructor\" attribute");
366 if (attrEnvironment_
.isEmpty()) {
367 throw css::registry::InvalidRegistryException(
369 + ": <implementation> has \"constructor\" attribute but"
370 " <component> has no \"environment\" attribute");
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(
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_
).
390 throw css::registry::InvalidRegistryException(
391 reader_
.getUrl() + ": duplicate <implementation name=\"" + attrName
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
;
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(
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");
437 class ContentEnumeration
:
438 public cppu::WeakImplHelper
< css::container::XEnumeration
>
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;
448 virtual ~ContentEnumeration() override
{}
450 virtual sal_Bool SAL_CALL
hasMoreElements() override
;
452 virtual css::uno::Any SAL_CALL
nextElement() override
;
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));
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
>
488 rtl::Reference
< cppuhelper::ServiceManager
> const & manager
,
490 cppuhelper::ServiceManager::Data::Implementation
> const &
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;
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
>
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
>
539 ImplementationWrapper(
540 rtl::Reference
< cppuhelper::ServiceManager
> const & manager
,
542 cppuhelper::ServiceManager::Data::Implementation
> const &
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;
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
>
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();
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();
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();
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();
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()));
645 for (std::vector
< rtl::OUString
>::const_iterator
j(
646 impl
->info
->services
.begin());
647 j
!= impl
->info
->services
.end(); ++j
)
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
;
664 constructor(context
.get(), css::uno::Sequence
<css::uno::Any
>()),
666 } else if (factory1
.is()) {
667 inst
= factory1
->createInstanceWithContext(context
);
669 assert(factory2
.is());
670 inst
= factory2
->createInstance();
672 updateDisposeSingleton(singletonRequest
, 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
;
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
689 css::uno::Reference
<css::lang::XInitialization
> init(
690 inst
, css::uno::UNO_QUERY
);
692 init
->initialize(arguments
);
694 } else if (factory1
.is()) {
695 inst
= factory1
->createInstanceWithArgumentsAndContext(
698 assert(factory2
.is());
699 inst
= factory2
->createInstanceWithArguments(arguments
);
701 updateDisposeSingleton(singletonRequest
, 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();
719 } else if (!info
->singletons
.empty()) {
720 css::uno::Reference
<css::lang::XComponent
> comp(
721 instance
, css::uno::UNO_QUERY
);
723 osl::MutexGuard
g(mutex
);
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);
741 i
->second
.size() > 1, "cppuhelper",
742 "Arbitrarily choosing " << i
->second
[0]->info
->name
743 << " among multiple implementations for " << i
->first
);
745 cppu::ContextEntry_Init(
746 "/singletons/" + i
->first
,
748 css::uno::Reference
<css::lang::XSingleComponentFactory
> >(
749 new SingletonFactory(this, i
->second
[0])),
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
) {
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
);
785 assert(!implementation
->info
->environment
.isEmpty());
789 !implementation
->info
->environment
.isEmpty(), "cppuhelper",
790 "Loader " << implementation
->info
->loader
791 << " and non-empty environment "
792 << implementation
->info
->environment
);
794 !implementation
->info
->prefix
.isEmpty(), "cppuhelper",
795 "Loader " << implementation
->info
->loader
796 << " and non-empty constructor "
797 << implementation
->info
->constructor
);
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
);
808 assert(context
.is());
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
;
822 f1
.set(f0
, css::uno::UNO_QUERY
);
824 f2
.set(f0
, css::uno::UNO_QUERY
);
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
);
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
;
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
);
886 css::uno::Reference
<css::lang::XComponent
> >::const_iterator
i(
888 i
!= sngls
.end(); ++i
)
892 } catch (css::uno::RuntimeException
& e
) {
893 SAL_WARN("cppuhelper", "Ignoring " << e
<< " while disposing singleton");
897 css::uno::Reference
< css::lang::XComponent
> >::const_iterator
i(
899 i
!= comps
.end(); ++i
)
901 removeEventListenerFromComponent(*i
);
905 void cppuhelper::ServiceManager::initialize(
906 css::uno::Sequence
<css::uno::Any
> const & aArguments
)
909 if (aArguments
.getLength() != 1 || !(aArguments
[0] >>= arg
)
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";
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
);
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
));
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());
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
);
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") {
1044 if (!(args
[i
].Value
>>= uri
)) {
1045 throw css::lang::IllegalArgumentException(
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);
1062 throw css::lang::IllegalArgumentException(
1063 "Bad argument " + args
[i
].Name
,
1064 static_cast< cppu::OWeakObject
* >(this), 0);
1067 insertRdbFiles(uris
, alienContext
);
1070 css::uno::Reference
< css::lang::XServiceInfo
> info
;
1071 if ((aElement
>>= info
) && info
.is()) {
1072 insertLegacyFactory(info
);
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()) {
1090 "Ignored XSingleComponentFactory not implementing XServiceInfo");
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(
1112 static_cast< cppu::OWeakObject
* >(this), 0);
1114 uris
.push_back(uri
);
1116 removeRdbFiles(uris
);
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));
1129 if (aElement
>>= impl
) {
1130 // For live-removal of extensions:
1131 removeImplementation(impl
);
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()) {
1151 std::vector
< css::uno::Any
> factories
;
1153 std::shared_ptr
< Data::Implementation
> >::const_iterator
i(
1155 i
!= impls
.end(); ++i
)
1157 Data::Implementation
* impl
= i
->get();
1158 assert(impl
!= nullptr);
1160 osl::MutexGuard
g(rBHelper
.rMutex
);
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
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
));
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()
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));
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 &
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 &
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 &
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 &
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();
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
),
1304 void cppuhelper::ServiceManager::removeEventListenerFromComponent(
1305 css::uno::Reference
< css::lang::XComponent
> const & component
)
1307 assert(component
.is());
1309 component
->removeEventListener(this);
1310 } catch (css::uno::RuntimeException
& e
) {
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()) {
1325 cppu::decodeRdbUri(&uri
, &optional
, &directory
);
1327 readRdbDirectory(uri
, optional
);
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
:
1341 case osl::FileBase::E_NOENT
:
1343 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
1348 throw css::uno::DeploymentException(
1349 "Cannot open directory " + uri
,
1350 static_cast< cppu::OWeakObject
* >(this));
1354 if (!cppu::nextDirectoryItem(dir
, &url
)) {
1357 readRdbFile(url
, false);
1361 void cppuhelper::ServiceManager::readRdbFile(
1362 rtl::OUString
const & uri
, bool optional
)
1366 uri
, css::uno::Reference
< css::uno::XComponentContext
>(), &data_
);
1367 } catch (css::container::NoSuchElementException
&) {
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
)) {
1387 bool cppuhelper::ServiceManager::readLegacyRdbFile(rtl::OUString
const & uri
) {
1389 switch (reg
.open(uri
, RegAccessMode::READONLY
)) {
1390 case RegError::NO_ERROR
:
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)
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
:
1422 case RegError::KEY_NOT_EXISTS
:
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/"));
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
);
1464 rtl::OUString
cppuhelper::ServiceManager::readLegacyRdbString(
1465 rtl::OUString
const & uri
, RegistryKey
& key
, rtl::OUString
const & path
)
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));
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
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));
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);
1503 switch (key
.openKey(path
, subkey
)) {
1504 case RegError::NO_ERROR
:
1506 case RegError::KEY_NOT_EXISTS
:
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
)
1531 for (std::vector
< rtl::OUString
>::const_iterator
i(uris
.begin());
1532 i
!= uris
.end(); ++i
)
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
;
1558 f2
.set(factoryInfo
, css::uno::UNO_QUERY
);
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
));
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
);
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:
1639 cont
->removeByName(name
+ "/arguments");
1640 } catch (const css::container::NoSuchElementException
&) {}
1641 assert(!i
->second
.empty());
1642 assert(i
->second
[0].get() != nullptr);
1644 i
->second
.size() > 1, "cppuhelper",
1645 "Arbitrarily choosing " << i
->second
[0]->info
->name
1646 << " among multiple implementations for singleton "
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
));
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());
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
1687 removeFromImplementationMap(
1688 &data_
.services
, j
->second
->info
->services
, j
->second
);
1689 removeFromImplementationMap(
1690 &data_
.singletons
, j
->second
->info
->singletons
,
1692 j
= data_
.namedImplementations
.erase(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);
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
);
1732 removeEventListenerFromComponent(comp
);
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
);
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);
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
);
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
;
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
>();
1793 assert(!i
->second
.empty());
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
;
1804 loadImplementation(context
, impl
);
1809 /// Make a simpler unique name for preload / progress reporting.
1810 #ifndef DISABLE_DYNLOADING
1811 static rtl::OUString
simplifyModule(const rtl::OUString
&uri
)
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)
1833 return edit
.makeStringAndClear();
1837 /// Used only by LibreOfficeKit when used by Online to pre-initialize
1838 void cppuhelper::ServiceManager::preloadImplementations() {
1839 #ifdef DISABLE_DYNLOADING
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())
1861 if (std::find(aReported
.begin(), aReported
.end(), aLibrary
) == aReported
.end())
1863 std::cerr
<< " " << simplifyModule(aLibrary
);
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";
1889 // load component library
1890 osl::Module
aModule(aUri
, SAL_LOADMODULE_NOW
| SAL_LOADMODULE_GLOBAL
);
1894 std::cerr
<< ":failed" << std::endl
;
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
;
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
));
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
);
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
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" );
1983 static std::vector
<oslGenericFunction
> aPreloaded
;
1984 if (std::find(aPreloaded
.begin(), aPreloaded
.end(), fpPreload
) == aPreloaded
.end())
1986 aPreloaded
.push_back(fpPreload
);
1995 std::cerr
<< std::endl
;
1997 // Various rather important uno mappings.
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
)));
2018 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */