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"
16 #include "boost/noncopyable.hpp"
17 #include "boost/shared_ptr.hpp"
18 #include "com/sun/star/beans/NamedValue.hpp"
19 #include "com/sun/star/beans/PropertyAttribute.hpp"
20 #include "com/sun/star/container/ElementExistException.hpp"
21 #include "com/sun/star/container/XEnumeration.hpp"
22 #include "com/sun/star/container/XNameContainer.hpp"
23 #include "com/sun/star/lang/XInitialization.hpp"
24 #include "com/sun/star/lang/XServiceInfo.hpp"
25 #include "com/sun/star/lang/XSingleComponentFactory.hpp"
26 #include "com/sun/star/lang/XSingleServiceFactory.hpp"
27 #include "com/sun/star/loader/XImplementationLoader.hpp"
28 #include "com/sun/star/registry/InvalidRegistryException.hpp"
29 #include "com/sun/star/uno/DeploymentException.hpp"
30 #include "com/sun/star/uno/Reference.hxx"
31 #include "com/sun/star/uno/XComponentContext.hpp"
32 #include "cppuhelper/bootstrap.hxx"
33 #include "cppuhelper/component_context.hxx"
34 #include "cppuhelper/implbase1.hxx"
35 #include "cppuhelper/implbase3.hxx"
36 #include "cppuhelper/shlib.hxx"
37 #include "cppuhelper/supportsservice.hxx"
38 #include "osl/file.hxx"
39 #include "rtl/ref.hxx"
40 #include "rtl/uri.hxx"
41 #include "rtl/ustring.hxx"
42 #include "rtl/strbuf.hxx"
43 #include "sal/log.hxx"
44 #include "uno/environment.hxx"
46 #include <loadsharedlibcomponentfactory.hxx>
50 using rtl::OStringBuffer
;
52 #include "registry/registry.hxx"
53 #include "xmlreader/xmlreader.hxx"
56 #include "servicemanager.hxx"
60 void insertImplementationMap(
61 cppuhelper::ServiceManager::Data::ImplementationMap
* destination
,
62 cppuhelper::ServiceManager::Data::ImplementationMap
const & source
)
64 assert(destination
!= 0);
65 for (cppuhelper::ServiceManager::Data::ImplementationMap::const_iterator
i(
67 i
!= source
.end(); ++i
)
71 cppuhelper::ServiceManager::Data::Implementation
> > & impls
72 = (*destination
)[i
->first
];
73 impls
.insert(impls
.end(), i
->second
.begin(), i
->second
.end());
77 void removeFromImplementationMap(
78 cppuhelper::ServiceManager::Data::ImplementationMap
* map
,
79 std::vector
< rtl::OUString
> const & elements
,
80 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
81 const & implementation
)
83 // The underlying data structures make this function somewhat inefficient,
84 // but the assumption is that it is rarely called:
86 for (std::vector
< rtl::OUString
>::const_iterator
i(elements
.begin());
87 i
!= elements
.end(); ++i
)
89 cppuhelper::ServiceManager::Data::ImplementationMap::iterator
j(
91 assert(j
!= map
->end());
94 cppuhelper::ServiceManager::Data::Implementation
> >::iterator
95 k(std::find(j
->second
.begin(), j
->second
.end(), implementation
));
96 assert(k
!= j
->second
.end());
98 if (j
->second
.empty()) {
104 // For simplicity, this code keeps throwing
105 // css::registry::InvalidRegistryException for invalid XML rdbs (even though
106 // that does not fit the exception's name):
107 class Parser
: private boost::noncopyable
{
110 rtl::OUString
const & uri
,
111 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
,
112 cppuhelper::ServiceManager::Data
* data
);
115 void handleComponent();
117 void handleImplementation();
119 void handleService();
121 void handleSingleton();
123 rtl::OUString
getNameAttribute();
125 xmlreader::XmlReader reader_
;
126 css::uno::Reference
< css::uno::XComponentContext
> alienContext_
;
127 cppuhelper::ServiceManager::Data
* data_
;
128 rtl::OUString attrLoader_
;
129 rtl::OUString attrUri_
;
130 rtl::OUString attrEnvironment_
;
131 rtl::OUString attrPrefix_
;
132 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
137 rtl::OUString
const & uri
,
138 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
,
139 cppuhelper::ServiceManager::Data
* data
):
140 reader_(uri
), alienContext_(alienContext
), data_(data
)
143 int ucNsId
= reader_
.registerNamespaceIri(
145 RTL_CONSTASCII_STRINGPARAM(
146 "http://openoffice.org/2010/uno-components")));
148 STATE_BEGIN
, STATE_END
, STATE_COMPONENTS
, STATE_COMPONENT_INITIAL
,
149 STATE_COMPONENT
, STATE_IMPLEMENTATION
, STATE_SERVICE
, STATE_SINGLETON
};
150 for (State state
= STATE_BEGIN
;;) {
151 xmlreader::Span name
;
153 xmlreader::XmlReader::Result res
= reader_
.nextItem(
154 xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
157 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
158 && name
.equals(RTL_CONSTASCII_STRINGPARAM("components")))
160 state
= STATE_COMPONENTS
;
163 throw css::registry::InvalidRegistryException(
164 reader_
.getUrl() + ": unexpected item in outer level",
165 css::uno::Reference
< css::uno::XInterface
>());
167 if (res
== xmlreader::XmlReader::RESULT_DONE
) {
170 throw css::registry::InvalidRegistryException(
171 reader_
.getUrl() + ": unexpected item in outer level",
172 css::uno::Reference
< css::uno::XInterface
>());
173 case STATE_COMPONENTS
:
174 if (res
== xmlreader::XmlReader::RESULT_END
) {
178 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
179 && name
.equals(RTL_CONSTASCII_STRINGPARAM("component")))
182 state
= STATE_COMPONENT_INITIAL
;
185 throw css::registry::InvalidRegistryException(
186 reader_
.getUrl() + ": unexpected item in <components>",
187 css::uno::Reference
< css::uno::XInterface
>());
188 case STATE_COMPONENT
:
189 if (res
== xmlreader::XmlReader::RESULT_END
) {
190 state
= STATE_COMPONENTS
;
194 case STATE_COMPONENT_INITIAL
:
195 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
196 && name
.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
198 handleImplementation();
199 state
= STATE_IMPLEMENTATION
;
202 throw css::registry::InvalidRegistryException(
203 reader_
.getUrl() + ": unexpected item in <component>",
204 css::uno::Reference
< css::uno::XInterface
>());
205 case STATE_IMPLEMENTATION
:
206 if (res
== xmlreader::XmlReader::RESULT_END
) {
207 state
= STATE_COMPONENT
;
210 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
211 && name
.equals(RTL_CONSTASCII_STRINGPARAM("service")))
214 state
= STATE_SERVICE
;
217 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
218 && name
.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
221 state
= STATE_SINGLETON
;
224 throw css::registry::InvalidRegistryException(
225 reader_
.getUrl() + ": unexpected item in <implementation>",
226 css::uno::Reference
< css::uno::XInterface
>());
228 if (res
== xmlreader::XmlReader::RESULT_END
) {
229 state
= STATE_IMPLEMENTATION
;
232 throw css::registry::InvalidRegistryException(
233 reader_
.getUrl() + ": unexpected item in <service>",
234 css::uno::Reference
< css::uno::XInterface
>());
235 case STATE_SINGLETON
:
236 if (res
== xmlreader::XmlReader::RESULT_END
) {
237 state
= STATE_IMPLEMENTATION
;
240 throw css::registry::InvalidRegistryException(
241 reader_
.getUrl() + ": unexpected item in <service>",
242 css::uno::Reference
< css::uno::XInterface
>());
247 void Parser::handleComponent() {
248 attrLoader_
= rtl::OUString();
249 attrUri_
= rtl::OUString();
250 attrEnvironment_
= rtl::OUString();
251 attrPrefix_
= rtl::OUString();
252 xmlreader::Span name
;
254 while (reader_
.nextAttribute(&nsId
, &name
)) {
255 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
256 && name
.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
258 if (!attrLoader_
.isEmpty()) {
259 throw css::registry::InvalidRegistryException(
261 + ": <component> has multiple \"loader\" attributes"),
262 css::uno::Reference
< css::uno::XInterface
>());
264 attrLoader_
= reader_
.getAttributeValue(false).convertFromUtf8();
265 if (attrLoader_
.isEmpty()) {
266 throw css::registry::InvalidRegistryException(
268 + ": <component> has empty \"loader\" attribute"),
269 css::uno::Reference
< css::uno::XInterface
>());
271 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
272 && name
.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
274 if (!attrUri_
.isEmpty()) {
275 throw css::registry::InvalidRegistryException(
277 + ": <component> has multiple \"uri\" attributes"),
278 css::uno::Reference
< css::uno::XInterface
>());
280 attrUri_
= reader_
.getAttributeValue(false).convertFromUtf8();
281 if (attrUri_
.isEmpty()) {
282 throw css::registry::InvalidRegistryException(
284 + ": <component> has empty \"uri\" attribute"),
285 css::uno::Reference
< css::uno::XInterface
>());
287 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
288 && name
.equals(RTL_CONSTASCII_STRINGPARAM("environment")))
290 if (!attrEnvironment_
.isEmpty()) {
291 throw css::registry::InvalidRegistryException(
293 ": <component> has multiple \"environment\" attributes"),
294 css::uno::Reference
< css::uno::XInterface
>());
296 attrEnvironment_
= reader_
.getAttributeValue(false)
298 if (attrEnvironment_
.isEmpty()) {
299 throw css::registry::InvalidRegistryException(
301 ": <component> has empty \"environment\" attribute"),
302 css::uno::Reference
< css::uno::XInterface
>());
304 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
305 && name
.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
307 if (!attrPrefix_
.isEmpty()) {
308 throw css::registry::InvalidRegistryException(
310 ": <component> has multiple \"prefix\" attributes"),
311 css::uno::Reference
< css::uno::XInterface
>());
313 attrPrefix_
= reader_
.getAttributeValue(false).convertFromUtf8();
314 if (attrPrefix_
.isEmpty()) {
315 throw css::registry::InvalidRegistryException(
317 ": <component> has empty \"prefix\" attribute"),
318 css::uno::Reference
< css::uno::XInterface
>());
321 throw css::registry::InvalidRegistryException(
322 (reader_
.getUrl() + ": unexpected attribute \""
323 + name
.convertFromUtf8() + "\" in <component>"),
324 css::uno::Reference
< css::uno::XInterface
>());
327 if (attrLoader_
.isEmpty()) {
328 throw css::registry::InvalidRegistryException(
329 reader_
.getUrl() + ": <component> is missing \"loader\" attribute",
330 css::uno::Reference
< css::uno::XInterface
>());
332 if (attrUri_
.isEmpty()) {
333 throw css::registry::InvalidRegistryException(
334 reader_
.getUrl() + ": <component> is missing \"uri\" attribute",
335 css::uno::Reference
< css::uno::XInterface
>());
337 #ifndef DISABLE_DYNLOADING
339 attrUri_
= rtl::Uri::convertRelToAbs(reader_
.getUrl(), attrUri_
);
340 } catch (const rtl::MalformedUriException
& e
) {
341 throw css::registry::InvalidRegistryException(
342 reader_
.getUrl() + ": bad \"uri\" attribute: " + e
.getMessage(),
343 css::uno::Reference
< css::uno::XInterface
>());
348 void Parser::handleImplementation() {
349 rtl::OUString attrName
;
350 rtl::OUString attrConstructor
;
351 xmlreader::Span name
;
353 while (reader_
.nextAttribute(&nsId
, &name
)) {
354 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
355 && name
.equals(RTL_CONSTASCII_STRINGPARAM("name")))
357 if (!attrName
.isEmpty()) {
358 throw css::registry::InvalidRegistryException(
360 + ": <implementation> has multiple \"name\" attributes"),
361 css::uno::Reference
< css::uno::XInterface
>());
363 attrName
= reader_
.getAttributeValue(false).convertFromUtf8();
364 if (attrName
.isEmpty()) {
365 throw css::registry::InvalidRegistryException(
367 + ": <implementation> has empty \"name\" attribute"),
368 css::uno::Reference
< css::uno::XInterface
>());
370 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
371 && name
.equals(RTL_CONSTASCII_STRINGPARAM("constructor")))
373 if (!attrConstructor
.isEmpty()) {
374 throw css::registry::InvalidRegistryException(
376 + (": <implementation> has multiple \"constructor\""
378 css::uno::Reference
< css::uno::XInterface
>());
380 attrConstructor
= reader_
.getAttributeValue(false)
382 if (attrConstructor
.isEmpty()) {
383 throw css::registry::InvalidRegistryException(
385 + ": element has empty \"constructor\" attribute"),
386 css::uno::Reference
< css::uno::XInterface
>());
388 if (attrEnvironment_
.isEmpty()) {
389 throw css::registry::InvalidRegistryException(
391 + (": <implementation> has \"constructor\" attribute but"
392 " <component> has no \"environment\" attribute")),
393 css::uno::Reference
< css::uno::XInterface
>());
396 throw css::registry::InvalidRegistryException(
397 (reader_
.getUrl() + ": unexpected element attribute \""
398 + name
.convertFromUtf8() + "\" in <implementation>"),
399 css::uno::Reference
< css::uno::XInterface
>());
402 if (attrName
.isEmpty()) {
403 throw css::registry::InvalidRegistryException(
405 + ": <implementation> is missing \"name\" attribute"),
406 css::uno::Reference
< css::uno::XInterface
>());
408 implementation_
.reset(
409 new cppuhelper::ServiceManager::Data::Implementation(
410 attrName
, attrLoader_
, attrUri_
, attrEnvironment_
, attrConstructor
,
411 attrPrefix_
, alienContext_
, reader_
.getUrl()));
412 if (!data_
->namedImplementations
.insert(
413 cppuhelper::ServiceManager::Data::NamedImplementations::value_type(
414 attrName
, implementation_
)).
417 throw css::registry::InvalidRegistryException(
418 (reader_
.getUrl() + ": duplicate <implementation name=\"" + attrName
420 css::uno::Reference
< css::uno::XInterface
>());
424 void Parser::handleService() {
425 rtl::OUString
name(getNameAttribute());
426 implementation_
->info
->services
.push_back(name
);
427 data_
->services
[name
].push_back(implementation_
);
430 void Parser::handleSingleton() {
431 rtl::OUString
name(getNameAttribute());
432 implementation_
->info
->singletons
.push_back(name
);
433 data_
->singletons
[name
].push_back(implementation_
);
436 rtl::OUString
Parser::getNameAttribute() {
437 rtl::OUString attrName
;
438 xmlreader::Span name
;
440 while (reader_
.nextAttribute(&nsId
, &name
)) {
441 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
442 && name
.equals(RTL_CONSTASCII_STRINGPARAM("name")))
444 if (!attrName
.isEmpty()) {
445 throw css::registry::InvalidRegistryException(
447 + ": element has multiple \"name\" attributes"),
448 css::uno::Reference
< css::uno::XInterface
>());
450 attrName
= reader_
.getAttributeValue(false).convertFromUtf8();
451 if (attrName
.isEmpty()) {
452 throw css::registry::InvalidRegistryException(
453 reader_
.getUrl() + ": element has empty \"name\" attribute",
454 css::uno::Reference
< css::uno::XInterface
>());
457 throw css::registry::InvalidRegistryException(
458 reader_
.getUrl() + ": expected element attribute \"name\"",
459 css::uno::Reference
< css::uno::XInterface
>());
462 if (attrName
.isEmpty()) {
463 throw css::registry::InvalidRegistryException(
464 reader_
.getUrl() + ": element is missing \"name\" attribute",
465 css::uno::Reference
< css::uno::XInterface
>());
470 class ContentEnumeration
:
471 public cppu::WeakImplHelper1
< css::container::XEnumeration
>,
472 private boost::noncopyable
475 explicit ContentEnumeration(std::vector
< css::uno::Any
> const & factories
):
476 factories_(factories
), iterator_(factories_
.begin()) {}
479 virtual ~ContentEnumeration() {}
481 virtual sal_Bool SAL_CALL
hasMoreElements()
482 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
484 virtual css::uno::Any SAL_CALL
nextElement()
486 css::container::NoSuchElementException
,
487 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
490 std::vector
< css::uno::Any
> factories_
;
491 std::vector
< css::uno::Any
>::const_iterator iterator_
;
494 sal_Bool
ContentEnumeration::hasMoreElements()
495 throw (css::uno::RuntimeException
, std::exception
)
497 osl::MutexGuard
g(mutex_
);
498 return iterator_
!= factories_
.end();
501 css::uno::Any
ContentEnumeration::nextElement()
503 css::container::NoSuchElementException
,
504 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
)
506 osl::MutexGuard
g(mutex_
);
507 if (iterator_
== factories_
.end()) {
508 throw css::container::NoSuchElementException(
509 "Bootstrap service manager service enumerator has no more elements",
510 static_cast< cppu::OWeakObject
* >(this));
515 css::beans::Property
getDefaultContextProperty() {
516 return css::beans::Property(
517 "DefaultContext", -1,
518 cppu::UnoType
< css::uno::XComponentContext
>::get(),
519 css::beans::PropertyAttribute::READONLY
);
522 class SingletonFactory
:
523 public cppu::WeakImplHelper1
<css::lang::XSingleComponentFactory
>,
524 private boost::noncopyable
528 rtl::Reference
< cppuhelper::ServiceManager
> const & manager
,
530 cppuhelper::ServiceManager::Data::Implementation
> const &
532 manager_(manager
), implementation_(implementation
)
533 { assert(manager
.is()); assert(implementation
.get() != 0); }
536 virtual ~SingletonFactory() {}
538 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
539 createInstanceWithContext(
540 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
541 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
543 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
544 createInstanceWithArgumentsAndContext(
545 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
546 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
547 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
549 rtl::Reference
< cppuhelper::ServiceManager
> manager_
;
550 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
554 css::uno::Reference
< css::uno::XInterface
>
555 SingletonFactory::createInstanceWithContext(
556 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
557 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
559 manager_
->loadImplementation(Context
, implementation_
);
560 return implementation_
->createInstance(Context
, true);
563 css::uno::Reference
< css::uno::XInterface
>
564 SingletonFactory::createInstanceWithArgumentsAndContext(
565 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
566 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
567 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
569 manager_
->loadImplementation(Context
, implementation_
);
570 return implementation_
->createInstanceWithArguments(
571 Context
, true, Arguments
);
574 class ImplementationWrapper
:
575 public cppu::WeakImplHelper3
<
576 css::lang::XSingleComponentFactory
, css::lang::XSingleServiceFactory
,
577 css::lang::XServiceInfo
>,
578 private boost::noncopyable
581 ImplementationWrapper(
582 rtl::Reference
< cppuhelper::ServiceManager
> const & manager
,
584 cppuhelper::ServiceManager::Data::Implementation
> const &
586 manager_(manager
), implementation_(implementation
)
587 { assert(manager
.is()); assert(implementation
.get() != 0); }
590 virtual ~ImplementationWrapper() {}
592 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
593 createInstanceWithContext(
594 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
595 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
597 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
598 createInstanceWithArgumentsAndContext(
599 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
600 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
601 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
603 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
604 createInstance() throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
606 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
607 createInstanceWithArguments(
608 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
609 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
611 virtual rtl::OUString SAL_CALL
getImplementationName()
612 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
614 virtual sal_Bool SAL_CALL
supportsService(rtl::OUString
const & ServiceName
)
615 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
617 virtual css::uno::Sequence
< rtl::OUString
> SAL_CALL
618 getSupportedServiceNames() throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
620 rtl::Reference
< cppuhelper::ServiceManager
> manager_
;
621 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
625 css::uno::Reference
< css::uno::XInterface
>
626 ImplementationWrapper::createInstanceWithContext(
627 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
628 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
630 manager_
->loadImplementation(Context
, implementation_
);
631 return implementation_
->createInstance(Context
, false);
634 css::uno::Reference
< css::uno::XInterface
>
635 ImplementationWrapper::createInstanceWithArgumentsAndContext(
636 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
637 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
638 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
640 manager_
->loadImplementation(Context
, implementation_
);
641 return implementation_
->createInstanceWithArguments(
642 Context
, false, Arguments
);
645 css::uno::Reference
< css::uno::XInterface
>
646 ImplementationWrapper::createInstance()
647 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
649 return createInstanceWithContext(manager_
->getContext());
652 css::uno::Reference
< css::uno::XInterface
>
653 ImplementationWrapper::createInstanceWithArguments(
654 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
655 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
657 return createInstanceWithArgumentsAndContext(
658 Arguments
, manager_
->getContext());
661 rtl::OUString
ImplementationWrapper::getImplementationName()
662 throw (css::uno::RuntimeException
, std::exception
)
664 return implementation_
->info
->name
;
667 sal_Bool
ImplementationWrapper::supportsService(rtl::OUString
const & ServiceName
)
668 throw (css::uno::RuntimeException
, std::exception
)
670 return cppu::supportsService(this, ServiceName
);
673 css::uno::Sequence
< rtl::OUString
>
674 ImplementationWrapper::getSupportedServiceNames()
675 throw (css::uno::RuntimeException
, std::exception
)
677 if (implementation_
->info
->services
.size()
678 > static_cast< sal_uInt32
>(SAL_MAX_INT32
))
680 throw css::uno::RuntimeException(
681 ("Implementation " + implementation_
->info
->name
682 + " supports too many services"),
683 static_cast< cppu::OWeakObject
* >(this));
685 css::uno::Sequence
< rtl::OUString
> names(
686 static_cast< sal_Int32
>(implementation_
->info
->services
.size()));
688 for (std::vector
< rtl::OUString
>::const_iterator
j(
689 implementation_
->info
->services
.begin());
690 j
!= implementation_
->info
->services
.end(); ++j
)
699 css::uno::Reference
<css::uno::XInterface
>
700 cppuhelper::ServiceManager::Data::Implementation::createInstance(
701 css::uno::Reference
<css::uno::XComponentContext
> const & context
,
702 bool singletonRequest
)
704 css::uno::Reference
<css::uno::XInterface
> inst
;
705 if (constructor
!= 0) {
707 (*constructor
)(context
.get(), css::uno::Sequence
<css::uno::Any
>()),
709 } else if (factory1
.is()) {
710 inst
= factory1
->createInstanceWithContext(context
);
712 assert(factory2
.is());
713 inst
= factory2
->createInstance();
715 updateDisposeSingleton(singletonRequest
, inst
);
719 css::uno::Reference
<css::uno::XInterface
>
720 cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
721 css::uno::Reference
<css::uno::XComponentContext
> const & context
,
722 bool singletonRequest
, css::uno::Sequence
<css::uno::Any
> const & arguments
)
724 css::uno::Reference
<css::uno::XInterface
> inst
;
725 if (constructor
!= 0) {
726 inst
.set((*constructor
)(context
.get(), arguments
), SAL_NO_ACQUIRE
);
727 //HACK: The constructor will either observe arguments and return inst
728 // that does not implement XInitialization (or null), or ignore
729 // arguments and return inst that implements XInitialization; this
730 // should be removed again once XInitialization-based implementations
732 css::uno::Reference
<css::lang::XInitialization
> init(
733 inst
, css::uno::UNO_QUERY
);
735 init
->initialize(arguments
);
737 } else if (factory1
.is()) {
738 inst
= factory1
->createInstanceWithArgumentsAndContext(
741 assert(factory2
.is());
742 inst
= factory2
->createInstanceWithArguments(arguments
);
744 updateDisposeSingleton(singletonRequest
, inst
);
748 void cppuhelper::ServiceManager::Data::Implementation::updateDisposeSingleton(
749 bool singletonRequest
,
750 css::uno::Reference
<css::uno::XInterface
> const & instance
)
752 // This is an optimization, to only call dispose once (from the component
753 // context) on a singleton that is obtained both via the component context
754 // and via the service manager; however, there is a harmless race here that
755 // may cause two calls to dispose nevertheless (also, this calls dispose on
756 // at most one of the instances obtained via the service manager, in case
757 // the implementation hands out different instances):
758 if (singletonRequest
) {
759 osl::MutexGuard
g(mutex
);
760 disposeSingleton
.clear();
762 } else if (!info
->singletons
.empty()) {
763 css::uno::Reference
<css::lang::XComponent
> comp(
764 instance
, css::uno::UNO_QUERY
);
766 osl::MutexGuard
g(mutex
);
768 disposeSingleton
= comp
;
774 void cppuhelper::ServiceManager::addSingletonContextEntries(
775 std::vector
< cppu::ContextEntry_Init
> * entries
)
777 assert(entries
!= 0);
778 for (Data::ImplementationMap::const_iterator
i(data_
.singletons
.begin());
779 i
!= data_
.singletons
.end(); ++i
)
781 assert(!i
->second
.empty());
782 assert(i
->second
[0].get() != 0);
784 i
->second
.size() > 1, "cppuhelper",
785 "Arbitrarily chosing " << i
->second
[0]->info
->name
786 << " among multiple implementations for " << i
->first
);
788 cppu::ContextEntry_Init(
789 "/singletons/" + i
->first
,
791 css::uno::Reference
<css::lang::XSingleComponentFactory
> >(
792 new SingletonFactory(this, i
->second
[0])),
797 void cppuhelper::ServiceManager::loadImplementation(
798 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
799 boost::shared_ptr
< Data::Implementation
> & implementation
)
801 assert(implementation
.get() != 0);
803 osl::MutexGuard
g(rBHelper
.rMutex
);
804 if (implementation
->status
== Data::Implementation::STATUS_LOADED
) {
810 uri
= cppu::bootstrap_expandUri(implementation
->info
->uri
);
811 } catch (css::lang::IllegalArgumentException
& e
) {
812 throw css::uno::DeploymentException(
813 "Cannot expand URI" + implementation
->info
->uri
+ ": " + e
.Message
,
814 static_cast< cppu::OWeakObject
* >(this));
816 cppuhelper::ImplementationConstructorFn
* ctor
= 0;
817 css::uno::Reference
< css::uno::XInterface
> f0
;
818 // Special handling of SharedLibrary loader, with support for environment,
819 // constructor, and prefix arguments:
820 if (!implementation
->info
->alienContext
.is()
821 && implementation
->info
->loader
== "com.sun.star.loader.SharedLibrary")
823 cppuhelper::detail::loadSharedLibComponentFactory(
824 uri
, implementation
->info
->environment
,
825 implementation
->info
->prefix
, implementation
->info
->name
,
826 implementation
->info
->constructor
, this, &ctor
, &f0
);
828 assert(!implementation
->info
->environment
.isEmpty());
829 css::uno::Environment
curEnv(css::uno::Environment::getCurrent());
830 css::uno::Environment
env(
831 cppuhelper::detail::getEnvironment(
832 implementation
->info
->environment
,
833 implementation
->info
->name
));
834 if (!(curEnv
.is() && env
.is())) {
835 throw css::uno::DeploymentException(
836 "cannot get environments",
837 css::uno::Reference
<css::uno::XInterface
>());
839 if (curEnv
.get() != env
.get()) {
845 !implementation
->info
->environment
.isEmpty(), "cppuhelper",
846 "Loader " << implementation
->info
->loader
847 << " and non-empty environment "
848 << implementation
->info
->environment
);
850 !implementation
->info
->prefix
.isEmpty(), "cppuhelper",
851 "Loader " << implementation
->info
->loader
852 << " and non-empty constructor "
853 << implementation
->info
->constructor
);
855 !implementation
->info
->prefix
.isEmpty(), "cppuhelper",
856 "Loader " << implementation
->info
->loader
857 << " and non-empty prefix " << implementation
->info
->prefix
);
858 css::uno::Reference
< css::uno::XComponentContext
> ctxt
;
859 css::uno::Reference
< css::lang::XMultiComponentFactory
> smgr
;
860 if (implementation
->info
->alienContext
.is()) {
861 ctxt
= implementation
->info
->alienContext
;
862 smgr
= css::uno::Reference
< css::lang::XMultiComponentFactory
>(
863 ctxt
->getServiceManager(), css::uno::UNO_SET_THROW
);
865 assert(context
.is());
869 css::uno::Reference
< css::loader::XImplementationLoader
> loader(
870 smgr
->createInstanceWithContext(implementation
->info
->loader
, ctxt
),
871 css::uno::UNO_QUERY_THROW
);
872 f0
= loader
->activate(
873 implementation
->info
->name
, rtl::OUString(), uri
,
874 css::uno::Reference
< css::registry::XRegistryKey
>());
876 css::uno::Reference
<css::lang::XSingleComponentFactory
> f1
;
877 css::uno::Reference
<css::lang::XSingleServiceFactory
> f2
;
879 f1
.set(f0
, css::uno::UNO_QUERY
);
881 f2
.set(f0
, css::uno::UNO_QUERY
);
883 throw css::uno::DeploymentException(
884 ("Implementation " + implementation
->info
->name
885 + " does not provide a constructor or factory"),
886 static_cast< cppu::OWeakObject
* >(this));
890 //TODO: There is a race here, as the relevant service factory can be removed
891 // while the mutex is unlocked and loading can thus fail, as the entity from
892 // which to load can disappear once the service factory is removed.
893 osl::MutexGuard
g(rBHelper
.rMutex
);
895 || implementation
->status
== Data::Implementation::STATUS_LOADED
))
897 implementation
->status
= Data::Implementation::STATUS_LOADED
;
898 implementation
->constructor
= ctor
;
899 implementation
->factory1
= f1
;
900 implementation
->factory2
= f2
;
904 void cppuhelper::ServiceManager::disposing() {
905 std::vector
< css::uno::Reference
<css::lang::XComponent
> > sngls
;
906 std::vector
< css::uno::Reference
< css::lang::XComponent
> > comps
;
909 osl::MutexGuard
g(rBHelper
.rMutex
);
910 for (Data::NamedImplementations::const_iterator
i(
911 data_
.namedImplementations
.begin());
912 i
!= data_
.namedImplementations
.end(); ++i
)
914 assert(i
->second
.get() != 0);
915 if (!i
->second
->info
->singletons
.empty()) {
916 osl::MutexGuard
g2(i
->second
->mutex
);
917 if (i
->second
->disposeSingleton
.is()) {
918 sngls
.push_back(i
->second
->disposeSingleton
);
922 for (Data::DynamicImplementations::const_iterator
i(
923 data_
.dynamicImplementations
.begin());
924 i
!= data_
.dynamicImplementations
.end(); ++i
)
926 assert(i
->second
.get() != 0);
927 if (!i
->second
->info
->singletons
.empty()) {
928 osl::MutexGuard
g2(i
->second
->mutex
);
929 if (i
->second
->disposeSingleton
.is()) {
930 sngls
.push_back(i
->second
->disposeSingleton
);
933 if (i
->second
->component
.is()) {
934 comps
.push_back(i
->second
->component
);
937 data_
.namedImplementations
.swap(clear
.namedImplementations
);
938 data_
.dynamicImplementations
.swap(clear
.dynamicImplementations
);
939 data_
.services
.swap(clear
.services
);
940 data_
.singletons
.swap(clear
.singletons
);
943 css::uno::Reference
<css::lang::XComponent
> >::const_iterator
i(
945 i
!= sngls
.end(); ++i
)
949 } catch (css::uno::RuntimeException
& e
) {
952 "Ignoring RuntimeException \"" << e
.Message
953 << "\" while disposing singleton");
957 css::uno::Reference
< css::lang::XComponent
> >::const_iterator
i(
959 i
!= comps
.end(); ++i
)
961 removeEventListenerFromComponent(*i
);
965 rtl::OUString
cppuhelper::ServiceManager::getImplementationName()
966 throw (css::uno::RuntimeException
, std::exception
)
968 return rtl::OUString(
969 "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager");
972 sal_Bool
cppuhelper::ServiceManager::supportsService(
973 rtl::OUString
const & ServiceName
)
974 throw (css::uno::RuntimeException
, std::exception
)
976 return cppu::supportsService(this, ServiceName
);
979 css::uno::Sequence
< rtl::OUString
>
980 cppuhelper::ServiceManager::getSupportedServiceNames()
981 throw (css::uno::RuntimeException
, std::exception
)
983 css::uno::Sequence
< rtl::OUString
> names(2);
984 names
[0] = "com.sun.star.lang.MultiServiceFactory";
985 names
[1] = "com.sun.star.lang.ServiceManager";
989 css::uno::Reference
< css::uno::XInterface
>
990 cppuhelper::ServiceManager::createInstance(
991 rtl::OUString
const & aServiceSpecifier
)
992 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
994 assert(context_
.is());
995 return createInstanceWithContext(aServiceSpecifier
, context_
);
998 css::uno::Reference
< css::uno::XInterface
>
999 cppuhelper::ServiceManager::createInstanceWithArguments(
1000 rtl::OUString
const & ServiceSpecifier
,
1001 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
1002 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
1004 assert(context_
.is());
1005 return createInstanceWithArgumentsAndContext(
1006 ServiceSpecifier
, Arguments
, context_
);
1009 css::uno::Sequence
< rtl::OUString
>
1010 cppuhelper::ServiceManager::getAvailableServiceNames()
1011 throw (css::uno::RuntimeException
, std::exception
)
1013 osl::MutexGuard
g(rBHelper
.rMutex
);
1015 return css::uno::Sequence
< rtl::OUString
>();
1017 Data::ImplementationMap::size_type n
= data_
.services
.size();
1018 if (n
> static_cast< sal_uInt32
>(SAL_MAX_INT32
)) {
1019 throw css::uno::RuntimeException(
1020 "getAvailableServiceNames: too many services",
1021 static_cast< cppu::OWeakObject
* >(this));
1023 css::uno::Sequence
< rtl::OUString
> names(static_cast< sal_Int32
>(n
));
1025 for (Data::ImplementationMap::const_iterator
j(data_
.services
.begin());
1026 j
!= data_
.services
.end(); ++j
)
1028 names
[i
++] = j
->first
;
1030 assert(i
== names
.getLength());
1034 css::uno::Reference
< css::uno::XInterface
>
1035 cppuhelper::ServiceManager::createInstanceWithContext(
1036 rtl::OUString
const & aServiceSpecifier
,
1037 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
1038 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
1040 boost::shared_ptr
< Data::Implementation
> impl(
1041 findServiceImplementation(Context
, aServiceSpecifier
));
1042 return impl
.get() == 0
1043 ? css::uno::Reference
< css::uno::XInterface
>()
1044 : impl
->createInstance(Context
, false);
1047 css::uno::Reference
< css::uno::XInterface
>
1048 cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
1049 rtl::OUString
const & ServiceSpecifier
,
1050 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
1051 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
1052 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
1054 boost::shared_ptr
< Data::Implementation
> impl(
1055 findServiceImplementation(Context
, ServiceSpecifier
));
1056 return impl
.get() == 0
1057 ? css::uno::Reference
< css::uno::XInterface
>()
1058 : impl
->createInstanceWithArguments(Context
, false, Arguments
);
1061 css::uno::Type
cppuhelper::ServiceManager::getElementType()
1062 throw (css::uno::RuntimeException
, std::exception
)
1064 return css::uno::Type();
1067 sal_Bool
cppuhelper::ServiceManager::hasElements()
1068 throw (css::uno::RuntimeException
, std::exception
)
1070 osl::MutexGuard
g(rBHelper
.rMutex
);
1072 !(data_
.namedImplementations
.empty()
1073 && data_
.dynamicImplementations
.empty());
1076 css::uno::Reference
< css::container::XEnumeration
>
1077 cppuhelper::ServiceManager::createEnumeration()
1078 throw (css::uno::RuntimeException
, std::exception
)
1080 throw css::uno::RuntimeException(
1081 "ServiceManager createEnumeration: method not supported",
1082 static_cast< cppu::OWeakObject
* >(this));
1085 sal_Bool
cppuhelper::ServiceManager::has(css::uno::Any
const &)
1086 throw (css::uno::RuntimeException
, std::exception
)
1088 throw css::uno::RuntimeException(
1089 "ServiceManager has: method not supported",
1090 static_cast< cppu::OWeakObject
* >(this));
1093 void cppuhelper::ServiceManager::insert(css::uno::Any
const & aElement
)
1095 css::lang::IllegalArgumentException
,
1096 css::container::ElementExistException
, css::uno::RuntimeException
, std::exception
)
1098 css::uno::Sequence
< css::beans::NamedValue
> args
;
1099 if (aElement
>>= args
) {
1100 std::vector
< rtl::OUString
> uris
;
1101 css::uno::Reference
< css::uno::XComponentContext
> alienContext
;
1102 for (sal_Int32 i
= 0; i
< args
.getLength(); ++i
) {
1103 if (args
[i
].Name
== "uri") {
1105 if (!(args
[i
].Value
>>= uri
)) {
1106 throw css::lang::IllegalArgumentException(
1108 static_cast< cppu::OWeakObject
* >(this), 0);
1110 uris
.push_back(uri
);
1111 } else if (args
[i
].Name
== "component-context") {
1112 if (alienContext
.is()) {
1113 throw css::lang::IllegalArgumentException(
1114 "Multiple component-context arguments",
1115 static_cast< cppu::OWeakObject
* >(this), 0);
1117 if (!(args
[i
].Value
>>= alienContext
) || !alienContext
.is()) {
1118 throw css::lang::IllegalArgumentException(
1119 "Bad component-context argument",
1120 static_cast< cppu::OWeakObject
* >(this), 0);
1123 throw css::lang::IllegalArgumentException(
1124 "Bad argument " + args
[i
].Name
,
1125 static_cast< cppu::OWeakObject
* >(this), 0);
1128 insertRdbFiles(uris
, alienContext
);
1131 css::uno::Reference
< css::lang::XServiceInfo
> info
;
1132 if ((aElement
>>= info
) && info
.is()) {
1133 insertLegacyFactory(info
);
1136 // At least revisions up to 1.7 of LanguageTool.oxt (incl. the bundled 1.4.0 in
1137 // module languagetool) contain an (actively registered) factory that does not
1138 // implement XServiceInfo (see <http://sourceforge.net/tracker/?
1139 // func=detail&aid=3526635&group_id=110216&atid=655717> "SingletonFactory should
1140 // implement XServiceInfo"); the old OServiceManager::insert
1141 // (stoc/source/servicemanager/servicemanager.cxx) silently did not add such
1142 // broken factories to its m_ImplementationNameMap, so ignore them here for
1143 // backwards compatibility of live-insertion of extensions, too.
1145 // (The plan was that this warning would go away (and we would do the
1146 // throw instead) for the incompatible LO 4, but we changed our mind):
1147 css::uno::Reference
< css::lang::XSingleComponentFactory
> legacy
;
1148 if ((aElement
>>= legacy
) && legacy
.is()) {
1151 "Ignored XSingleComponentFactory not implementing XServiceInfo");
1155 throw css::lang::IllegalArgumentException(
1156 "Bad insert element", static_cast< cppu::OWeakObject
* >(this), 0);
1159 void cppuhelper::ServiceManager::remove(css::uno::Any
const & aElement
)
1161 css::lang::IllegalArgumentException
,
1162 css::container::NoSuchElementException
, css::uno::RuntimeException
, std::exception
)
1164 css::uno::Sequence
< css::beans::NamedValue
> args
;
1165 if (aElement
>>= args
) {
1166 std::vector
< rtl::OUString
> uris
;
1167 for (sal_Int32 i
= 0; i
< args
.getLength(); ++i
) {
1168 if (args
[i
].Name
== "uri") {
1170 if (!(args
[i
].Value
>>= uri
)) {
1171 throw css::lang::IllegalArgumentException(
1173 static_cast< cppu::OWeakObject
* >(this), 0);
1175 uris
.push_back(uri
);
1177 throw css::lang::IllegalArgumentException(
1178 "Bad argument " + args
[i
].Name
,
1179 static_cast< cppu::OWeakObject
* >(this), 0);
1182 removeRdbFiles(uris
);
1185 css::uno::Reference
< css::lang::XServiceInfo
> info
;
1186 if ((aElement
>>= info
) && info
.is()) {
1187 if (!removeLegacyFactory(info
, true)) {
1188 throw css::container::NoSuchElementException(
1189 "Remove non-inserted factory object",
1190 static_cast< cppu::OWeakObject
* >(this));
1195 if (aElement
>>= impl
) {
1196 // For live-removal of extensions:
1197 removeImplementation(impl
);
1200 throw css::lang::IllegalArgumentException(
1201 "Bad remove element", static_cast< cppu::OWeakObject
* >(this), 0);
1204 css::uno::Reference
< css::container::XEnumeration
>
1205 cppuhelper::ServiceManager::createContentEnumeration(
1206 rtl::OUString
const & aServiceName
)
1207 throw (css::uno::RuntimeException
, std::exception
)
1209 std::vector
< boost::shared_ptr
< Data::Implementation
> > impls
;
1211 osl::MutexGuard
g(rBHelper
.rMutex
);
1212 Data::ImplementationMap::const_iterator
i(
1213 data_
.services
.find(aServiceName
));
1214 if (i
!= data_
.services
.end()) {
1218 std::vector
< css::uno::Any
> factories
;
1220 boost::shared_ptr
< Data::Implementation
> >::const_iterator
i(
1222 i
!= impls
.end(); ++i
)
1224 Data::Implementation
* impl
= i
->get();
1227 osl::MutexGuard
g(rBHelper
.rMutex
);
1232 if (impl
->status
== Data::Implementation::STATUS_NEW
) {
1233 // Postpone actual implementation instantiation as long as
1234 // possible (so that e.g. opening LO's "Tools - Macros" menu
1235 // does not try to instantiate a JVM, which can lead to a
1236 // synchronous error dialog when no JVM is specified, and
1237 // showing the dialog while hovering over a menu can cause
1239 impl
->factory1
= new ImplementationWrapper(this, *i
);
1240 impl
->status
= Data::Implementation::STATUS_WRAPPER
;
1243 if (impl
->factory1
.is()) {
1244 factories
.push_back(css::uno::makeAny(impl
->factory1
));
1245 } else if (impl
->factory2
.is()) {
1246 factories
.push_back(css::uno::makeAny(impl
->factory2
));
1248 css::uno::Reference
< css::lang::XSingleComponentFactory
> factory(
1249 new ImplementationWrapper(this, *i
));
1250 factories
.push_back(css::uno::makeAny(factory
));
1253 return new ContentEnumeration(factories
);
1256 css::uno::Reference
< css::beans::XPropertySetInfo
>
1257 cppuhelper::ServiceManager::getPropertySetInfo()
1258 throw (css::uno::RuntimeException
, std::exception
)
1263 void cppuhelper::ServiceManager::setPropertyValue(
1264 rtl::OUString
const & aPropertyName
, css::uno::Any
const &)
1266 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1267 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1268 css::uno::RuntimeException
, std::exception
)
1270 if (aPropertyName
== "DefaultContext") {
1271 throw css::beans::PropertyVetoException(
1272 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1274 throw css::beans::UnknownPropertyException(
1275 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1279 css::uno::Any
cppuhelper::ServiceManager::getPropertyValue(
1280 rtl::OUString
const & PropertyName
)
1282 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1283 css::uno::RuntimeException
, std::exception
)
1285 if (PropertyName
!= "DefaultContext") {
1286 throw css::beans::UnknownPropertyException(
1287 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1289 assert(context_
.is());
1290 return css::uno::makeAny(context_
);
1293 void cppuhelper::ServiceManager::addPropertyChangeListener(
1294 rtl::OUString
const & aPropertyName
,
1295 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
1298 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1299 css::uno::RuntimeException
, std::exception
)
1301 if (!aPropertyName
.isEmpty() && aPropertyName
!= "DefaultContext") {
1302 throw css::beans::UnknownPropertyException(
1303 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1305 // DefaultContext does not change, so just treat it as an event listener:
1306 return addEventListener(xListener
);
1309 void cppuhelper::ServiceManager::removePropertyChangeListener(
1310 rtl::OUString
const & aPropertyName
,
1311 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
1314 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1315 css::uno::RuntimeException
, std::exception
)
1317 if (!aPropertyName
.isEmpty() && aPropertyName
!= "DefaultContext") {
1318 throw css::beans::UnknownPropertyException(
1319 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1321 // DefaultContext does not change, so just treat it as an event listener:
1322 return removeEventListener(aListener
);
1325 void cppuhelper::ServiceManager::addVetoableChangeListener(
1326 rtl::OUString
const & PropertyName
,
1327 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
1330 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1331 css::uno::RuntimeException
, std::exception
)
1333 if (!PropertyName
.isEmpty() && PropertyName
!= "DefaultContext") {
1334 throw css::beans::UnknownPropertyException(
1335 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1337 // DefaultContext does not change, so just treat it as an event listener:
1338 return addEventListener(aListener
);
1341 void cppuhelper::ServiceManager::removeVetoableChangeListener(
1342 rtl::OUString
const & PropertyName
,
1343 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
1346 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1347 css::uno::RuntimeException
, std::exception
)
1349 if (!PropertyName
.isEmpty() && PropertyName
!= "DefaultContext") {
1350 throw css::beans::UnknownPropertyException(
1351 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1353 // DefaultContext does not change, so just treat it as an event listener:
1354 return removeEventListener(aListener
);
1357 css::uno::Sequence
< css::beans::Property
>
1358 cppuhelper::ServiceManager::getProperties() throw (css::uno::RuntimeException
, std::exception
) {
1359 css::uno::Sequence
< css::beans::Property
> props(1);
1360 props
[0] = getDefaultContextProperty();
1364 css::beans::Property
cppuhelper::ServiceManager::getPropertyByName(
1365 rtl::OUString
const & aName
)
1366 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
, std::exception
)
1368 if (aName
!= "DefaultContext") {
1369 throw css::beans::UnknownPropertyException(
1370 aName
, static_cast< cppu::OWeakObject
* >(this));
1372 return getDefaultContextProperty();
1375 sal_Bool
cppuhelper::ServiceManager::hasPropertyByName(
1376 rtl::OUString
const & Name
)
1377 throw (css::uno::RuntimeException
, std::exception
)
1379 return Name
== "DefaultContext";
1382 void cppuhelper::ServiceManager::disposing(
1383 css::lang::EventObject
const & Source
)
1384 throw (css::uno::RuntimeException
, std::exception
)
1386 removeLegacyFactory(
1387 css::uno::Reference
< css::lang::XServiceInfo
>(
1388 Source
.Source
, css::uno::UNO_QUERY_THROW
),
1392 void cppuhelper::ServiceManager::removeEventListenerFromComponent(
1393 css::uno::Reference
< css::lang::XComponent
> const & component
)
1395 assert(component
.is());
1397 component
->removeEventListener(this);
1398 } catch (css::uno::RuntimeException
& e
) {
1401 "Ignored removeEventListener RuntimeException " + e
.Message
);
1405 void cppuhelper::ServiceManager::readRdbs(rtl::OUString
const & uris
) {
1406 for (sal_Int32 i
= 0; i
!= -1;) {
1407 rtl::OUString
uri(uris
.getToken(0, ' ', i
));
1408 if (uri
.isEmpty()) {
1413 cppu::decodeRdbUri(&uri
, &optional
, &directory
);
1415 readRdbDirectory(uri
, optional
);
1417 readRdbFile(uri
, optional
);
1422 void cppuhelper::ServiceManager::readRdbDirectory(
1423 rtl::OUString
const & uri
, bool optional
)
1425 osl::Directory
dir(uri
);
1426 switch (dir
.open()) {
1427 case osl::FileBase::E_None
:
1429 case osl::FileBase::E_NOENT
:
1431 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
1436 throw css::uno::DeploymentException(
1437 "Cannot open directory " + uri
,
1438 static_cast< cppu::OWeakObject
* >(this));
1442 if (!cppu::nextDirectoryItem(dir
, &url
)) {
1445 readRdbFile(url
, false);
1449 void cppuhelper::ServiceManager::readRdbFile(
1450 rtl::OUString
const & uri
, bool optional
)
1454 uri
, css::uno::Reference
< css::uno::XComponentContext
>(), &data_
);
1455 } catch (css::container::NoSuchElementException
&) {
1457 throw css::uno::DeploymentException(
1458 uri
+ ": no such file",
1459 static_cast< cppu::OWeakObject
* >(this));
1461 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
1462 } catch (css::registry::InvalidRegistryException
& e
) {
1463 if (!readLegacyRdbFile(uri
)) {
1464 throw css::uno::DeploymentException(
1465 "InvalidRegistryException: " + e
.Message
,
1466 static_cast< cppu::OWeakObject
* >(this));
1468 } catch (css::uno::RuntimeException
&) {
1469 if (!readLegacyRdbFile(uri
)) {
1475 bool cppuhelper::ServiceManager::readLegacyRdbFile(rtl::OUString
const & uri
) {
1477 switch (reg
.open(uri
, REG_READONLY
)) {
1480 case REG_REGISTRY_NOT_EXISTS
:
1481 case REG_INVALID_REGISTRY
:
1483 // Ignore empty rdb files (which are at least seen by subordinate
1484 // uno processes during extension registration; Registry::open can
1485 // fail on them if mmap(2) returns EINVAL for a zero length):
1486 osl::DirectoryItem item
;
1487 if (osl::DirectoryItem::get(uri
, item
) == osl::FileBase::E_None
) {
1488 osl::FileStatus
status(osl_FileStatus_Mask_FileSize
);
1489 if (item
.getFileStatus(status
) == osl::FileBase::E_None
1490 && status
.getFileSize() == 0)
1500 RegistryKey rootKey
;
1501 if (reg
.openRootKey(rootKey
) != REG_NO_ERROR
) {
1502 throw css::uno::DeploymentException(
1503 "Failure reading legacy rdb file " + uri
,
1504 static_cast< cppu::OWeakObject
* >(this));
1506 RegistryKeyArray impls
;
1507 switch (rootKey
.openSubKeys("IMPLEMENTATIONS", impls
)) {
1510 case REG_KEY_NOT_EXISTS
:
1513 throw css::uno::DeploymentException(
1514 "Failure reading legacy rdb file " + uri
,
1515 static_cast< cppu::OWeakObject
* >(this));
1517 for (sal_uInt32 i
= 0; i
!= impls
.getLength(); ++i
) {
1518 RegistryKey
implKey(impls
.getElement(i
));
1519 assert(implKey
.getName().match("/IMPLEMENTATIONS/"));
1521 implKey
.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1522 boost::shared_ptr
< Data::Implementation
> impl(
1523 new Data::Implementation(
1524 name
, readLegacyRdbString(uri
, implKey
, "UNO/ACTIVATOR"),
1525 readLegacyRdbString(uri
, implKey
, "UNO/LOCATION"), "", "", "",
1526 css::uno::Reference
< css::uno::XComponentContext
>(), uri
));
1527 if (!data_
.namedImplementations
.insert(
1528 Data::NamedImplementations::value_type(name
, impl
)).
1531 throw css::registry::InvalidRegistryException(
1532 uri
+ ": duplicate <implementation name=\"" + name
+ "\">",
1533 css::uno::Reference
< css::uno::XInterface
>());
1535 readLegacyRdbStrings(
1536 uri
, implKey
, "UNO/SERVICES", &impl
->info
->services
);
1537 for (std::vector
< rtl::OUString
>::const_iterator
j(
1538 impl
->info
->services
.begin());
1539 j
!= impl
->info
->services
.end(); ++j
)
1541 data_
.services
[*j
].push_back(impl
);
1543 readLegacyRdbStrings(
1544 uri
, implKey
, "UNO/SINGLETONS", &impl
->info
->singletons
);
1545 for (std::vector
< rtl::OUString
>::const_iterator
j(
1546 impl
->info
->singletons
.begin());
1547 j
!= impl
->info
->singletons
.end(); ++j
)
1549 data_
.singletons
[*j
].push_back(impl
);
1555 rtl::OUString
cppuhelper::ServiceManager::readLegacyRdbString(
1556 rtl::OUString
const & uri
, RegistryKey
& key
, rtl::OUString
const & path
)
1561 if (key
.openKey(path
, subkey
) != REG_NO_ERROR
1562 || subkey
.getValueInfo(rtl::OUString(), &t
, &s
) != REG_NO_ERROR
1563 || t
!= RG_VALUETYPE_STRING
1564 || s
== 0 || s
> static_cast< sal_uInt32
>(SAL_MAX_INT32
))
1566 throw css::uno::DeploymentException(
1567 "Failure reading legacy rdb file " + uri
,
1568 static_cast< cppu::OWeakObject
* >(this));
1571 std::vector
< char > v(s
); // assuming sal_uInt32 fits into vector::size_type
1572 if (subkey
.getValue(rtl::OUString(), &v
[0]) != REG_NO_ERROR
1574 || !rtl_convertStringToUString(
1575 &val
.pData
, &v
[0], static_cast< sal_Int32
>(s
- 1),
1576 RTL_TEXTENCODING_UTF8
,
1577 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1578 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1579 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
)))
1581 throw css::uno::DeploymentException(
1582 "Failure reading legacy rdb file " + uri
,
1583 static_cast< cppu::OWeakObject
* >(this));
1588 void cppuhelper::ServiceManager::readLegacyRdbStrings(
1589 rtl::OUString
const & uri
, RegistryKey
& key
, rtl::OUString
const & path
,
1590 std::vector
< rtl::OUString
> * strings
)
1592 assert(strings
!= 0);
1594 switch (key
.openKey(path
, subkey
)) {
1597 case REG_KEY_NOT_EXISTS
:
1600 throw css::uno::DeploymentException(
1601 "Failure reading legacy rdb file " + uri
,
1602 static_cast< cppu::OWeakObject
* >(this));
1604 rtl::OUString
prefix(subkey
.getName() + "/");
1605 RegistryKeyNames names
;
1606 if (subkey
.getKeyNames(rtl::OUString(), names
) != REG_NO_ERROR
) {
1607 throw css::uno::DeploymentException(
1608 "Failure reading legacy rdb file " + uri
,
1609 static_cast< cppu::OWeakObject
* >(this));
1611 for (sal_uInt32 i
= 0; i
!= names
.getLength(); ++i
) {
1612 assert(names
.getElement(i
).match(prefix
));
1613 strings
->push_back(names
.getElement(i
).copy(prefix
.getLength()));
1617 void cppuhelper::ServiceManager::insertRdbFiles(
1618 std::vector
< rtl::OUString
> const & uris
,
1619 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
)
1622 for (std::vector
< rtl::OUString
>::const_iterator
i(uris
.begin());
1623 i
!= uris
.end(); ++i
)
1626 Parser(*i
, alienContext
, &extra
);
1627 } catch (css::container::NoSuchElementException
&) {
1628 throw css::lang::IllegalArgumentException(
1629 *i
+ ": no such file", static_cast< cppu::OWeakObject
* >(this),
1631 } catch (css::registry::InvalidRegistryException
& e
) {
1632 throw css::lang::IllegalArgumentException(
1633 "InvalidRegistryException: " + e
.Message
,
1634 static_cast< cppu::OWeakObject
* >(this), 0);
1637 insertExtraData(extra
);
1640 void cppuhelper::ServiceManager::insertLegacyFactory(
1641 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
)
1643 assert(factoryInfo
.is());
1644 rtl::OUString
name(factoryInfo
->getImplementationName());
1645 css::uno::Reference
< css::lang::XSingleComponentFactory
> f1(
1646 factoryInfo
, css::uno::UNO_QUERY
);
1647 css::uno::Reference
< css::lang::XSingleServiceFactory
> f2
;
1649 f2
= css::uno::Reference
< css::lang::XSingleServiceFactory
>(
1650 factoryInfo
, css::uno::UNO_QUERY
);
1652 throw css::lang::IllegalArgumentException(
1653 ("Bad XServiceInfo argument implements neither"
1654 " XSingleComponentFactory nor XSingleServiceFactory"),
1655 static_cast< cppu::OWeakObject
* >(this), 0);
1658 css::uno::Reference
< css::lang::XComponent
> comp(
1659 factoryInfo
, css::uno::UNO_QUERY
);
1660 boost::shared_ptr
< Data::Implementation
> impl(
1661 new Data::Implementation(name
, f1
, f2
, comp
));
1663 if (!name
.isEmpty()) {
1664 extra
.namedImplementations
.insert(
1665 Data::NamedImplementations::value_type(name
, impl
));
1667 extra
.dynamicImplementations
.insert(
1668 Data::DynamicImplementations::value_type(factoryInfo
, impl
));
1669 css::uno::Sequence
< rtl::OUString
> services(
1670 factoryInfo
->getSupportedServiceNames());
1671 for (sal_Int32 i
= 0; i
!= services
.getLength(); ++i
) {
1672 impl
->info
->services
.push_back(services
[i
]);
1673 extra
.services
[services
[i
]].push_back(impl
);
1675 if (insertExtraData(extra
) && comp
.is()) {
1676 comp
->addEventListener(this);
1680 bool cppuhelper::ServiceManager::insertExtraData(Data
const & extra
) {
1682 osl::MutexGuard
g(rBHelper
.rMutex
);
1686 for (Data::NamedImplementations::const_iterator
i(
1687 extra
.namedImplementations
.begin());
1688 i
!= extra
.namedImplementations
.end(); ++i
)
1690 if (data_
.namedImplementations
.find(i
->first
)
1691 != data_
.namedImplementations
.end())
1693 throw css::lang::IllegalArgumentException(
1694 "Insert duplicate implementation name " + i
->first
,
1695 static_cast< cppu::OWeakObject
* >(this), 0);
1698 for (Data::DynamicImplementations::const_iterator
i(
1699 extra
.dynamicImplementations
.begin());
1700 i
!= extra
.dynamicImplementations
.end(); ++i
)
1702 if (data_
.dynamicImplementations
.find(i
->first
)
1703 != data_
.dynamicImplementations
.end())
1705 throw css::lang::IllegalArgumentException(
1706 "Insert duplicate factory object",
1707 static_cast< cppu::OWeakObject
* >(this), 0);
1710 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1711 data_
.namedImplementations
.insert(
1712 extra
.namedImplementations
.begin(),
1713 extra
.namedImplementations
.end());
1714 data_
.dynamicImplementations
.insert(
1715 extra
.dynamicImplementations
.begin(),
1716 extra
.dynamicImplementations
.end());
1717 insertImplementationMap(&data_
.services
, extra
.services
);
1718 insertImplementationMap(&data_
.singletons
, extra
.singletons
);
1720 //TODO: Updating the component context singleton data should be part of the
1721 // atomic service manager update:
1722 if (!extra
.singletons
.empty()) {
1723 assert(context_
.is());
1724 css::uno::Reference
< css::container::XNameContainer
> cont(
1725 context_
, css::uno::UNO_QUERY_THROW
);
1726 for (Data::ImplementationMap::const_iterator
i(
1727 extra
.singletons
.begin());
1728 i
!= extra
.singletons
.end(); ++i
)
1730 rtl::OUString
name("/singletons/" + i
->first
);
1731 //TODO: Update should be atomic:
1733 cont
->removeByName(name
+ "/arguments");
1734 } catch (const css::container::NoSuchElementException
&) {}
1735 assert(!i
->second
.empty());
1736 assert(i
->second
[0].get() != 0);
1738 i
->second
.size() > 1, "cppuhelper",
1739 "Arbitrarily chosing " << i
->second
[0]->info
->name
1740 << " among multiple implementations for singleton "
1744 name
+ "/service", css::uno::Any(i
->second
[0]->info
->name
));
1745 } catch (css::container::ElementExistException
&) {
1746 cont
->replaceByName(
1747 name
+ "/service", css::uno::Any(i
->second
[0]->info
->name
));
1750 cont
->insertByName(name
, css::uno::Any());
1751 } catch (css::container::ElementExistException
&) {
1752 SAL_INFO("cppuhelper", "Overwriting singleton " << i
->first
);
1753 cont
->replaceByName(name
, css::uno::Any());
1760 void cppuhelper::ServiceManager::removeRdbFiles(
1761 std::vector
< rtl::OUString
> const & uris
)
1763 // The underlying data structures make this function somewhat inefficient,
1764 // but the assumption is that it is rarely called (and that if it is called,
1765 // it is called with a uris vector of size one):
1766 std::vector
< boost::shared_ptr
< Data::Implementation
> > clear
;
1768 osl::MutexGuard
g(rBHelper
.rMutex
);
1769 for (std::vector
< rtl::OUString
>::const_iterator
i(uris
.begin());
1770 i
!= uris
.end(); ++i
)
1772 for (Data::NamedImplementations::iterator
j(
1773 data_
.namedImplementations
.begin());
1774 j
!= data_
.namedImplementations
.end();)
1776 assert(j
->second
.get() != 0);
1777 if (j
->second
->info
->rdbFile
== *i
) {
1778 clear
.push_back(j
->second
);
1779 //TODO: The below leaves data_ in an inconsistent state upon
1781 removeFromImplementationMap(
1782 &data_
.services
, j
->second
->info
->services
, j
->second
);
1783 removeFromImplementationMap(
1784 &data_
.singletons
, j
->second
->info
->singletons
,
1786 data_
.namedImplementations
.erase(j
++);
1793 //TODO: Update the component context singleton data
1796 bool cppuhelper::ServiceManager::removeLegacyFactory(
1797 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
,
1798 bool removeListener
)
1800 assert(factoryInfo
.is());
1801 boost::shared_ptr
< Data::Implementation
> clear
;
1802 css::uno::Reference
< css::lang::XComponent
> comp
;
1804 osl::MutexGuard
g(rBHelper
.rMutex
);
1805 Data::DynamicImplementations::iterator
i(
1806 data_
.dynamicImplementations
.find(factoryInfo
));
1807 if (i
== data_
.dynamicImplementations
.end()) {
1808 return isDisposed();
1810 assert(i
->second
.get() != 0);
1812 if (removeListener
) {
1813 comp
= i
->second
->component
;
1815 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1816 removeFromImplementationMap(
1817 &data_
.services
, i
->second
->info
->services
, i
->second
);
1818 removeFromImplementationMap(
1819 &data_
.singletons
, i
->second
->info
->singletons
, i
->second
);
1820 if (!i
->second
->info
->name
.isEmpty()) {
1821 data_
.namedImplementations
.erase(i
->second
->info
->name
);
1823 data_
.dynamicImplementations
.erase(i
);
1826 removeEventListenerFromComponent(comp
);
1831 void cppuhelper::ServiceManager::removeImplementation(const rtl::OUString
& name
) {
1832 // The underlying data structures make this function somewhat inefficient,
1833 // but the assumption is that it is rarely called:
1834 boost::shared_ptr
< Data::Implementation
> clear
;
1836 osl::MutexGuard
g(rBHelper
.rMutex
);
1840 Data::NamedImplementations::iterator
i(
1841 data_
.namedImplementations
.find(name
));
1842 if (i
== data_
.namedImplementations
.end()) {
1843 throw css::container::NoSuchElementException(
1844 "Remove non-inserted implementation " + name
,
1845 static_cast< cppu::OWeakObject
* >(this));
1847 assert(i
->second
.get() != 0);
1849 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1850 removeFromImplementationMap(
1851 &data_
.services
, i
->second
->info
->services
, i
->second
);
1852 removeFromImplementationMap(
1853 &data_
.singletons
, i
->second
->info
->singletons
, i
->second
);
1854 for (Data::DynamicImplementations::iterator
j(
1855 data_
.dynamicImplementations
.begin());
1856 j
!= data_
.dynamicImplementations
.end(); ++j
)
1858 if (j
->second
== i
->second
) {
1859 data_
.dynamicImplementations
.erase(j
);
1863 data_
.namedImplementations
.erase(i
);
1867 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
1868 cppuhelper::ServiceManager::findServiceImplementation(
1869 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
1870 rtl::OUString
const & specifier
)
1872 boost::shared_ptr
< Data::Implementation
> impl
;
1875 osl::MutexGuard
g(rBHelper
.rMutex
);
1876 Data::ImplementationMap::const_iterator
i(
1877 data_
.services
.find(specifier
));
1878 if (i
== data_
.services
.end()) {
1879 Data::NamedImplementations::const_iterator
j(
1880 data_
.namedImplementations
.find(specifier
));
1881 if (j
== data_
.namedImplementations
.end()) {
1882 SAL_INFO("cppuhelper", "No implementation for " << specifier
);
1883 return boost::shared_ptr
< Data::Implementation
>();
1887 assert(!i
->second
.empty());
1889 i
->second
.size() > 1, "cppuhelper",
1890 "Arbitrarily chosing " << i
->second
[0]->info
->name
1891 << " among multiple implementations for " << i
->first
);
1892 impl
= i
->second
[0];
1894 assert(impl
.get() != 0);
1895 loaded
= impl
->status
== Data::Implementation::STATUS_LOADED
;
1898 loadImplementation(context
, impl
);
1903 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */