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 <boost/weak_ptr.hpp>
19 #include <com/sun/star/beans/NamedValue.hpp>
20 #include <com/sun/star/beans/PropertyAttribute.hpp>
21 #include <com/sun/star/container/ElementExistException.hpp>
22 #include <com/sun/star/container/XEnumeration.hpp>
23 #include <com/sun/star/container/XNameContainer.hpp>
24 #include <com/sun/star/lang/XInitialization.hpp>
25 #include <com/sun/star/lang/XServiceInfo.hpp>
26 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
27 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
28 #include <com/sun/star/loader/XImplementationLoader.hpp>
29 #include <com/sun/star/registry/InvalidRegistryException.hpp>
30 #include <com/sun/star/uno/DeploymentException.hpp>
31 #include <com/sun/star/uno/Reference.hxx>
32 #include <com/sun/star/uno/XComponentContext.hpp>
33 #include <cppuhelper/bootstrap.hxx>
34 #include <cppuhelper/component_context.hxx>
35 #include <cppuhelper/implbase1.hxx>
36 #include <cppuhelper/implbase3.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");
166 if (res
== xmlreader::XmlReader::RESULT_DONE
) {
169 throw css::registry::InvalidRegistryException(
170 reader_
.getUrl() + ": unexpected item in outer level");
171 case STATE_COMPONENTS
:
172 if (res
== xmlreader::XmlReader::RESULT_END
) {
176 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
177 && name
.equals(RTL_CONSTASCII_STRINGPARAM("component")))
180 state
= STATE_COMPONENT_INITIAL
;
183 throw css::registry::InvalidRegistryException(
184 reader_
.getUrl() + ": unexpected item in <components>");
185 case STATE_COMPONENT
:
186 if (res
== xmlreader::XmlReader::RESULT_END
) {
187 state
= STATE_COMPONENTS
;
191 case STATE_COMPONENT_INITIAL
:
192 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
193 && name
.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
195 handleImplementation();
196 state
= STATE_IMPLEMENTATION
;
199 throw css::registry::InvalidRegistryException(
200 reader_
.getUrl() + ": unexpected item in <component>");
201 case STATE_IMPLEMENTATION
:
202 if (res
== xmlreader::XmlReader::RESULT_END
) {
203 state
= STATE_COMPONENT
;
206 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
207 && name
.equals(RTL_CONSTASCII_STRINGPARAM("service")))
210 state
= STATE_SERVICE
;
213 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
214 && name
.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
217 state
= STATE_SINGLETON
;
220 throw css::registry::InvalidRegistryException(
221 reader_
.getUrl() + ": unexpected item in <implementation>");
223 if (res
== xmlreader::XmlReader::RESULT_END
) {
224 state
= STATE_IMPLEMENTATION
;
227 throw css::registry::InvalidRegistryException(
228 reader_
.getUrl() + ": unexpected item in <service>");
229 case STATE_SINGLETON
:
230 if (res
== xmlreader::XmlReader::RESULT_END
) {
231 state
= STATE_IMPLEMENTATION
;
234 throw css::registry::InvalidRegistryException(
235 reader_
.getUrl() + ": unexpected item in <service>");
240 void Parser::handleComponent() {
241 attrLoader_
= rtl::OUString();
242 attrUri_
= rtl::OUString();
243 attrEnvironment_
= rtl::OUString();
244 attrPrefix_
= rtl::OUString();
245 xmlreader::Span name
;
247 while (reader_
.nextAttribute(&nsId
, &name
)) {
248 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
249 && name
.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
251 if (!attrLoader_
.isEmpty()) {
252 throw css::registry::InvalidRegistryException(
254 + ": <component> has multiple \"loader\" attributes");
256 attrLoader_
= reader_
.getAttributeValue(false).convertFromUtf8();
257 if (attrLoader_
.isEmpty()) {
258 throw css::registry::InvalidRegistryException(
260 + ": <component> has empty \"loader\" attribute");
262 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
263 && name
.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
265 if (!attrUri_
.isEmpty()) {
266 throw css::registry::InvalidRegistryException(
268 + ": <component> has multiple \"uri\" attributes");
270 attrUri_
= reader_
.getAttributeValue(false).convertFromUtf8();
271 if (attrUri_
.isEmpty()) {
272 throw css::registry::InvalidRegistryException(
274 + ": <component> has empty \"uri\" attribute");
276 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
277 && name
.equals(RTL_CONSTASCII_STRINGPARAM("environment")))
279 if (!attrEnvironment_
.isEmpty()) {
280 throw css::registry::InvalidRegistryException(
282 ": <component> has multiple \"environment\" attributes");
284 attrEnvironment_
= reader_
.getAttributeValue(false)
286 if (attrEnvironment_
.isEmpty()) {
287 throw css::registry::InvalidRegistryException(
289 ": <component> has empty \"environment\" attribute");
291 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
292 && name
.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
294 if (!attrPrefix_
.isEmpty()) {
295 throw css::registry::InvalidRegistryException(
297 ": <component> has multiple \"prefix\" attributes");
299 attrPrefix_
= reader_
.getAttributeValue(false).convertFromUtf8();
300 if (attrPrefix_
.isEmpty()) {
301 throw css::registry::InvalidRegistryException(
303 ": <component> has empty \"prefix\" attribute");
306 throw css::registry::InvalidRegistryException(
307 reader_
.getUrl() + ": unexpected attribute \""
308 + name
.convertFromUtf8() + "\" in <component>");
311 if (attrLoader_
.isEmpty()) {
312 throw css::registry::InvalidRegistryException(
313 reader_
.getUrl() + ": <component> is missing \"loader\" attribute");
315 if (attrUri_
.isEmpty()) {
316 throw css::registry::InvalidRegistryException(
317 reader_
.getUrl() + ": <component> is missing \"uri\" attribute");
319 #ifndef DISABLE_DYNLOADING
321 attrUri_
= rtl::Uri::convertRelToAbs(reader_
.getUrl(), attrUri_
);
322 } catch (const rtl::MalformedUriException
& e
) {
323 throw css::registry::InvalidRegistryException(
324 reader_
.getUrl() + ": bad \"uri\" attribute: " + e
.getMessage());
329 void Parser::handleImplementation() {
330 rtl::OUString attrName
;
331 rtl::OUString attrConstructor
;
332 xmlreader::Span name
;
334 while (reader_
.nextAttribute(&nsId
, &name
)) {
335 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
336 && name
.equals(RTL_CONSTASCII_STRINGPARAM("name")))
338 if (!attrName
.isEmpty()) {
339 throw css::registry::InvalidRegistryException(
341 + ": <implementation> has multiple \"name\" attributes");
343 attrName
= reader_
.getAttributeValue(false).convertFromUtf8();
344 if (attrName
.isEmpty()) {
345 throw css::registry::InvalidRegistryException(
347 + ": <implementation> has empty \"name\" attribute");
349 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
350 && name
.equals(RTL_CONSTASCII_STRINGPARAM("constructor")))
352 if (!attrConstructor
.isEmpty()) {
353 throw css::registry::InvalidRegistryException(
355 + ": <implementation> has multiple \"constructor\""
358 attrConstructor
= reader_
.getAttributeValue(false)
360 if (attrConstructor
.isEmpty()) {
361 throw css::registry::InvalidRegistryException(
363 + ": element has empty \"constructor\" attribute");
365 if (attrEnvironment_
.isEmpty()) {
366 throw css::registry::InvalidRegistryException(
368 + ": <implementation> has \"constructor\" attribute but"
369 " <component> has no \"environment\" attribute");
372 throw css::registry::InvalidRegistryException(
373 reader_
.getUrl() + ": unexpected element attribute \""
374 + name
.convertFromUtf8() + "\" in <implementation>");
377 if (attrName
.isEmpty()) {
378 throw css::registry::InvalidRegistryException(
380 + ": <implementation> is missing \"name\" attribute");
382 implementation_
.reset(
383 new cppuhelper::ServiceManager::Data::Implementation(
384 attrName
, attrLoader_
, attrUri_
, attrEnvironment_
, attrConstructor
,
385 attrPrefix_
, alienContext_
, reader_
.getUrl()));
386 if (!data_
->namedImplementations
.insert(
387 cppuhelper::ServiceManager::Data::NamedImplementations::value_type(
388 attrName
, implementation_
)).
391 throw css::registry::InvalidRegistryException(
392 reader_
.getUrl() + ": duplicate <implementation name=\"" + attrName
397 void Parser::handleService() {
398 rtl::OUString
name(getNameAttribute());
399 implementation_
->info
->services
.push_back(name
);
400 data_
->services
[name
].push_back(implementation_
);
403 void Parser::handleSingleton() {
404 rtl::OUString
name(getNameAttribute());
405 implementation_
->info
->singletons
.push_back(name
);
406 data_
->singletons
[name
].push_back(implementation_
);
409 rtl::OUString
Parser::getNameAttribute() {
410 rtl::OUString attrName
;
411 xmlreader::Span name
;
413 while (reader_
.nextAttribute(&nsId
, &name
)) {
414 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
415 && name
.equals(RTL_CONSTASCII_STRINGPARAM("name")))
417 if (!attrName
.isEmpty()) {
418 throw css::registry::InvalidRegistryException(
420 + ": element has multiple \"name\" attributes");
422 attrName
= reader_
.getAttributeValue(false).convertFromUtf8();
423 if (attrName
.isEmpty()) {
424 throw css::registry::InvalidRegistryException(
425 reader_
.getUrl() + ": element has empty \"name\" attribute");
428 throw css::registry::InvalidRegistryException(
429 reader_
.getUrl() + ": expected element attribute \"name\"");
432 if (attrName
.isEmpty()) {
433 throw css::registry::InvalidRegistryException(
434 reader_
.getUrl() + ": element is missing \"name\" attribute");
439 class ContentEnumeration
:
440 public cppu::WeakImplHelper1
< css::container::XEnumeration
>,
441 private boost::noncopyable
444 explicit ContentEnumeration(std::vector
< css::uno::Any
> const & factories
):
445 factories_(factories
), iterator_(factories_
.begin()) {}
448 virtual ~ContentEnumeration() {}
450 virtual sal_Bool SAL_CALL
hasMoreElements()
451 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
453 virtual css::uno::Any SAL_CALL
nextElement()
455 css::container::NoSuchElementException
,
456 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
459 std::vector
< css::uno::Any
> factories_
;
460 std::vector
< css::uno::Any
>::const_iterator iterator_
;
463 sal_Bool
ContentEnumeration::hasMoreElements()
464 throw (css::uno::RuntimeException
, std::exception
)
466 osl::MutexGuard
g(mutex_
);
467 return iterator_
!= factories_
.end();
470 css::uno::Any
ContentEnumeration::nextElement()
472 css::container::NoSuchElementException
,
473 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
)
475 osl::MutexGuard
g(mutex_
);
476 if (iterator_
== factories_
.end()) {
477 throw css::container::NoSuchElementException(
478 "Bootstrap service manager service enumerator has no more elements",
479 static_cast< cppu::OWeakObject
* >(this));
484 css::beans::Property
getDefaultContextProperty() {
485 return css::beans::Property(
486 "DefaultContext", -1,
487 cppu::UnoType
< css::uno::XComponentContext
>::get(),
488 css::beans::PropertyAttribute::READONLY
);
491 class SingletonFactory
:
492 public cppu::WeakImplHelper1
<css::lang::XSingleComponentFactory
>,
493 private boost::noncopyable
497 rtl::Reference
< cppuhelper::ServiceManager
> const & manager
,
499 cppuhelper::ServiceManager::Data::Implementation
> const &
501 manager_(manager
), implementation_(implementation
)
502 { assert(manager
.is()); assert(implementation
.get() != 0); }
505 virtual ~SingletonFactory() {}
507 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
508 createInstanceWithContext(
509 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
510 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
512 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
513 createInstanceWithArgumentsAndContext(
514 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
515 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
516 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
518 rtl::Reference
< cppuhelper::ServiceManager
> manager_
;
519 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
523 css::uno::Reference
< css::uno::XInterface
>
524 SingletonFactory::createInstanceWithContext(
525 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
526 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
528 manager_
->loadImplementation(Context
, implementation_
);
529 return implementation_
->createInstance(Context
, true);
532 css::uno::Reference
< css::uno::XInterface
>
533 SingletonFactory::createInstanceWithArgumentsAndContext(
534 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
535 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
536 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
538 manager_
->loadImplementation(Context
, implementation_
);
539 return implementation_
->createInstanceWithArguments(
540 Context
, true, Arguments
);
543 class ImplementationWrapper
:
544 public cppu::WeakImplHelper3
<
545 css::lang::XSingleComponentFactory
, css::lang::XSingleServiceFactory
,
546 css::lang::XServiceInfo
>,
547 private boost::noncopyable
550 ImplementationWrapper(
551 rtl::Reference
< cppuhelper::ServiceManager
> const & manager
,
553 cppuhelper::ServiceManager::Data::Implementation
> const &
555 manager_(manager
), implementation_(implementation
)
556 { assert(manager
.is()); assert(implementation
.get() != 0); }
559 virtual ~ImplementationWrapper() {}
561 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
562 createInstanceWithContext(
563 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
564 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
566 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
567 createInstanceWithArgumentsAndContext(
568 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
569 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
570 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
572 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
573 createInstance() throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
575 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
576 createInstanceWithArguments(
577 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
578 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
580 virtual rtl::OUString SAL_CALL
getImplementationName()
581 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
583 virtual sal_Bool SAL_CALL
supportsService(rtl::OUString
const & ServiceName
)
584 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
586 virtual css::uno::Sequence
< rtl::OUString
> SAL_CALL
587 getSupportedServiceNames() throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
589 rtl::Reference
< cppuhelper::ServiceManager
> manager_
;
590 boost::weak_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
594 css::uno::Reference
< css::uno::XInterface
>
595 ImplementationWrapper::createInstanceWithContext(
596 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
597 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
599 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
> impl
= implementation_
.lock();
601 manager_
->loadImplementation(Context
, impl
);
602 return impl
->createInstance(Context
, false);
605 css::uno::Reference
< css::uno::XInterface
>
606 ImplementationWrapper::createInstanceWithArgumentsAndContext(
607 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
608 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
609 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
611 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
> impl
= implementation_
.lock();
613 manager_
->loadImplementation(Context
, impl
);
614 return impl
->createInstanceWithArguments(
615 Context
, false, Arguments
);
618 css::uno::Reference
< css::uno::XInterface
>
619 ImplementationWrapper::createInstance()
620 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
622 return createInstanceWithContext(manager_
->getContext());
625 css::uno::Reference
< css::uno::XInterface
>
626 ImplementationWrapper::createInstanceWithArguments(
627 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
628 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
630 return createInstanceWithArgumentsAndContext(
631 Arguments
, manager_
->getContext());
634 rtl::OUString
ImplementationWrapper::getImplementationName()
635 throw (css::uno::RuntimeException
, std::exception
)
637 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
> impl
= implementation_
.lock();
639 return impl
->info
->name
;
642 sal_Bool
ImplementationWrapper::supportsService(rtl::OUString
const & ServiceName
)
643 throw (css::uno::RuntimeException
, std::exception
)
645 return cppu::supportsService(this, ServiceName
);
648 css::uno::Sequence
< rtl::OUString
>
649 ImplementationWrapper::getSupportedServiceNames()
650 throw (css::uno::RuntimeException
, std::exception
)
652 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
> impl
= implementation_
.lock();
654 if (impl
->info
->services
.size()
655 > static_cast< sal_uInt32
>(SAL_MAX_INT32
))
657 throw css::uno::RuntimeException(
658 ("Implementation " + impl
->info
->name
659 + " supports too many services"),
660 static_cast< cppu::OWeakObject
* >(this));
662 css::uno::Sequence
< rtl::OUString
> names(
663 static_cast< sal_Int32
>(impl
->info
->services
.size()));
665 for (std::vector
< rtl::OUString
>::const_iterator
j(
666 impl
->info
->services
.begin());
667 j
!= impl
->info
->services
.end(); ++j
)
676 css::uno::Reference
<css::uno::XInterface
>
677 cppuhelper::ServiceManager::Data::Implementation::createInstance(
678 css::uno::Reference
<css::uno::XComponentContext
> const & context
,
679 bool singletonRequest
)
681 css::uno::Reference
<css::uno::XInterface
> inst
;
682 if (constructor
!= 0) {
684 (*constructor
)(context
.get(), css::uno::Sequence
<css::uno::Any
>()),
686 } else if (factory1
.is()) {
687 inst
= factory1
->createInstanceWithContext(context
);
689 assert(factory2
.is());
690 inst
= factory2
->createInstance();
692 updateDisposeSingleton(singletonRequest
, inst
);
696 css::uno::Reference
<css::uno::XInterface
>
697 cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
698 css::uno::Reference
<css::uno::XComponentContext
> const & context
,
699 bool singletonRequest
, css::uno::Sequence
<css::uno::Any
> const & arguments
)
701 css::uno::Reference
<css::uno::XInterface
> inst
;
702 if (constructor
!= 0) {
703 inst
.set((*constructor
)(context
.get(), arguments
), SAL_NO_ACQUIRE
);
704 //HACK: The constructor will either observe arguments and return inst
705 // that does not implement XInitialization (or null), or ignore
706 // arguments and return inst that implements XInitialization; this
707 // should be removed again once XInitialization-based implementations
709 css::uno::Reference
<css::lang::XInitialization
> init(
710 inst
, css::uno::UNO_QUERY
);
712 init
->initialize(arguments
);
714 } else if (factory1
.is()) {
715 inst
= factory1
->createInstanceWithArgumentsAndContext(
718 assert(factory2
.is());
719 inst
= factory2
->createInstanceWithArguments(arguments
);
721 updateDisposeSingleton(singletonRequest
, inst
);
725 void cppuhelper::ServiceManager::Data::Implementation::updateDisposeSingleton(
726 bool singletonRequest
,
727 css::uno::Reference
<css::uno::XInterface
> const & instance
)
729 // This is an optimization, to only call dispose once (from the component
730 // context) on a singleton that is obtained both via the component context
731 // and via the service manager; however, there is a harmless race here that
732 // may cause two calls to dispose nevertheless (also, this calls dispose on
733 // at most one of the instances obtained via the service manager, in case
734 // the implementation hands out different instances):
735 if (singletonRequest
) {
736 osl::MutexGuard
g(mutex
);
737 disposeSingleton
.clear();
739 } else if (!info
->singletons
.empty()) {
740 css::uno::Reference
<css::lang::XComponent
> comp(
741 instance
, css::uno::UNO_QUERY
);
743 osl::MutexGuard
g(mutex
);
745 disposeSingleton
= comp
;
751 void cppuhelper::ServiceManager::addSingletonContextEntries(
752 std::vector
< cppu::ContextEntry_Init
> * entries
)
754 assert(entries
!= 0);
755 for (Data::ImplementationMap::const_iterator
i(data_
.singletons
.begin());
756 i
!= data_
.singletons
.end(); ++i
)
758 assert(!i
->second
.empty());
759 assert(i
->second
[0].get() != 0);
761 i
->second
.size() > 1, "cppuhelper",
762 "Arbitrarily chosing " << i
->second
[0]->info
->name
763 << " among multiple implementations for " << i
->first
);
765 cppu::ContextEntry_Init(
766 "/singletons/" + i
->first
,
768 css::uno::Reference
<css::lang::XSingleComponentFactory
> >(
769 new SingletonFactory(this, i
->second
[0])),
774 void cppuhelper::ServiceManager::loadImplementation(
775 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
776 boost::shared_ptr
< Data::Implementation
> & implementation
)
778 assert(implementation
.get() != 0);
780 osl::MutexGuard
g(rBHelper
.rMutex
);
781 if (implementation
->status
== Data::Implementation::STATUS_LOADED
) {
787 uri
= cppu::bootstrap_expandUri(implementation
->info
->uri
);
788 } catch (css::lang::IllegalArgumentException
& e
) {
789 throw css::uno::DeploymentException(
790 "Cannot expand URI" + implementation
->info
->uri
+ ": " + e
.Message
,
791 static_cast< cppu::OWeakObject
* >(this));
793 cppuhelper::ImplementationConstructorFn
* ctor
= 0;
794 css::uno::Reference
< css::uno::XInterface
> f0
;
795 // Special handling of SharedLibrary loader, with support for environment,
796 // constructor, and prefix arguments:
797 if (!implementation
->info
->alienContext
.is()
798 && implementation
->info
->loader
== "com.sun.star.loader.SharedLibrary")
800 cppuhelper::detail::loadSharedLibComponentFactory(
801 uri
, implementation
->info
->environment
,
802 implementation
->info
->prefix
, implementation
->info
->name
,
803 implementation
->info
->constructor
, this, &ctor
, &f0
);
805 assert(!implementation
->info
->environment
.isEmpty());
806 css::uno::Environment
curEnv(css::uno::Environment::getCurrent());
807 css::uno::Environment
env(
808 cppuhelper::detail::getEnvironment(
809 implementation
->info
->environment
,
810 implementation
->info
->name
));
811 if (!(curEnv
.is() && env
.is())) {
812 throw css::uno::DeploymentException(
813 "cannot get environments",
814 css::uno::Reference
<css::uno::XInterface
>());
816 if (curEnv
.get() != env
.get()) {
822 !implementation
->info
->environment
.isEmpty(), "cppuhelper",
823 "Loader " << implementation
->info
->loader
824 << " and non-empty environment "
825 << implementation
->info
->environment
);
827 !implementation
->info
->prefix
.isEmpty(), "cppuhelper",
828 "Loader " << implementation
->info
->loader
829 << " and non-empty constructor "
830 << implementation
->info
->constructor
);
832 !implementation
->info
->prefix
.isEmpty(), "cppuhelper",
833 "Loader " << implementation
->info
->loader
834 << " and non-empty prefix " << implementation
->info
->prefix
);
835 css::uno::Reference
< css::uno::XComponentContext
> ctxt
;
836 css::uno::Reference
< css::lang::XMultiComponentFactory
> smgr
;
837 if (implementation
->info
->alienContext
.is()) {
838 ctxt
= implementation
->info
->alienContext
;
839 smgr
= css::uno::Reference
< css::lang::XMultiComponentFactory
>(
840 ctxt
->getServiceManager(), css::uno::UNO_SET_THROW
);
842 assert(context
.is());
846 css::uno::Reference
< css::loader::XImplementationLoader
> loader(
847 smgr
->createInstanceWithContext(implementation
->info
->loader
, ctxt
),
848 css::uno::UNO_QUERY_THROW
);
849 f0
= loader
->activate(
850 implementation
->info
->name
, rtl::OUString(), uri
,
851 css::uno::Reference
< css::registry::XRegistryKey
>());
853 css::uno::Reference
<css::lang::XSingleComponentFactory
> f1
;
854 css::uno::Reference
<css::lang::XSingleServiceFactory
> f2
;
856 f1
.set(f0
, css::uno::UNO_QUERY
);
858 f2
.set(f0
, css::uno::UNO_QUERY
);
860 throw css::uno::DeploymentException(
861 ("Implementation " + implementation
->info
->name
862 + " does not provide a constructor or factory"),
863 static_cast< cppu::OWeakObject
* >(this));
867 //TODO: There is a race here, as the relevant service factory can be removed
868 // while the mutex is unlocked and loading can thus fail, as the entity from
869 // which to load can disappear once the service factory is removed.
870 osl::MutexGuard
g(rBHelper
.rMutex
);
872 || implementation
->status
== Data::Implementation::STATUS_LOADED
))
874 implementation
->status
= Data::Implementation::STATUS_LOADED
;
875 implementation
->constructor
= ctor
;
876 implementation
->factory1
= f1
;
877 implementation
->factory2
= f2
;
881 void cppuhelper::ServiceManager::disposing() {
882 std::vector
< css::uno::Reference
<css::lang::XComponent
> > sngls
;
883 std::vector
< css::uno::Reference
< css::lang::XComponent
> > comps
;
886 osl::MutexGuard
g(rBHelper
.rMutex
);
887 for (Data::NamedImplementations::const_iterator
i(
888 data_
.namedImplementations
.begin());
889 i
!= data_
.namedImplementations
.end(); ++i
)
891 assert(i
->second
.get() != 0);
892 if (!i
->second
->info
->singletons
.empty()) {
893 osl::MutexGuard
g2(i
->second
->mutex
);
894 if (i
->second
->disposeSingleton
.is()) {
895 sngls
.push_back(i
->second
->disposeSingleton
);
899 for (Data::DynamicImplementations::const_iterator
i(
900 data_
.dynamicImplementations
.begin());
901 i
!= data_
.dynamicImplementations
.end(); ++i
)
903 assert(i
->second
.get() != 0);
904 if (!i
->second
->info
->singletons
.empty()) {
905 osl::MutexGuard
g2(i
->second
->mutex
);
906 if (i
->second
->disposeSingleton
.is()) {
907 sngls
.push_back(i
->second
->disposeSingleton
);
910 if (i
->second
->component
.is()) {
911 comps
.push_back(i
->second
->component
);
914 data_
.namedImplementations
.swap(clear
.namedImplementations
);
915 data_
.dynamicImplementations
.swap(clear
.dynamicImplementations
);
916 data_
.services
.swap(clear
.services
);
917 data_
.singletons
.swap(clear
.singletons
);
920 css::uno::Reference
<css::lang::XComponent
> >::const_iterator
i(
922 i
!= sngls
.end(); ++i
)
926 } catch (css::uno::RuntimeException
& e
) {
929 "Ignoring RuntimeException \"" << e
.Message
930 << "\" while disposing singleton");
934 css::uno::Reference
< css::lang::XComponent
> >::const_iterator
i(
936 i
!= comps
.end(); ++i
)
938 removeEventListenerFromComponent(*i
);
942 rtl::OUString
cppuhelper::ServiceManager::getImplementationName()
943 throw (css::uno::RuntimeException
, std::exception
)
945 return rtl::OUString(
946 "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager");
949 sal_Bool
cppuhelper::ServiceManager::supportsService(
950 rtl::OUString
const & ServiceName
)
951 throw (css::uno::RuntimeException
, std::exception
)
953 return cppu::supportsService(this, ServiceName
);
956 css::uno::Sequence
< rtl::OUString
>
957 cppuhelper::ServiceManager::getSupportedServiceNames()
958 throw (css::uno::RuntimeException
, std::exception
)
960 css::uno::Sequence
< rtl::OUString
> names(2);
961 names
[0] = "com.sun.star.lang.MultiServiceFactory";
962 names
[1] = "com.sun.star.lang.ServiceManager";
966 css::uno::Reference
< css::uno::XInterface
>
967 cppuhelper::ServiceManager::createInstance(
968 rtl::OUString
const & aServiceSpecifier
)
969 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
971 assert(context_
.is());
972 return createInstanceWithContext(aServiceSpecifier
, context_
);
975 css::uno::Reference
< css::uno::XInterface
>
976 cppuhelper::ServiceManager::createInstanceWithArguments(
977 rtl::OUString
const & ServiceSpecifier
,
978 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
979 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
981 assert(context_
.is());
982 return createInstanceWithArgumentsAndContext(
983 ServiceSpecifier
, Arguments
, context_
);
986 css::uno::Sequence
< rtl::OUString
>
987 cppuhelper::ServiceManager::getAvailableServiceNames()
988 throw (css::uno::RuntimeException
, std::exception
)
990 osl::MutexGuard
g(rBHelper
.rMutex
);
992 return css::uno::Sequence
< rtl::OUString
>();
994 Data::ImplementationMap::size_type n
= data_
.services
.size();
995 if (n
> static_cast< sal_uInt32
>(SAL_MAX_INT32
)) {
996 throw css::uno::RuntimeException(
997 "getAvailableServiceNames: too many services",
998 static_cast< cppu::OWeakObject
* >(this));
1000 css::uno::Sequence
< rtl::OUString
> names(static_cast< sal_Int32
>(n
));
1002 for (Data::ImplementationMap::const_iterator
j(data_
.services
.begin());
1003 j
!= data_
.services
.end(); ++j
)
1005 names
[i
++] = j
->first
;
1007 assert(i
== names
.getLength());
1011 css::uno::Reference
< css::uno::XInterface
>
1012 cppuhelper::ServiceManager::createInstanceWithContext(
1013 rtl::OUString
const & aServiceSpecifier
,
1014 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
1015 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
1017 boost::shared_ptr
< Data::Implementation
> impl(
1018 findServiceImplementation(Context
, aServiceSpecifier
));
1019 return impl
.get() == 0
1020 ? css::uno::Reference
< css::uno::XInterface
>()
1021 : impl
->createInstance(Context
, false);
1024 css::uno::Reference
< css::uno::XInterface
>
1025 cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
1026 rtl::OUString
const & ServiceSpecifier
,
1027 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
1028 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
1029 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
1031 boost::shared_ptr
< Data::Implementation
> impl(
1032 findServiceImplementation(Context
, ServiceSpecifier
));
1033 return impl
.get() == 0
1034 ? css::uno::Reference
< css::uno::XInterface
>()
1035 : impl
->createInstanceWithArguments(Context
, false, Arguments
);
1038 css::uno::Type
cppuhelper::ServiceManager::getElementType()
1039 throw (css::uno::RuntimeException
, std::exception
)
1041 return css::uno::Type();
1044 sal_Bool
cppuhelper::ServiceManager::hasElements()
1045 throw (css::uno::RuntimeException
, std::exception
)
1047 osl::MutexGuard
g(rBHelper
.rMutex
);
1049 !(data_
.namedImplementations
.empty()
1050 && data_
.dynamicImplementations
.empty());
1053 css::uno::Reference
< css::container::XEnumeration
>
1054 cppuhelper::ServiceManager::createEnumeration()
1055 throw (css::uno::RuntimeException
, std::exception
)
1057 throw css::uno::RuntimeException(
1058 "ServiceManager createEnumeration: method not supported",
1059 static_cast< cppu::OWeakObject
* >(this));
1062 sal_Bool
cppuhelper::ServiceManager::has(css::uno::Any
const &)
1063 throw (css::uno::RuntimeException
, std::exception
)
1065 throw css::uno::RuntimeException(
1066 "ServiceManager has: method not supported",
1067 static_cast< cppu::OWeakObject
* >(this));
1070 void cppuhelper::ServiceManager::insert(css::uno::Any
const & aElement
)
1072 css::lang::IllegalArgumentException
,
1073 css::container::ElementExistException
, css::uno::RuntimeException
, std::exception
)
1075 css::uno::Sequence
< css::beans::NamedValue
> args
;
1076 if (aElement
>>= args
) {
1077 std::vector
< rtl::OUString
> uris
;
1078 css::uno::Reference
< css::uno::XComponentContext
> alienContext
;
1079 for (sal_Int32 i
= 0; i
< args
.getLength(); ++i
) {
1080 if (args
[i
].Name
== "uri") {
1082 if (!(args
[i
].Value
>>= uri
)) {
1083 throw css::lang::IllegalArgumentException(
1085 static_cast< cppu::OWeakObject
* >(this), 0);
1087 uris
.push_back(uri
);
1088 } else if (args
[i
].Name
== "component-context") {
1089 if (alienContext
.is()) {
1090 throw css::lang::IllegalArgumentException(
1091 "Multiple component-context arguments",
1092 static_cast< cppu::OWeakObject
* >(this), 0);
1094 if (!(args
[i
].Value
>>= alienContext
) || !alienContext
.is()) {
1095 throw css::lang::IllegalArgumentException(
1096 "Bad component-context argument",
1097 static_cast< cppu::OWeakObject
* >(this), 0);
1100 throw css::lang::IllegalArgumentException(
1101 "Bad argument " + args
[i
].Name
,
1102 static_cast< cppu::OWeakObject
* >(this), 0);
1105 insertRdbFiles(uris
, alienContext
);
1108 css::uno::Reference
< css::lang::XServiceInfo
> info
;
1109 if ((aElement
>>= info
) && info
.is()) {
1110 insertLegacyFactory(info
);
1113 // At least revisions up to 1.7 of LanguageTool.oxt (incl. the bundled 1.4.0 in
1114 // module languagetool) contain an (actively registered) factory that does not
1115 // implement XServiceInfo (see <http://sourceforge.net/tracker/?
1116 // func=detail&aid=3526635&group_id=110216&atid=655717> "SingletonFactory should
1117 // implement XServiceInfo"); the old OServiceManager::insert
1118 // (stoc/source/servicemanager/servicemanager.cxx) silently did not add such
1119 // broken factories to its m_ImplementationNameMap, so ignore them here for
1120 // backwards compatibility of live-insertion of extensions, too.
1122 // (The plan was that this warning would go away (and we would do the
1123 // throw instead) for the incompatible LO 4, but we changed our mind):
1124 css::uno::Reference
< css::lang::XSingleComponentFactory
> legacy
;
1125 if ((aElement
>>= legacy
) && legacy
.is()) {
1128 "Ignored XSingleComponentFactory not implementing XServiceInfo");
1132 throw css::lang::IllegalArgumentException(
1133 "Bad insert element", static_cast< cppu::OWeakObject
* >(this), 0);
1136 void cppuhelper::ServiceManager::remove(css::uno::Any
const & aElement
)
1138 css::lang::IllegalArgumentException
,
1139 css::container::NoSuchElementException
, css::uno::RuntimeException
, std::exception
)
1141 css::uno::Sequence
< css::beans::NamedValue
> args
;
1142 if (aElement
>>= args
) {
1143 std::vector
< rtl::OUString
> uris
;
1144 for (sal_Int32 i
= 0; i
< args
.getLength(); ++i
) {
1145 if (args
[i
].Name
== "uri") {
1147 if (!(args
[i
].Value
>>= uri
)) {
1148 throw css::lang::IllegalArgumentException(
1150 static_cast< cppu::OWeakObject
* >(this), 0);
1152 uris
.push_back(uri
);
1154 throw css::lang::IllegalArgumentException(
1155 "Bad argument " + args
[i
].Name
,
1156 static_cast< cppu::OWeakObject
* >(this), 0);
1159 removeRdbFiles(uris
);
1162 css::uno::Reference
< css::lang::XServiceInfo
> info
;
1163 if ((aElement
>>= info
) && info
.is()) {
1164 if (!removeLegacyFactory(info
, true)) {
1165 throw css::container::NoSuchElementException(
1166 "Remove non-inserted factory object",
1167 static_cast< cppu::OWeakObject
* >(this));
1172 if (aElement
>>= impl
) {
1173 // For live-removal of extensions:
1174 removeImplementation(impl
);
1177 throw css::lang::IllegalArgumentException(
1178 "Bad remove element", static_cast< cppu::OWeakObject
* >(this), 0);
1181 css::uno::Reference
< css::container::XEnumeration
>
1182 cppuhelper::ServiceManager::createContentEnumeration(
1183 rtl::OUString
const & aServiceName
)
1184 throw (css::uno::RuntimeException
, std::exception
)
1186 std::vector
< boost::shared_ptr
< Data::Implementation
> > impls
;
1188 osl::MutexGuard
g(rBHelper
.rMutex
);
1189 Data::ImplementationMap::const_iterator
i(
1190 data_
.services
.find(aServiceName
));
1191 if (i
!= data_
.services
.end()) {
1195 std::vector
< css::uno::Any
> factories
;
1197 boost::shared_ptr
< Data::Implementation
> >::const_iterator
i(
1199 i
!= impls
.end(); ++i
)
1201 Data::Implementation
* impl
= i
->get();
1204 osl::MutexGuard
g(rBHelper
.rMutex
);
1209 if (impl
->status
== Data::Implementation::STATUS_NEW
) {
1210 // Postpone actual implementation instantiation as long as
1211 // possible (so that e.g. opening LO's "Tools - Macros" menu
1212 // does not try to instantiate a JVM, which can lead to a
1213 // synchronous error dialog when no JVM is specified, and
1214 // showing the dialog while hovering over a menu can cause
1216 impl
->factory1
= new ImplementationWrapper(this, *i
);
1217 impl
->status
= Data::Implementation::STATUS_WRAPPER
;
1220 if (impl
->factory1
.is()) {
1221 factories
.push_back(css::uno::makeAny(impl
->factory1
));
1222 } else if (impl
->factory2
.is()) {
1223 factories
.push_back(css::uno::makeAny(impl
->factory2
));
1225 css::uno::Reference
< css::lang::XSingleComponentFactory
> factory(
1226 new ImplementationWrapper(this, *i
));
1227 factories
.push_back(css::uno::makeAny(factory
));
1230 return new ContentEnumeration(factories
);
1233 css::uno::Reference
< css::beans::XPropertySetInfo
>
1234 cppuhelper::ServiceManager::getPropertySetInfo()
1235 throw (css::uno::RuntimeException
, std::exception
)
1240 void cppuhelper::ServiceManager::setPropertyValue(
1241 rtl::OUString
const & aPropertyName
, css::uno::Any
const &)
1243 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1244 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1245 css::uno::RuntimeException
, std::exception
)
1247 if (aPropertyName
== "DefaultContext") {
1248 throw css::beans::PropertyVetoException(
1249 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1251 throw css::beans::UnknownPropertyException(
1252 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1256 css::uno::Any
cppuhelper::ServiceManager::getPropertyValue(
1257 rtl::OUString
const & PropertyName
)
1259 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1260 css::uno::RuntimeException
, std::exception
)
1262 if (PropertyName
!= "DefaultContext") {
1263 throw css::beans::UnknownPropertyException(
1264 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1266 assert(context_
.is());
1267 return css::uno::makeAny(context_
);
1270 void cppuhelper::ServiceManager::addPropertyChangeListener(
1271 rtl::OUString
const & aPropertyName
,
1272 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
1275 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1276 css::uno::RuntimeException
, std::exception
)
1278 if (!aPropertyName
.isEmpty() && aPropertyName
!= "DefaultContext") {
1279 throw css::beans::UnknownPropertyException(
1280 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1282 // DefaultContext does not change, so just treat it as an event listener:
1283 return addEventListener(xListener
);
1286 void cppuhelper::ServiceManager::removePropertyChangeListener(
1287 rtl::OUString
const & aPropertyName
,
1288 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
1291 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1292 css::uno::RuntimeException
, std::exception
)
1294 if (!aPropertyName
.isEmpty() && aPropertyName
!= "DefaultContext") {
1295 throw css::beans::UnknownPropertyException(
1296 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1298 // DefaultContext does not change, so just treat it as an event listener:
1299 return removeEventListener(aListener
);
1302 void cppuhelper::ServiceManager::addVetoableChangeListener(
1303 rtl::OUString
const & PropertyName
,
1304 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
1307 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1308 css::uno::RuntimeException
, std::exception
)
1310 if (!PropertyName
.isEmpty() && PropertyName
!= "DefaultContext") {
1311 throw css::beans::UnknownPropertyException(
1312 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1314 // DefaultContext does not change, so just treat it as an event listener:
1315 return addEventListener(aListener
);
1318 void cppuhelper::ServiceManager::removeVetoableChangeListener(
1319 rtl::OUString
const & PropertyName
,
1320 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
1323 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1324 css::uno::RuntimeException
, std::exception
)
1326 if (!PropertyName
.isEmpty() && PropertyName
!= "DefaultContext") {
1327 throw css::beans::UnknownPropertyException(
1328 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1330 // DefaultContext does not change, so just treat it as an event listener:
1331 return removeEventListener(aListener
);
1334 css::uno::Sequence
< css::beans::Property
>
1335 cppuhelper::ServiceManager::getProperties() throw (css::uno::RuntimeException
, std::exception
) {
1336 css::uno::Sequence
< css::beans::Property
> props(1);
1337 props
[0] = getDefaultContextProperty();
1341 css::beans::Property
cppuhelper::ServiceManager::getPropertyByName(
1342 rtl::OUString
const & aName
)
1343 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
, std::exception
)
1345 if (aName
!= "DefaultContext") {
1346 throw css::beans::UnknownPropertyException(
1347 aName
, static_cast< cppu::OWeakObject
* >(this));
1349 return getDefaultContextProperty();
1352 sal_Bool
cppuhelper::ServiceManager::hasPropertyByName(
1353 rtl::OUString
const & Name
)
1354 throw (css::uno::RuntimeException
, std::exception
)
1356 return Name
== "DefaultContext";
1359 void cppuhelper::ServiceManager::disposing(
1360 css::lang::EventObject
const & Source
)
1361 throw (css::uno::RuntimeException
, std::exception
)
1363 removeLegacyFactory(
1364 css::uno::Reference
< css::lang::XServiceInfo
>(
1365 Source
.Source
, css::uno::UNO_QUERY_THROW
),
1369 void cppuhelper::ServiceManager::removeEventListenerFromComponent(
1370 css::uno::Reference
< css::lang::XComponent
> const & component
)
1372 assert(component
.is());
1374 component
->removeEventListener(this);
1375 } catch (css::uno::RuntimeException
& e
) {
1378 "Ignored removeEventListener RuntimeException " + e
.Message
);
1382 void cppuhelper::ServiceManager::readRdbs(rtl::OUString
const & uris
) {
1383 for (sal_Int32 i
= 0; i
!= -1;) {
1384 rtl::OUString
uri(uris
.getToken(0, ' ', i
));
1385 if (uri
.isEmpty()) {
1390 cppu::decodeRdbUri(&uri
, &optional
, &directory
);
1392 readRdbDirectory(uri
, optional
);
1394 readRdbFile(uri
, optional
);
1399 void cppuhelper::ServiceManager::readRdbDirectory(
1400 rtl::OUString
const & uri
, bool optional
)
1402 osl::Directory
dir(uri
);
1403 switch (dir
.open()) {
1404 case osl::FileBase::E_None
:
1406 case osl::FileBase::E_NOENT
:
1408 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
1413 throw css::uno::DeploymentException(
1414 "Cannot open directory " + uri
,
1415 static_cast< cppu::OWeakObject
* >(this));
1419 if (!cppu::nextDirectoryItem(dir
, &url
)) {
1422 readRdbFile(url
, false);
1426 void cppuhelper::ServiceManager::readRdbFile(
1427 rtl::OUString
const & uri
, bool optional
)
1431 uri
, css::uno::Reference
< css::uno::XComponentContext
>(), &data_
);
1432 } catch (css::container::NoSuchElementException
&) {
1434 throw css::uno::DeploymentException(
1435 uri
+ ": no such file",
1436 static_cast< cppu::OWeakObject
* >(this));
1438 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
1439 } catch (css::registry::InvalidRegistryException
& e
) {
1440 if (!readLegacyRdbFile(uri
)) {
1441 throw css::uno::DeploymentException(
1442 "InvalidRegistryException: " + e
.Message
,
1443 static_cast< cppu::OWeakObject
* >(this));
1445 } catch (css::uno::RuntimeException
&) {
1446 if (!readLegacyRdbFile(uri
)) {
1452 bool cppuhelper::ServiceManager::readLegacyRdbFile(rtl::OUString
const & uri
) {
1454 switch (reg
.open(uri
, RegAccessMode::READONLY
)) {
1455 case RegError::NO_ERROR
:
1457 case RegError::REGISTRY_NOT_EXISTS
:
1458 case RegError::INVALID_REGISTRY
:
1460 // Ignore empty rdb files (which are at least seen by subordinate
1461 // uno processes during extension registration; Registry::open can
1462 // fail on them if mmap(2) returns EINVAL for a zero length):
1463 osl::DirectoryItem item
;
1464 if (osl::DirectoryItem::get(uri
, item
) == osl::FileBase::E_None
) {
1465 osl::FileStatus
status(osl_FileStatus_Mask_FileSize
);
1466 if (item
.getFileStatus(status
) == osl::FileBase::E_None
1467 && status
.getFileSize() == 0)
1477 RegistryKey rootKey
;
1478 if (reg
.openRootKey(rootKey
) != RegError::NO_ERROR
) {
1479 throw css::uno::DeploymentException(
1480 "Failure reading legacy rdb file " + uri
,
1481 static_cast< cppu::OWeakObject
* >(this));
1483 RegistryKeyArray impls
;
1484 switch (rootKey
.openSubKeys("IMPLEMENTATIONS", impls
)) {
1485 case RegError::NO_ERROR
:
1487 case RegError::KEY_NOT_EXISTS
:
1490 throw css::uno::DeploymentException(
1491 "Failure reading legacy rdb file " + uri
,
1492 static_cast< cppu::OWeakObject
* >(this));
1494 for (sal_uInt32 i
= 0; i
!= impls
.getLength(); ++i
) {
1495 RegistryKey
implKey(impls
.getElement(i
));
1496 assert(implKey
.getName().match("/IMPLEMENTATIONS/"));
1498 implKey
.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1499 boost::shared_ptr
< Data::Implementation
> impl(
1500 new Data::Implementation(
1501 name
, readLegacyRdbString(uri
, implKey
, "UNO/ACTIVATOR"),
1502 readLegacyRdbString(uri
, implKey
, "UNO/LOCATION"), "", "", "",
1503 css::uno::Reference
< css::uno::XComponentContext
>(), uri
));
1504 if (!data_
.namedImplementations
.insert(
1505 Data::NamedImplementations::value_type(name
, impl
)).
1508 throw css::registry::InvalidRegistryException(
1509 uri
+ ": duplicate <implementation name=\"" + name
+ "\">");
1511 readLegacyRdbStrings(
1512 uri
, implKey
, "UNO/SERVICES", &impl
->info
->services
);
1513 for (std::vector
< rtl::OUString
>::const_iterator
j(
1514 impl
->info
->services
.begin());
1515 j
!= impl
->info
->services
.end(); ++j
)
1517 data_
.services
[*j
].push_back(impl
);
1519 readLegacyRdbStrings(
1520 uri
, implKey
, "UNO/SINGLETONS", &impl
->info
->singletons
);
1521 for (std::vector
< rtl::OUString
>::const_iterator
j(
1522 impl
->info
->singletons
.begin());
1523 j
!= impl
->info
->singletons
.end(); ++j
)
1525 data_
.singletons
[*j
].push_back(impl
);
1531 rtl::OUString
cppuhelper::ServiceManager::readLegacyRdbString(
1532 rtl::OUString
const & uri
, RegistryKey
& key
, rtl::OUString
const & path
)
1537 if (key
.openKey(path
, subkey
) != RegError::NO_ERROR
1538 || subkey
.getValueInfo(rtl::OUString(), &t
, &s
) != RegError::NO_ERROR
1539 || t
!= RegValueType::STRING
1540 || s
== 0 || s
> static_cast< sal_uInt32
>(SAL_MAX_INT32
))
1542 throw css::uno::DeploymentException(
1543 "Failure reading legacy rdb file " + uri
,
1544 static_cast< cppu::OWeakObject
* >(this));
1547 std::vector
< char > v(s
); // assuming sal_uInt32 fits into vector::size_type
1548 if (subkey
.getValue(rtl::OUString(), &v
[0]) != RegError::NO_ERROR
1550 || !rtl_convertStringToUString(
1551 &val
.pData
, &v
[0], static_cast< sal_Int32
>(s
- 1),
1552 RTL_TEXTENCODING_UTF8
,
1553 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1554 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1555 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
)))
1557 throw css::uno::DeploymentException(
1558 "Failure reading legacy rdb file " + uri
,
1559 static_cast< cppu::OWeakObject
* >(this));
1564 void cppuhelper::ServiceManager::readLegacyRdbStrings(
1565 rtl::OUString
const & uri
, RegistryKey
& key
, rtl::OUString
const & path
,
1566 std::vector
< rtl::OUString
> * strings
)
1568 assert(strings
!= 0);
1570 switch (key
.openKey(path
, subkey
)) {
1571 case RegError::NO_ERROR
:
1573 case RegError::KEY_NOT_EXISTS
:
1576 throw css::uno::DeploymentException(
1577 "Failure reading legacy rdb file " + uri
,
1578 static_cast< cppu::OWeakObject
* >(this));
1580 rtl::OUString
prefix(subkey
.getName() + "/");
1581 RegistryKeyNames names
;
1582 if (subkey
.getKeyNames(rtl::OUString(), names
) != RegError::NO_ERROR
) {
1583 throw css::uno::DeploymentException(
1584 "Failure reading legacy rdb file " + uri
,
1585 static_cast< cppu::OWeakObject
* >(this));
1587 for (sal_uInt32 i
= 0; i
!= names
.getLength(); ++i
) {
1588 assert(names
.getElement(i
).match(prefix
));
1589 strings
->push_back(names
.getElement(i
).copy(prefix
.getLength()));
1593 void cppuhelper::ServiceManager::insertRdbFiles(
1594 std::vector
< rtl::OUString
> const & uris
,
1595 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
)
1598 for (std::vector
< rtl::OUString
>::const_iterator
i(uris
.begin());
1599 i
!= uris
.end(); ++i
)
1602 Parser(*i
, alienContext
, &extra
);
1603 } catch (css::container::NoSuchElementException
&) {
1604 throw css::lang::IllegalArgumentException(
1605 *i
+ ": no such file", static_cast< cppu::OWeakObject
* >(this),
1607 } catch (css::registry::InvalidRegistryException
& e
) {
1608 throw css::lang::IllegalArgumentException(
1609 "InvalidRegistryException: " + e
.Message
,
1610 static_cast< cppu::OWeakObject
* >(this), 0);
1613 insertExtraData(extra
);
1616 void cppuhelper::ServiceManager::insertLegacyFactory(
1617 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
)
1619 assert(factoryInfo
.is());
1620 rtl::OUString
name(factoryInfo
->getImplementationName());
1621 css::uno::Reference
< css::lang::XSingleComponentFactory
> f1(
1622 factoryInfo
, css::uno::UNO_QUERY
);
1623 css::uno::Reference
< css::lang::XSingleServiceFactory
> f2
;
1625 f2
= css::uno::Reference
< css::lang::XSingleServiceFactory
>(
1626 factoryInfo
, css::uno::UNO_QUERY
);
1628 throw css::lang::IllegalArgumentException(
1629 ("Bad XServiceInfo argument implements neither"
1630 " XSingleComponentFactory nor XSingleServiceFactory"),
1631 static_cast< cppu::OWeakObject
* >(this), 0);
1634 css::uno::Reference
< css::lang::XComponent
> comp(
1635 factoryInfo
, css::uno::UNO_QUERY
);
1636 boost::shared_ptr
< Data::Implementation
> impl(
1637 new Data::Implementation(name
, f1
, f2
, comp
));
1639 if (!name
.isEmpty()) {
1640 extra
.namedImplementations
.insert(
1641 Data::NamedImplementations::value_type(name
, impl
));
1643 extra
.dynamicImplementations
.insert(
1644 Data::DynamicImplementations::value_type(factoryInfo
, impl
));
1645 css::uno::Sequence
< rtl::OUString
> services(
1646 factoryInfo
->getSupportedServiceNames());
1647 for (sal_Int32 i
= 0; i
!= services
.getLength(); ++i
) {
1648 impl
->info
->services
.push_back(services
[i
]);
1649 extra
.services
[services
[i
]].push_back(impl
);
1651 if (insertExtraData(extra
) && comp
.is()) {
1652 comp
->addEventListener(this);
1656 bool cppuhelper::ServiceManager::insertExtraData(Data
const & extra
) {
1658 osl::MutexGuard
g(rBHelper
.rMutex
);
1662 for (Data::NamedImplementations::const_iterator
i(
1663 extra
.namedImplementations
.begin());
1664 i
!= extra
.namedImplementations
.end(); ++i
)
1666 if (data_
.namedImplementations
.find(i
->first
)
1667 != data_
.namedImplementations
.end())
1669 throw css::lang::IllegalArgumentException(
1670 "Insert duplicate implementation name " + i
->first
,
1671 static_cast< cppu::OWeakObject
* >(this), 0);
1674 for (Data::DynamicImplementations::const_iterator
i(
1675 extra
.dynamicImplementations
.begin());
1676 i
!= extra
.dynamicImplementations
.end(); ++i
)
1678 if (data_
.dynamicImplementations
.find(i
->first
)
1679 != data_
.dynamicImplementations
.end())
1681 throw css::lang::IllegalArgumentException(
1682 "Insert duplicate factory object",
1683 static_cast< cppu::OWeakObject
* >(this), 0);
1686 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1687 data_
.namedImplementations
.insert(
1688 extra
.namedImplementations
.begin(),
1689 extra
.namedImplementations
.end());
1690 data_
.dynamicImplementations
.insert(
1691 extra
.dynamicImplementations
.begin(),
1692 extra
.dynamicImplementations
.end());
1693 insertImplementationMap(&data_
.services
, extra
.services
);
1694 insertImplementationMap(&data_
.singletons
, extra
.singletons
);
1696 //TODO: Updating the component context singleton data should be part of the
1697 // atomic service manager update:
1698 if (!extra
.singletons
.empty()) {
1699 assert(context_
.is());
1700 css::uno::Reference
< css::container::XNameContainer
> cont(
1701 context_
, css::uno::UNO_QUERY_THROW
);
1702 for (Data::ImplementationMap::const_iterator
i(
1703 extra
.singletons
.begin());
1704 i
!= extra
.singletons
.end(); ++i
)
1706 rtl::OUString
name("/singletons/" + i
->first
);
1707 //TODO: Update should be atomic:
1709 cont
->removeByName(name
+ "/arguments");
1710 } catch (const css::container::NoSuchElementException
&) {}
1711 assert(!i
->second
.empty());
1712 assert(i
->second
[0].get() != 0);
1714 i
->second
.size() > 1, "cppuhelper",
1715 "Arbitrarily chosing " << i
->second
[0]->info
->name
1716 << " among multiple implementations for singleton "
1720 name
+ "/service", css::uno::Any(i
->second
[0]->info
->name
));
1721 } catch (css::container::ElementExistException
&) {
1722 cont
->replaceByName(
1723 name
+ "/service", css::uno::Any(i
->second
[0]->info
->name
));
1726 cont
->insertByName(name
, css::uno::Any());
1727 } catch (css::container::ElementExistException
&) {
1728 SAL_INFO("cppuhelper", "Overwriting singleton " << i
->first
);
1729 cont
->replaceByName(name
, css::uno::Any());
1736 void cppuhelper::ServiceManager::removeRdbFiles(
1737 std::vector
< rtl::OUString
> const & uris
)
1739 // The underlying data structures make this function somewhat inefficient,
1740 // but the assumption is that it is rarely called (and that if it is called,
1741 // it is called with a uris vector of size one):
1742 std::vector
< boost::shared_ptr
< Data::Implementation
> > clear
;
1744 osl::MutexGuard
g(rBHelper
.rMutex
);
1745 for (std::vector
< rtl::OUString
>::const_iterator
i(uris
.begin());
1746 i
!= uris
.end(); ++i
)
1748 for (Data::NamedImplementations::iterator
j(
1749 data_
.namedImplementations
.begin());
1750 j
!= data_
.namedImplementations
.end();)
1752 assert(j
->second
.get() != 0);
1753 if (j
->second
->info
->rdbFile
== *i
) {
1754 clear
.push_back(j
->second
);
1755 //TODO: The below leaves data_ in an inconsistent state upon
1757 removeFromImplementationMap(
1758 &data_
.services
, j
->second
->info
->services
, j
->second
);
1759 removeFromImplementationMap(
1760 &data_
.singletons
, j
->second
->info
->singletons
,
1762 data_
.namedImplementations
.erase(j
++);
1769 //TODO: Update the component context singleton data
1772 bool cppuhelper::ServiceManager::removeLegacyFactory(
1773 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
,
1774 bool removeListener
)
1776 assert(factoryInfo
.is());
1777 boost::shared_ptr
< Data::Implementation
> clear
;
1778 css::uno::Reference
< css::lang::XComponent
> comp
;
1780 osl::MutexGuard
g(rBHelper
.rMutex
);
1781 Data::DynamicImplementations::iterator
i(
1782 data_
.dynamicImplementations
.find(factoryInfo
));
1783 if (i
== data_
.dynamicImplementations
.end()) {
1784 return isDisposed();
1786 assert(i
->second
.get() != 0);
1788 if (removeListener
) {
1789 comp
= i
->second
->component
;
1791 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1792 removeFromImplementationMap(
1793 &data_
.services
, i
->second
->info
->services
, i
->second
);
1794 removeFromImplementationMap(
1795 &data_
.singletons
, i
->second
->info
->singletons
, i
->second
);
1796 if (!i
->second
->info
->name
.isEmpty()) {
1797 data_
.namedImplementations
.erase(i
->second
->info
->name
);
1799 data_
.dynamicImplementations
.erase(i
);
1802 removeEventListenerFromComponent(comp
);
1807 void cppuhelper::ServiceManager::removeImplementation(const rtl::OUString
& name
) {
1808 // The underlying data structures make this function somewhat inefficient,
1809 // but the assumption is that it is rarely called:
1810 boost::shared_ptr
< Data::Implementation
> clear
;
1812 osl::MutexGuard
g(rBHelper
.rMutex
);
1816 Data::NamedImplementations::iterator
i(
1817 data_
.namedImplementations
.find(name
));
1818 if (i
== data_
.namedImplementations
.end()) {
1819 throw css::container::NoSuchElementException(
1820 "Remove non-inserted implementation " + name
,
1821 static_cast< cppu::OWeakObject
* >(this));
1823 assert(i
->second
.get() != 0);
1825 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1826 removeFromImplementationMap(
1827 &data_
.services
, i
->second
->info
->services
, i
->second
);
1828 removeFromImplementationMap(
1829 &data_
.singletons
, i
->second
->info
->singletons
, i
->second
);
1830 for (Data::DynamicImplementations::iterator
j(
1831 data_
.dynamicImplementations
.begin());
1832 j
!= data_
.dynamicImplementations
.end(); ++j
)
1834 if (j
->second
== i
->second
) {
1835 data_
.dynamicImplementations
.erase(j
);
1839 data_
.namedImplementations
.erase(i
);
1843 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
1844 cppuhelper::ServiceManager::findServiceImplementation(
1845 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
1846 rtl::OUString
const & specifier
)
1848 boost::shared_ptr
< Data::Implementation
> impl
;
1851 osl::MutexGuard
g(rBHelper
.rMutex
);
1852 Data::ImplementationMap::const_iterator
i(
1853 data_
.services
.find(specifier
));
1854 if (i
== data_
.services
.end()) {
1855 Data::NamedImplementations::const_iterator
j(
1856 data_
.namedImplementations
.find(specifier
));
1857 if (j
== data_
.namedImplementations
.end()) {
1858 SAL_INFO("cppuhelper", "No implementation for " << specifier
);
1859 return boost::shared_ptr
< Data::Implementation
>();
1863 assert(!i
->second
.empty());
1865 i
->second
.size() > 1, "cppuhelper",
1866 "Arbitrarily chosing " << i
->second
[0]->info
->name
1867 << " among multiple implementations for " << i
->first
);
1868 impl
= i
->second
[0];
1870 assert(impl
.get() != 0);
1871 loaded
= impl
->status
== Data::Implementation::STATUS_LOADED
;
1874 loadImplementation(context
, impl
);
1879 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */