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/XServiceInfo.hpp"
24 #include "com/sun/star/lang/XSingleComponentFactory.hpp"
25 #include "com/sun/star/lang/XSingleServiceFactory.hpp"
26 #include "com/sun/star/loader/XImplementationLoader.hpp"
27 #include "com/sun/star/registry/InvalidRegistryException.hpp"
28 #include "com/sun/star/uno/DeploymentException.hpp"
29 #include "com/sun/star/uno/Reference.hxx"
30 #include "com/sun/star/uno/XComponentContext.hpp"
31 #include "cppuhelper/bootstrap.hxx"
32 #include "cppuhelper/component_context.hxx"
33 #include "cppuhelper/implbase1.hxx"
34 #include "cppuhelper/implbase3.hxx"
35 #include "cppuhelper/shlib.hxx"
36 #include "cppuhelper/supportsservice.hxx"
37 #include "osl/file.hxx"
38 #include "rtl/ref.hxx"
39 #include "rtl/uri.hxx"
40 #include "rtl/ustring.hxx"
41 #include "rtl/strbuf.hxx"
42 #include "sal/log.hxx"
46 using rtl::OStringBuffer
;
48 #include "registry/registry.hxx"
49 #include "xmlreader/xmlreader.hxx"
52 #include "servicemanager.hxx"
56 void insertImplementationMap(
57 cppuhelper::ServiceManager::Data::ImplementationMap
* destination
,
58 cppuhelper::ServiceManager::Data::ImplementationMap
const & source
)
60 assert(destination
!= 0);
61 for (cppuhelper::ServiceManager::Data::ImplementationMap::const_iterator
i(
63 i
!= source
.end(); ++i
)
67 cppuhelper::ServiceManager::Data::Implementation
> > & impls
68 = (*destination
)[i
->first
];
69 impls
.insert(impls
.end(), i
->second
.begin(), i
->second
.end());
73 void removeFromImplementationMap(
74 cppuhelper::ServiceManager::Data::ImplementationMap
* map
,
75 std::vector
< rtl::OUString
> const & elements
,
76 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
77 const & implementation
)
79 // The underlying data structures make this function somewhat inefficient,
80 // but the assumption is that it is rarely called:
82 for (std::vector
< rtl::OUString
>::const_iterator
i(elements
.begin());
83 i
!= elements
.end(); ++i
)
85 cppuhelper::ServiceManager::Data::ImplementationMap::iterator
j(
87 assert(j
!= map
->end());
90 cppuhelper::ServiceManager::Data::Implementation
> >::iterator
91 k(std::find(j
->second
.begin(), j
->second
.end(), implementation
));
92 assert(k
!= j
->second
.end());
94 if (j
->second
.empty()) {
100 // For simplicity, this code keeps throwing
101 // css::registry::InvalidRegistryException for invalid XML rdbs (even though
102 // that does not fit the exception's name):
103 class Parser
: private boost::noncopyable
{
106 rtl::OUString
const & uri
,
107 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
,
108 cppuhelper::ServiceManager::Data
* data
);
111 void handleComponent();
113 void handleImplementation();
115 void handleService();
117 void handleSingleton();
119 rtl::OUString
getNameAttribute();
121 xmlreader::XmlReader reader_
;
122 css::uno::Reference
< css::uno::XComponentContext
> alienContext_
;
123 cppuhelper::ServiceManager::Data
* data_
;
124 rtl::OUString attrLoader_
;
125 rtl::OUString attrUri_
;
126 rtl::OUString attrPrefix_
;
127 rtl::OUString attrImplementation_
;
128 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
133 rtl::OUString
const & uri
,
134 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
,
135 cppuhelper::ServiceManager::Data
* data
):
136 reader_(uri
), alienContext_(alienContext
), data_(data
)
139 int ucNsId
= reader_
.registerNamespaceIri(
141 RTL_CONSTASCII_STRINGPARAM(
142 "http://openoffice.org/2010/uno-components")));
144 STATE_BEGIN
, STATE_END
, STATE_COMPONENTS
, STATE_COMPONENT_INITIAL
,
145 STATE_COMPONENT
, STATE_IMPLEMENTATION
, STATE_SERVICE
, STATE_SINGLETON
};
146 for (State state
= STATE_BEGIN
;;) {
147 xmlreader::Span name
;
149 xmlreader::XmlReader::Result res
= reader_
.nextItem(
150 xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
153 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
154 && name
.equals(RTL_CONSTASCII_STRINGPARAM("components")))
156 state
= STATE_COMPONENTS
;
159 throw css::registry::InvalidRegistryException(
160 reader_
.getUrl() + ": unexpected item in outer level",
161 css::uno::Reference
< css::uno::XInterface
>());
163 if (res
== xmlreader::XmlReader::RESULT_DONE
) {
166 throw css::registry::InvalidRegistryException(
167 reader_
.getUrl() + ": unexpected item in outer level",
168 css::uno::Reference
< css::uno::XInterface
>());
169 case STATE_COMPONENTS
:
170 if (res
== xmlreader::XmlReader::RESULT_END
) {
174 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
175 && name
.equals(RTL_CONSTASCII_STRINGPARAM("component")))
178 state
= STATE_COMPONENT_INITIAL
;
181 throw css::registry::InvalidRegistryException(
182 reader_
.getUrl() + ": unexpected item in <components>",
183 css::uno::Reference
< css::uno::XInterface
>());
184 case STATE_COMPONENT
:
185 if (res
== xmlreader::XmlReader::RESULT_END
) {
186 state
= STATE_COMPONENTS
;
190 case STATE_COMPONENT_INITIAL
:
191 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
192 && name
.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
194 handleImplementation();
195 state
= STATE_IMPLEMENTATION
;
198 throw css::registry::InvalidRegistryException(
199 reader_
.getUrl() + ": unexpected item in <component>",
200 css::uno::Reference
< css::uno::XInterface
>());
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>",
222 css::uno::Reference
< css::uno::XInterface
>());
224 if (res
== xmlreader::XmlReader::RESULT_END
) {
225 state
= STATE_IMPLEMENTATION
;
228 throw css::registry::InvalidRegistryException(
229 reader_
.getUrl() + ": unexpected item in <service>",
230 css::uno::Reference
< css::uno::XInterface
>());
231 case STATE_SINGLETON
:
232 if (res
== xmlreader::XmlReader::RESULT_END
) {
233 state
= STATE_IMPLEMENTATION
;
236 throw css::registry::InvalidRegistryException(
237 reader_
.getUrl() + ": unexpected item in <service>",
238 css::uno::Reference
< css::uno::XInterface
>());
243 void Parser::handleComponent() {
244 attrLoader_
= rtl::OUString();
245 attrUri_
= rtl::OUString();
246 attrPrefix_
= rtl::OUString();
247 xmlreader::Span name
;
249 while (reader_
.nextAttribute(&nsId
, &name
)) {
250 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
251 && name
.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
253 if (!attrLoader_
.isEmpty()) {
254 throw css::registry::InvalidRegistryException(
256 + ": <component> has multiple \"loader\" attributes"),
257 css::uno::Reference
< css::uno::XInterface
>());
259 attrLoader_
= reader_
.getAttributeValue(false).convertFromUtf8();
260 if (attrLoader_
.isEmpty()) {
261 throw css::registry::InvalidRegistryException(
263 + ": <component> has empty \"loader\" attribute"),
264 css::uno::Reference
< css::uno::XInterface
>());
266 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
267 && name
.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
269 if (!attrUri_
.isEmpty()) {
270 throw css::registry::InvalidRegistryException(
272 + ": <component> has multiple \"uri\" attributes"),
273 css::uno::Reference
< css::uno::XInterface
>());
275 attrUri_
= reader_
.getAttributeValue(false).convertFromUtf8();
276 if (attrUri_
.isEmpty()) {
277 throw css::registry::InvalidRegistryException(
279 + ": <component> has empty \"uri\" attribute"),
280 css::uno::Reference
< css::uno::XInterface
>());
282 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
283 && name
.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
285 if (!attrPrefix_
.isEmpty()) {
286 throw css::registry::InvalidRegistryException(
288 ": <component> has multiple \"prefix\" attributes"),
289 css::uno::Reference
< css::uno::XInterface
>());
291 attrPrefix_
= reader_
.getAttributeValue(false).convertFromUtf8();
292 if (attrPrefix_
.isEmpty()) {
293 throw css::registry::InvalidRegistryException(
295 ": <component> has empty \"prefix\" attribute"),
296 css::uno::Reference
< css::uno::XInterface
>());
299 throw css::registry::InvalidRegistryException(
300 (reader_
.getUrl() + ": unexpected attribute \""
301 + name
.convertFromUtf8() + "\" in <component>"),
302 css::uno::Reference
< css::uno::XInterface
>());
305 if (attrLoader_
.isEmpty()) {
306 throw css::registry::InvalidRegistryException(
307 reader_
.getUrl() + ": <component> is missing \"loader\" attribute",
308 css::uno::Reference
< css::uno::XInterface
>());
310 if (attrUri_
.isEmpty()) {
311 throw css::registry::InvalidRegistryException(
312 reader_
.getUrl() + ": <component> is missing \"uri\" attribute",
313 css::uno::Reference
< css::uno::XInterface
>());
315 #ifndef DISABLE_DYNLOADING
317 attrUri_
= rtl::Uri::convertRelToAbs(reader_
.getUrl(), attrUri_
);
318 } catch (const rtl::MalformedUriException
& e
) {
319 throw css::registry::InvalidRegistryException(
320 reader_
.getUrl() + ": bad \"uri\" attribute: " + e
.getMessage(),
321 css::uno::Reference
< css::uno::XInterface
>());
326 void Parser::handleImplementation() {
327 attrImplementation_
= getNameAttribute();
328 implementation_
.reset(
329 new cppuhelper::ServiceManager::Data::Implementation(
330 attrImplementation_
, attrLoader_
, attrUri_
, attrPrefix_
,
331 alienContext_
, reader_
.getUrl()));
332 if (!data_
->namedImplementations
.insert(
333 cppuhelper::ServiceManager::Data::NamedImplementations::value_type(
334 attrImplementation_
, implementation_
)).
337 throw css::registry::InvalidRegistryException(
338 (reader_
.getUrl() + ": duplicate <implementation name=\""
339 + attrImplementation_
+ "\">"),
340 css::uno::Reference
< css::uno::XInterface
>());
344 void Parser::handleService() {
345 rtl::OUString
name(getNameAttribute());
346 implementation_
->info
->services
.push_back(name
);
347 data_
->services
[name
].push_back(implementation_
);
350 void Parser::handleSingleton() {
351 rtl::OUString
name(getNameAttribute());
352 implementation_
->info
->singletons
.push_back(name
);
353 data_
->singletons
[name
].push_back(implementation_
);
356 rtl::OUString
Parser::getNameAttribute() {
357 rtl::OUString attrName
;
358 xmlreader::Span name
;
360 while (reader_
.nextAttribute(&nsId
, &name
)) {
361 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
362 && name
.equals(RTL_CONSTASCII_STRINGPARAM("name")))
364 if (!attrName
.isEmpty()) {
365 throw css::registry::InvalidRegistryException(
367 + ": element has multiple \"name\" attributes"),
368 css::uno::Reference
< css::uno::XInterface
>());
370 attrName
= reader_
.getAttributeValue(false).convertFromUtf8();
371 if (attrName
.isEmpty()) {
372 throw css::registry::InvalidRegistryException(
373 reader_
.getUrl() + ": element has empty \"name\" attribute",
374 css::uno::Reference
< css::uno::XInterface
>());
377 throw css::registry::InvalidRegistryException(
378 reader_
.getUrl() + ": expected element attribute \"name\"",
379 css::uno::Reference
< css::uno::XInterface
>());
382 if (attrName
.isEmpty()) {
383 throw css::registry::InvalidRegistryException(
384 reader_
.getUrl() + ": element is missing \"name\" attribute",
385 css::uno::Reference
< css::uno::XInterface
>());
390 class ContentEnumeration
:
391 public cppu::WeakImplHelper1
< css::container::XEnumeration
>,
392 private boost::noncopyable
395 explicit ContentEnumeration(std::vector
< css::uno::Any
> const & factories
):
396 factories_(factories
), iterator_(factories_
.begin()) {}
399 virtual ~ContentEnumeration() {}
401 virtual sal_Bool SAL_CALL
hasMoreElements()
402 throw (css::uno::RuntimeException
);
404 virtual css::uno::Any SAL_CALL
nextElement()
406 css::container::NoSuchElementException
,
407 css::lang::WrappedTargetException
, css::uno::RuntimeException
);
410 std::vector
< css::uno::Any
> factories_
;
411 std::vector
< css::uno::Any
>::const_iterator iterator_
;
414 sal_Bool
ContentEnumeration::hasMoreElements()
415 throw (css::uno::RuntimeException
)
417 osl::MutexGuard
g(mutex_
);
418 return iterator_
!= factories_
.end();
421 css::uno::Any
ContentEnumeration::nextElement()
423 css::container::NoSuchElementException
,
424 css::lang::WrappedTargetException
, css::uno::RuntimeException
)
426 osl::MutexGuard
g(mutex_
);
427 if (iterator_
== factories_
.end()) {
428 throw css::container::NoSuchElementException(
429 "Bootstrap service manager service enumerator has no more elements",
430 static_cast< cppu::OWeakObject
* >(this));
435 css::beans::Property
getDefaultContextProperty() {
436 return css::beans::Property(
437 "DefaultContext", -1,
438 cppu::UnoType
< css::uno::XComponentContext
>::get(),
439 css::beans::PropertyAttribute::READONLY
);
442 class FactoryWrapper
:
443 public cppu::WeakImplHelper3
<
444 css::lang::XSingleComponentFactory
, css::lang::XSingleServiceFactory
,
445 css::lang::XServiceInfo
>,
446 private boost::noncopyable
450 rtl::Reference
< cppuhelper::ServiceManager
> const & manager
,
452 cppuhelper::ServiceManager::Data::ImplementationInfo
> const &
454 manager_(manager
), info_(info
), loaded_(false)
455 { assert(manager
.is() && info
.get() != 0); }
458 virtual ~FactoryWrapper() {}
460 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
461 createInstanceWithContext(
462 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
463 throw (css::uno::Exception
, css::uno::RuntimeException
);
465 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
466 createInstanceWithArgumentsAndContext(
467 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
468 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
469 throw (css::uno::Exception
, css::uno::RuntimeException
);
471 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
472 createInstance() throw (css::uno::Exception
, css::uno::RuntimeException
);
474 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
475 createInstanceWithArguments(
476 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
477 throw (css::uno::Exception
, css::uno::RuntimeException
);
479 virtual rtl::OUString SAL_CALL
getImplementationName()
480 throw (css::uno::RuntimeException
);
482 virtual sal_Bool SAL_CALL
supportsService(rtl::OUString
const & ServiceName
)
483 throw (css::uno::RuntimeException
);
485 virtual css::uno::Sequence
< rtl::OUString
> SAL_CALL
486 getSupportedServiceNames() throw (css::uno::RuntimeException
);
488 void loadImplementation(
489 css::uno::Reference
< css::uno::XComponentContext
> const & context
);
491 rtl::Reference
< cppuhelper::ServiceManager
> manager_
;
492 boost::shared_ptr
< cppuhelper::ServiceManager::Data::ImplementationInfo
>
497 css::uno::Reference
< css::lang::XSingleComponentFactory
> factory1_
;
498 css::uno::Reference
< css::lang::XSingleServiceFactory
> factory2_
;
501 css::uno::Reference
< css::uno::XInterface
>
502 FactoryWrapper::createInstanceWithContext(
503 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
504 throw (css::uno::Exception
, css::uno::RuntimeException
)
506 loadImplementation(Context
);
507 return factory1_
.is()
508 ? factory1_
->createInstanceWithContext(Context
)
509 : factory2_
->createInstance();
512 css::uno::Reference
< css::uno::XInterface
>
513 FactoryWrapper::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
)
518 loadImplementation(Context
);
519 return factory1_
.is()
520 ? factory1_
->createInstanceWithArgumentsAndContext(Arguments
, Context
)
521 : factory2_
->createInstanceWithArguments(Arguments
);
524 css::uno::Reference
< css::uno::XInterface
> FactoryWrapper::createInstance()
525 throw (css::uno::Exception
, css::uno::RuntimeException
)
527 loadImplementation(manager_
->getContext());
528 return factory1_
.is()
529 ? factory1_
->createInstanceWithContext(manager_
->getContext())
530 : factory2_
->createInstance();
533 css::uno::Reference
< css::uno::XInterface
>
534 FactoryWrapper::createInstanceWithArguments(
535 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
536 throw (css::uno::Exception
, css::uno::RuntimeException
)
538 loadImplementation(manager_
->getContext());
539 return factory1_
.is()
540 ? factory1_
->createInstanceWithArgumentsAndContext(
541 Arguments
, manager_
->getContext())
542 : factory2_
->createInstanceWithArguments(Arguments
);
545 rtl::OUString
FactoryWrapper::getImplementationName()
546 throw (css::uno::RuntimeException
)
551 sal_Bool
FactoryWrapper::supportsService(rtl::OUString
const & ServiceName
)
552 throw (css::uno::RuntimeException
)
554 return cppu::supportsService(this, ServiceName
);
557 css::uno::Sequence
< rtl::OUString
> FactoryWrapper::getSupportedServiceNames()
558 throw (css::uno::RuntimeException
)
560 if (info_
->services
.size() > static_cast< sal_uInt32
>(SAL_MAX_INT32
)) {
561 throw css::uno::RuntimeException(
562 "Implementation " + info_
->name
+ " supports too many services",
563 static_cast< cppu::OWeakObject
* >(this));
565 css::uno::Sequence
< rtl::OUString
> names(
566 static_cast< sal_Int32
>(info_
->services
.size()));
568 for (std::vector
< rtl::OUString
>::const_iterator
j(
569 info_
->services
.begin());
570 j
!= info_
->services
.end(); ++j
)
577 void FactoryWrapper::loadImplementation(
578 css::uno::Reference
< css::uno::XComponentContext
> const & context
)
581 osl::MutexGuard
g(mutex_
);
586 css::uno::Reference
< css::lang::XSingleComponentFactory
> f1
;
587 css::uno::Reference
< css::lang::XSingleServiceFactory
> f2
;
588 //TODO: There is a race here, as the relevant service factory can already
589 // have been removed and loading can thus fail, as the entity from which to
590 // load can disappear once the service factory is removed:
591 manager_
->loadImplementation(context
, info_
, &f1
, &f2
);
592 if (!(f1
.is() || f2
.is())) {
593 throw css::uno::DeploymentException(
594 "Implementation " + info_
->name
+ " does not provide a factory",
595 static_cast< cppu::OWeakObject
* >(this));
597 osl::MutexGuard
g(mutex_
);
607 void cppuhelper::ServiceManager::addSingletonContextEntries(
608 std::vector
< cppu::ContextEntry_Init
> * entries
) const
610 assert(entries
!= 0);
611 for (Data::ImplementationMap::const_iterator
i(data_
.singletons
.begin());
612 i
!= data_
.singletons
.end(); ++i
)
614 assert(!i
->second
.empty());
615 assert(i
->second
[0].get() != 0);
617 i
->second
.size() > 1, "cppuhelper",
618 "Arbitrarily chosing " << i
->second
[0]->info
->name
619 << " among multiple implementations for " << i
->first
);
621 cppu::ContextEntry_Init(
622 "/singletons/" + i
->first
,
623 css::uno::makeAny(i
->second
[0]->info
->name
), true));
627 void cppuhelper::ServiceManager::loadImplementation(
628 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
629 boost::shared_ptr
< Data::ImplementationInfo
> const & info
,
630 css::uno::Reference
< css::lang::XSingleComponentFactory
> * factory1
,
631 css::uno::Reference
< css::lang::XSingleServiceFactory
> * factory2
)
634 info
.get() != 0 && factory1
!= 0 && !factory1
->is() && factory2
!= 0
638 uri
= cppu::bootstrap_expandUri(info
->uri
);
639 } catch (css::lang::IllegalArgumentException
& e
) {
640 throw css::uno::DeploymentException(
641 "Cannot expand URI" + info
->uri
+ ": " + e
.Message
,
642 static_cast< cppu::OWeakObject
* >(this));
644 css::uno::Reference
< css::uno::XInterface
> f0
;
645 // Shortcut loading via SharedLibrary loader, to pass in prefix argument
646 // (which the loader's activate implementation would normally obtain through
647 // the legacy xKey argument):
648 if (!info
->alienContext
.is()
649 && info
->loader
== "com.sun.star.loader.SharedLibrary")
651 rtl::OUString
prefix(info
->prefix
);
652 if (!prefix
.isEmpty()) {
655 f0
= cppu::loadSharedLibComponentFactory(
656 uri
, rtl::OUString(), info
->name
, this,
657 css::uno::Reference
< css::registry::XRegistryKey
>(), prefix
);
660 !info
->prefix
.isEmpty(), "cppuhelper",
661 "Loader " << info
->loader
<< " and non-empty prefix "
663 css::uno::Reference
< css::uno::XComponentContext
> ctxt
;
664 css::uno::Reference
< css::lang::XMultiComponentFactory
> smgr
;
665 if (info
->alienContext
.is()) {
666 ctxt
= info
->alienContext
;
667 smgr
= css::uno::Reference
< css::lang::XMultiComponentFactory
>(
668 ctxt
->getServiceManager(), css::uno::UNO_SET_THROW
);
670 assert(context
.is());
674 css::uno::Reference
< css::loader::XImplementationLoader
> loader(
675 smgr
->createInstanceWithContext(info
->loader
, ctxt
),
676 css::uno::UNO_QUERY_THROW
);
677 f0
= loader
->activate(
678 info
->name
, rtl::OUString(), uri
,
679 css::uno::Reference
< css::registry::XRegistryKey
>());
681 factory1
->set(f0
, css::uno::UNO_QUERY
);
682 if (!factory1
->is()) {
683 factory2
->set(f0
, css::uno::UNO_QUERY
);
687 void cppuhelper::ServiceManager::disposing() {
688 std::vector
< css::uno::Reference
< css::lang::XComponent
> > comps
;
691 osl::MutexGuard
g(rBHelper
.rMutex
);
692 for (Data::DynamicImplementations::const_iterator
i(
693 data_
.dynamicImplementations
.begin());
694 i
!= data_
.dynamicImplementations
.end(); ++i
)
696 assert(i
->second
.get() != 0);
697 if (i
->second
->component
.is()) {
698 comps
.push_back(i
->second
->component
);
701 data_
.namedImplementations
.swap(clear
.namedImplementations
);
702 data_
.dynamicImplementations
.swap(clear
.dynamicImplementations
);
703 data_
.services
.swap(clear
.services
);
704 data_
.singletons
.swap(clear
.singletons
);
707 css::uno::Reference
< css::lang::XComponent
> >::const_iterator
i(
709 i
!= comps
.end(); ++i
)
711 removeEventListenerFromComponent(*i
);
715 rtl::OUString
cppuhelper::ServiceManager::getImplementationName()
716 throw (css::uno::RuntimeException
)
718 return rtl::OUString(
719 "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager");
722 sal_Bool
cppuhelper::ServiceManager::supportsService(
723 rtl::OUString
const & ServiceName
)
724 throw (css::uno::RuntimeException
)
726 return cppu::supportsService(this, ServiceName
);
729 css::uno::Sequence
< rtl::OUString
>
730 cppuhelper::ServiceManager::getSupportedServiceNames()
731 throw (css::uno::RuntimeException
)
733 css::uno::Sequence
< rtl::OUString
> names(2);
734 names
[0] = "com.sun.star.lang.MultiServiceFactory";
735 names
[1] = "com.sun.star.lang.ServiceManager";
739 css::uno::Reference
< css::uno::XInterface
>
740 cppuhelper::ServiceManager::createInstance(
741 rtl::OUString
const & aServiceSpecifier
)
742 throw (css::uno::Exception
, css::uno::RuntimeException
)
744 assert(context_
.is());
745 return createInstanceWithContext(aServiceSpecifier
, context_
);
748 css::uno::Reference
< css::uno::XInterface
>
749 cppuhelper::ServiceManager::createInstanceWithArguments(
750 rtl::OUString
const & ServiceSpecifier
,
751 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
752 throw (css::uno::Exception
, css::uno::RuntimeException
)
754 assert(context_
.is());
755 return createInstanceWithArgumentsAndContext(
756 ServiceSpecifier
, Arguments
, context_
);
759 css::uno::Sequence
< rtl::OUString
>
760 cppuhelper::ServiceManager::getAvailableServiceNames()
761 throw (css::uno::RuntimeException
)
763 osl::MutexGuard
g(rBHelper
.rMutex
);
765 return css::uno::Sequence
< rtl::OUString
>();
767 Data::ImplementationMap::size_type n
= data_
.services
.size();
768 if (n
> static_cast< sal_uInt32
>(SAL_MAX_INT32
)) {
769 throw css::uno::RuntimeException(
770 "getAvailableServiceNames: too many services",
771 static_cast< cppu::OWeakObject
* >(this));
773 css::uno::Sequence
< rtl::OUString
> names(static_cast< sal_Int32
>(n
));
775 for (Data::ImplementationMap::const_iterator
j(data_
.services
.begin());
776 j
!= data_
.services
.end(); ++j
)
778 names
[i
++] = j
->first
;
780 assert(i
== names
.getLength());
784 css::uno::Reference
< css::uno::XInterface
>
785 cppuhelper::ServiceManager::createInstanceWithContext(
786 rtl::OUString
const & aServiceSpecifier
,
787 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
788 throw (css::uno::Exception
, css::uno::RuntimeException
)
790 boost::shared_ptr
< Data::Implementation
> impl(
791 findServiceImplementation(Context
, aServiceSpecifier
));
792 if (impl
.get() == 0) {
793 return css::uno::Reference
< css::uno::XInterface
>();
795 if (impl
->factory1
.is()) {
796 return impl
->factory1
->createInstanceWithContext(Context
);
798 if (impl
->factory2
.is()) {
799 return impl
->factory2
->createInstance();
801 throw css::uno::DeploymentException(
802 "Implementation " + impl
->info
->name
+ " does not provide a factory",
803 static_cast< cppu::OWeakObject
* >(this));
806 css::uno::Reference
< css::uno::XInterface
>
807 cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
808 rtl::OUString
const & ServiceSpecifier
,
809 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
810 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
811 throw (css::uno::Exception
, css::uno::RuntimeException
)
813 boost::shared_ptr
< Data::Implementation
> impl(
814 findServiceImplementation(Context
, ServiceSpecifier
));
815 if (impl
.get() == 0) {
816 return css::uno::Reference
< css::uno::XInterface
>();
818 if (impl
->factory1
.is()) {
819 return impl
->factory1
->createInstanceWithArgumentsAndContext(
822 if (impl
->factory2
.is()) {
823 return impl
->factory2
->createInstanceWithArguments(Arguments
);
825 throw css::uno::DeploymentException(
826 "Implementation " + impl
->info
->name
+ " does not provide a factory",
827 static_cast< cppu::OWeakObject
* >(this));
830 css::uno::Type
cppuhelper::ServiceManager::getElementType()
831 throw (css::uno::RuntimeException
)
833 return css::uno::Type();
836 sal_Bool
cppuhelper::ServiceManager::hasElements()
837 throw (css::uno::RuntimeException
)
839 osl::MutexGuard
g(rBHelper
.rMutex
);
841 !(data_
.namedImplementations
.empty()
842 && data_
.dynamicImplementations
.empty());
845 css::uno::Reference
< css::container::XEnumeration
>
846 cppuhelper::ServiceManager::createEnumeration()
847 throw (css::uno::RuntimeException
)
849 throw css::uno::RuntimeException(
850 "ServiceManager createEnumeration: method not supported",
851 static_cast< cppu::OWeakObject
* >(this));
854 sal_Bool
cppuhelper::ServiceManager::has(css::uno::Any
const &)
855 throw (css::uno::RuntimeException
)
857 throw css::uno::RuntimeException(
858 "ServiceManager has: method not supported",
859 static_cast< cppu::OWeakObject
* >(this));
862 void cppuhelper::ServiceManager::insert(css::uno::Any
const & aElement
)
864 css::lang::IllegalArgumentException
,
865 css::container::ElementExistException
, css::uno::RuntimeException
)
867 css::uno::Sequence
< css::beans::NamedValue
> args
;
868 if (aElement
>>= args
) {
869 std::vector
< rtl::OUString
> uris
;
870 css::uno::Reference
< css::uno::XComponentContext
> alienContext
;
871 for (sal_Int32 i
= 0; i
< args
.getLength(); ++i
) {
872 if (args
[i
].Name
== "uri") {
874 if (!(args
[i
].Value
>>= uri
)) {
875 throw css::lang::IllegalArgumentException(
877 static_cast< cppu::OWeakObject
* >(this), 0);
880 } else if (args
[i
].Name
== "component-context") {
881 if (alienContext
.is()) {
882 throw css::lang::IllegalArgumentException(
883 "Multiple component-context arguments",
884 static_cast< cppu::OWeakObject
* >(this), 0);
886 if (!(args
[i
].Value
>>= alienContext
) || !alienContext
.is()) {
887 throw css::lang::IllegalArgumentException(
888 "Bad component-context argument",
889 static_cast< cppu::OWeakObject
* >(this), 0);
892 throw css::lang::IllegalArgumentException(
893 "Bad argument " + args
[i
].Name
,
894 static_cast< cppu::OWeakObject
* >(this), 0);
897 insertRdbFiles(uris
, alienContext
);
900 css::uno::Reference
< css::lang::XServiceInfo
> info
;
901 if ((aElement
>>= info
) && info
.is()) {
902 insertLegacyFactory(info
);
905 // At least revisions up to 1.7 of LanguageTool.oxt (incl. the bundled 1.4.0 in
906 // module languagetool) contain an (actively registered) factory that does not
907 // implement XServiceInfo (see <http://sourceforge.net/tracker/?
908 // func=detail&aid=3526635&group_id=110216&atid=655717> "SingletonFactory should
909 // implement XServiceInfo"); the old OServiceManager::insert
910 // (stoc/source/servicemanager/servicemanager.cxx) silently did not add such
911 // broken factories to its m_ImplementationNameMap, so ignore them here for
912 // backwards compatibility of live-insertion of extensions, too.
914 // (The plan was that this warning would go away (and we would do the
915 // throw instead) for the incompatible LO 4, but we changed our mind):
916 css::uno::Reference
< css::lang::XSingleComponentFactory
> legacy
;
917 if ((aElement
>>= legacy
) && legacy
.is()) {
920 "Ignored XSingleComponentFactory not implementing XServiceInfo");
924 throw css::lang::IllegalArgumentException(
925 "Bad insert element", static_cast< cppu::OWeakObject
* >(this), 0);
928 void cppuhelper::ServiceManager::remove(css::uno::Any
const & aElement
)
930 css::lang::IllegalArgumentException
,
931 css::container::NoSuchElementException
, css::uno::RuntimeException
)
933 css::uno::Sequence
< css::beans::NamedValue
> args
;
934 if (aElement
>>= args
) {
935 std::vector
< rtl::OUString
> uris
;
936 for (sal_Int32 i
= 0; i
< args
.getLength(); ++i
) {
937 if (args
[i
].Name
== "uri") {
939 if (!(args
[i
].Value
>>= uri
)) {
940 throw css::lang::IllegalArgumentException(
942 static_cast< cppu::OWeakObject
* >(this), 0);
946 throw css::lang::IllegalArgumentException(
947 "Bad argument " + args
[i
].Name
,
948 static_cast< cppu::OWeakObject
* >(this), 0);
951 removeRdbFiles(uris
);
954 css::uno::Reference
< css::lang::XServiceInfo
> info
;
955 if ((aElement
>>= info
) && info
.is()) {
956 if (!removeLegacyFactory(info
, true)) {
957 throw css::container::NoSuchElementException(
958 "Remove non-inserted factory object",
959 static_cast< cppu::OWeakObject
* >(this));
964 if (aElement
>>= impl
) {
965 // For live-removal of extensions:
966 removeImplementation(impl
);
969 throw css::lang::IllegalArgumentException(
970 "Bad remove element", static_cast< cppu::OWeakObject
* >(this), 0);
973 css::uno::Reference
< css::container::XEnumeration
>
974 cppuhelper::ServiceManager::createContentEnumeration(
975 rtl::OUString
const & aServiceName
)
976 throw (css::uno::RuntimeException
)
978 std::vector
< boost::shared_ptr
< Data::Implementation
> > impls
;
980 osl::MutexGuard
g(rBHelper
.rMutex
);
981 Data::ImplementationMap::const_iterator
i(
982 data_
.services
.find(aServiceName
));
983 if (i
!= data_
.services
.end()) {
987 std::vector
< css::uno::Any
> factories
;
989 boost::shared_ptr
< Data::Implementation
> >::const_iterator
i(
991 i
!= impls
.end(); ++i
)
993 Data::Implementation
* impl
= i
->get();
996 osl::MutexGuard
g(rBHelper
.rMutex
);
1001 if (!impl
->loaded
) {
1002 // Postpone actual factory instantiation as long as possible (so
1003 // that e.g. opening LO's "Tools - Macros" menu does not try to
1004 // instantiate a JVM, which can lead to a synchronous error
1005 // dialog when no JVM is specified, and showing the dialog while
1006 // hovering over a menu can cause trouble):
1007 impl
->factory1
= new FactoryWrapper(this, impl
->info
);
1008 impl
->loaded
= true;
1011 if (impl
->factory1
.is()) {
1012 factories
.push_back(css::uno::makeAny(impl
->factory1
));
1013 } else if (impl
->factory2
.is()) {
1014 factories
.push_back(css::uno::makeAny(impl
->factory2
));
1016 throw css::uno::DeploymentException(
1017 ("Implementation " + impl
->info
->name
1018 + " does not provide a factory"),
1019 static_cast< cppu::OWeakObject
* >(this));
1022 return new ContentEnumeration(factories
);
1025 css::uno::Reference
< css::beans::XPropertySetInfo
>
1026 cppuhelper::ServiceManager::getPropertySetInfo()
1027 throw (css::uno::RuntimeException
)
1032 void cppuhelper::ServiceManager::setPropertyValue(
1033 rtl::OUString
const & aPropertyName
, css::uno::Any
const &)
1035 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1036 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1037 css::uno::RuntimeException
)
1039 if (aPropertyName
== "DefaultContext") {
1040 throw css::beans::PropertyVetoException(
1041 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1043 throw css::beans::UnknownPropertyException(
1044 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1048 css::uno::Any
cppuhelper::ServiceManager::getPropertyValue(
1049 rtl::OUString
const & PropertyName
)
1051 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1052 css::uno::RuntimeException
)
1054 if (PropertyName
!= "DefaultContext") {
1055 throw css::beans::UnknownPropertyException(
1056 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1058 assert(context_
.is());
1059 return css::uno::makeAny(context_
);
1062 void cppuhelper::ServiceManager::addPropertyChangeListener(
1063 rtl::OUString
const & aPropertyName
,
1064 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
1067 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1068 css::uno::RuntimeException
)
1070 if (!aPropertyName
.isEmpty() && aPropertyName
!= "DefaultContext") {
1071 throw css::beans::UnknownPropertyException(
1072 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1074 // DefaultContext does not change, so just treat it as an event listener:
1075 return addEventListener(xListener
.get());
1078 void cppuhelper::ServiceManager::removePropertyChangeListener(
1079 rtl::OUString
const & aPropertyName
,
1080 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
1083 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1084 css::uno::RuntimeException
)
1086 if (!aPropertyName
.isEmpty() && aPropertyName
!= "DefaultContext") {
1087 throw css::beans::UnknownPropertyException(
1088 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1090 // DefaultContext does not change, so just treat it as an event listener:
1091 return removeEventListener(aListener
.get());
1094 void cppuhelper::ServiceManager::addVetoableChangeListener(
1095 rtl::OUString
const & PropertyName
,
1096 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
1099 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1100 css::uno::RuntimeException
)
1102 if (!PropertyName
.isEmpty() && PropertyName
!= "DefaultContext") {
1103 throw css::beans::UnknownPropertyException(
1104 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1106 // DefaultContext does not change, so just treat it as an event listener:
1107 return addEventListener(aListener
.get());
1110 void cppuhelper::ServiceManager::removeVetoableChangeListener(
1111 rtl::OUString
const & PropertyName
,
1112 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
1115 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1116 css::uno::RuntimeException
)
1118 if (!PropertyName
.isEmpty() && PropertyName
!= "DefaultContext") {
1119 throw css::beans::UnknownPropertyException(
1120 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1122 // DefaultContext does not change, so just treat it as an event listener:
1123 return removeEventListener(aListener
.get());
1126 css::uno::Sequence
< css::beans::Property
>
1127 cppuhelper::ServiceManager::getProperties() throw (css::uno::RuntimeException
) {
1128 css::uno::Sequence
< css::beans::Property
> props(1);
1129 props
[0] = getDefaultContextProperty();
1133 css::beans::Property
cppuhelper::ServiceManager::getPropertyByName(
1134 rtl::OUString
const & aName
)
1135 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
)
1137 if (aName
!= "DefaultContext") {
1138 throw css::beans::UnknownPropertyException(
1139 aName
, static_cast< cppu::OWeakObject
* >(this));
1141 return getDefaultContextProperty();
1144 sal_Bool
cppuhelper::ServiceManager::hasPropertyByName(
1145 rtl::OUString
const & Name
)
1146 throw (css::uno::RuntimeException
)
1148 return Name
== "DefaultContext";
1151 void cppuhelper::ServiceManager::disposing(
1152 css::lang::EventObject
const & Source
)
1153 throw (css::uno::RuntimeException
)
1155 removeLegacyFactory(
1156 css::uno::Reference
< css::lang::XServiceInfo
>(
1157 Source
.Source
, css::uno::UNO_QUERY_THROW
),
1161 void cppuhelper::ServiceManager::removeEventListenerFromComponent(
1162 css::uno::Reference
< css::lang::XComponent
> const & component
)
1164 assert(component
.is());
1166 component
->removeEventListener(this);
1167 } catch (css::uno::RuntimeException
& e
) {
1170 "Ignored removeEventListener RuntimeException " + e
.Message
);
1174 void cppuhelper::ServiceManager::readRdbs(rtl::OUString
const & uris
) {
1175 for (sal_Int32 i
= 0; i
!= -1;) {
1176 rtl::OUString
uri(uris
.getToken(0, ' ', i
));
1177 if (uri
.isEmpty()) {
1182 cppu::decodeRdbUri(&uri
, &optional
, &directory
);
1184 readRdbDirectory(uri
, optional
);
1186 readRdbFile(uri
, optional
);
1191 void cppuhelper::ServiceManager::readRdbDirectory(
1192 rtl::OUString
const & uri
, bool optional
)
1194 osl::Directory
dir(uri
);
1195 switch (dir
.open()) {
1196 case osl::FileBase::E_None
:
1198 case osl::FileBase::E_NOENT
:
1200 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
1205 throw css::uno::DeploymentException(
1206 "Cannot open directory " + uri
,
1207 static_cast< cppu::OWeakObject
* >(this));
1211 if (!cppu::nextDirectoryItem(dir
, &url
)) {
1214 readRdbFile(url
, false);
1218 void cppuhelper::ServiceManager::readRdbFile(
1219 rtl::OUString
const & uri
, bool optional
)
1223 uri
, css::uno::Reference
< css::uno::XComponentContext
>(), &data_
);
1224 } catch (css::container::NoSuchElementException
&) {
1226 throw css::uno::DeploymentException(
1227 uri
+ ": no such file",
1228 static_cast< cppu::OWeakObject
* >(this));
1230 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
1231 } catch (css::registry::InvalidRegistryException
& e
) {
1232 if (!readLegacyRdbFile(uri
)) {
1233 throw css::uno::DeploymentException(
1234 "InvalidRegistryException: " + e
.Message
,
1235 static_cast< cppu::OWeakObject
* >(this));
1237 } catch (css::uno::RuntimeException
&) {
1238 if (!readLegacyRdbFile(uri
)) {
1244 bool cppuhelper::ServiceManager::readLegacyRdbFile(rtl::OUString
const & uri
) {
1246 switch (reg
.open(uri
, REG_READONLY
)) {
1249 case REG_REGISTRY_NOT_EXISTS
:
1250 case REG_INVALID_REGISTRY
:
1252 // Ignore empty rdb files (which are at least seen by subordinate
1253 // uno processes during extension registration; Registry::open can
1254 // fail on them if mmap(2) returns EINVAL for a zero length):
1255 osl::DirectoryItem item
;
1256 if (osl::DirectoryItem::get(uri
, item
) == osl::FileBase::E_None
) {
1257 osl::FileStatus
status(osl_FileStatus_Mask_FileSize
);
1258 if (item
.getFileStatus(status
) == osl::FileBase::E_None
1259 && status
.getFileSize() == 0)
1269 RegistryKey rootKey
;
1270 if (reg
.openRootKey(rootKey
) != REG_NO_ERROR
) {
1271 throw css::uno::DeploymentException(
1272 "Failure reading legacy rdb file " + uri
,
1273 static_cast< cppu::OWeakObject
* >(this));
1275 RegistryKeyArray impls
;
1276 switch (rootKey
.openSubKeys("IMPLEMENTATIONS", impls
)) {
1279 case REG_KEY_NOT_EXISTS
:
1282 throw css::uno::DeploymentException(
1283 "Failure reading legacy rdb file " + uri
,
1284 static_cast< cppu::OWeakObject
* >(this));
1286 for (sal_uInt32 i
= 0; i
!= impls
.getLength(); ++i
) {
1287 RegistryKey
implKey(impls
.getElement(i
));
1288 assert(implKey
.getName().match("/IMPLEMENTATIONS/"));
1290 implKey
.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1291 boost::shared_ptr
< Data::Implementation
> impl(
1292 new Data::Implementation(
1293 name
, readLegacyRdbString(uri
, implKey
, "UNO/ACTIVATOR"),
1294 readLegacyRdbString(uri
, implKey
, "UNO/LOCATION"),
1296 css::uno::Reference
< css::uno::XComponentContext
>(), uri
));
1297 if (!data_
.namedImplementations
.insert(
1298 Data::NamedImplementations::value_type(name
, impl
)).
1301 throw css::registry::InvalidRegistryException(
1302 uri
+ ": duplicate <implementation name=\"" + name
+ "\">",
1303 css::uno::Reference
< css::uno::XInterface
>());
1305 readLegacyRdbStrings(
1306 uri
, implKey
, "UNO/SERVICES", &impl
->info
->services
);
1307 for (std::vector
< rtl::OUString
>::const_iterator
j(
1308 impl
->info
->services
.begin());
1309 j
!= impl
->info
->services
.end(); ++j
)
1311 data_
.services
[*j
].push_back(impl
);
1313 readLegacyRdbStrings(
1314 uri
, implKey
, "UNO/SINGLETONS", &impl
->info
->singletons
);
1315 for (std::vector
< rtl::OUString
>::const_iterator
j(
1316 impl
->info
->singletons
.begin());
1317 j
!= impl
->info
->singletons
.end(); ++j
)
1319 data_
.singletons
[*j
].push_back(impl
);
1325 rtl::OUString
cppuhelper::ServiceManager::readLegacyRdbString(
1326 rtl::OUString
const & uri
, RegistryKey
& key
, rtl::OUString
const & path
)
1331 if (key
.openKey(path
, subkey
) != REG_NO_ERROR
1332 || subkey
.getValueInfo(rtl::OUString(), &t
, &s
) != REG_NO_ERROR
1333 || t
!= RG_VALUETYPE_STRING
1334 || s
== 0 || s
> static_cast< sal_uInt32
>(SAL_MAX_INT32
))
1336 throw css::uno::DeploymentException(
1337 "Failure reading legacy rdb file " + uri
,
1338 static_cast< cppu::OWeakObject
* >(this));
1341 std::vector
< char > v(s
); // assuming sal_uInt32 fits into vector::size_type
1342 if (subkey
.getValue(rtl::OUString(), &v
[0]) != REG_NO_ERROR
1344 || !rtl_convertStringToUString(
1345 &val
.pData
, &v
[0], static_cast< sal_Int32
>(s
- 1),
1346 RTL_TEXTENCODING_UTF8
,
1347 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1348 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1349 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
)))
1351 throw css::uno::DeploymentException(
1352 "Failure reading legacy rdb file " + uri
,
1353 static_cast< cppu::OWeakObject
* >(this));
1358 void cppuhelper::ServiceManager::readLegacyRdbStrings(
1359 rtl::OUString
const & uri
, RegistryKey
& key
, rtl::OUString
const & path
,
1360 std::vector
< rtl::OUString
> * strings
)
1362 assert(strings
!= 0);
1364 switch (key
.openKey(path
, subkey
)) {
1367 case REG_KEY_NOT_EXISTS
:
1370 throw css::uno::DeploymentException(
1371 "Failure reading legacy rdb file " + uri
,
1372 static_cast< cppu::OWeakObject
* >(this));
1374 rtl::OUString
prefix(subkey
.getName() + "/");
1375 RegistryKeyNames names
;
1376 if (subkey
.getKeyNames(rtl::OUString(), names
) != REG_NO_ERROR
) {
1377 throw css::uno::DeploymentException(
1378 "Failure reading legacy rdb file " + uri
,
1379 static_cast< cppu::OWeakObject
* >(this));
1381 for (sal_uInt32 i
= 0; i
!= names
.getLength(); ++i
) {
1382 assert(names
.getElement(i
).match(prefix
));
1383 strings
->push_back(names
.getElement(i
).copy(prefix
.getLength()));
1387 void cppuhelper::ServiceManager::insertRdbFiles(
1388 std::vector
< rtl::OUString
> const & uris
,
1389 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
)
1392 for (std::vector
< rtl::OUString
>::const_iterator
i(uris
.begin());
1393 i
!= uris
.end(); ++i
)
1396 Parser(*i
, alienContext
, &extra
);
1397 } catch (css::container::NoSuchElementException
&) {
1398 throw css::lang::IllegalArgumentException(
1399 *i
+ ": no such file", static_cast< cppu::OWeakObject
* >(this),
1401 } catch (css::registry::InvalidRegistryException
& e
) {
1402 throw css::lang::IllegalArgumentException(
1403 "InvalidRegistryException: " + e
.Message
,
1404 static_cast< cppu::OWeakObject
* >(this), 0);
1407 insertExtraData(extra
);
1410 void cppuhelper::ServiceManager::insertLegacyFactory(
1411 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
)
1413 assert(factoryInfo
.is());
1414 rtl::OUString
name(factoryInfo
->getImplementationName());
1415 css::uno::Reference
< css::lang::XSingleComponentFactory
> f1(
1416 factoryInfo
, css::uno::UNO_QUERY
);
1417 css::uno::Reference
< css::lang::XSingleServiceFactory
> f2
;
1419 f2
= css::uno::Reference
< css::lang::XSingleServiceFactory
>(
1420 factoryInfo
, css::uno::UNO_QUERY
);
1422 css::uno::Reference
< css::lang::XComponent
> comp(
1423 factoryInfo
, css::uno::UNO_QUERY
);
1424 boost::shared_ptr
< Data::Implementation
> impl(
1425 new Data::Implementation(name
, f1
, f2
, comp
));
1427 if (!name
.isEmpty()) {
1428 extra
.namedImplementations
.insert(
1429 Data::NamedImplementations::value_type(name
, impl
));
1431 extra
.dynamicImplementations
.insert(
1432 Data::DynamicImplementations::value_type(factoryInfo
, impl
));
1433 css::uno::Sequence
< rtl::OUString
> services(
1434 factoryInfo
->getSupportedServiceNames());
1435 for (sal_Int32 i
= 0; i
!= services
.getLength(); ++i
) {
1436 impl
->info
->services
.push_back(services
[i
]);
1437 extra
.services
[services
[i
]].push_back(impl
);
1439 if (insertExtraData(extra
) && comp
.is()) {
1440 comp
->addEventListener(this);
1444 bool cppuhelper::ServiceManager::insertExtraData(Data
const & extra
) {
1446 osl::MutexGuard
g(rBHelper
.rMutex
);
1450 for (Data::NamedImplementations::const_iterator
i(
1451 extra
.namedImplementations
.begin());
1452 i
!= extra
.namedImplementations
.end(); ++i
)
1454 if (data_
.namedImplementations
.find(i
->first
)
1455 != data_
.namedImplementations
.end())
1457 throw css::lang::IllegalArgumentException(
1458 "Insert duplicate implementation name " + i
->first
,
1459 static_cast< cppu::OWeakObject
* >(this), 0);
1462 for (Data::DynamicImplementations::const_iterator
i(
1463 extra
.dynamicImplementations
.begin());
1464 i
!= extra
.dynamicImplementations
.end(); ++i
)
1466 if (data_
.dynamicImplementations
.find(i
->first
)
1467 != data_
.dynamicImplementations
.end())
1469 throw css::lang::IllegalArgumentException(
1470 "Insert duplicate factory object",
1471 static_cast< cppu::OWeakObject
* >(this), 0);
1474 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1475 data_
.namedImplementations
.insert(
1476 extra
.namedImplementations
.begin(),
1477 extra
.namedImplementations
.end());
1478 data_
.dynamicImplementations
.insert(
1479 extra
.dynamicImplementations
.begin(),
1480 extra
.dynamicImplementations
.end());
1481 insertImplementationMap(&data_
.services
, extra
.services
);
1482 insertImplementationMap(&data_
.singletons
, extra
.singletons
);
1484 //TODO: Updating the component context singleton data should be part of the
1485 // atomic service manager update:
1486 if (!extra
.singletons
.empty()) {
1487 assert(context_
.is());
1488 css::uno::Reference
< css::container::XNameContainer
> cont(
1489 context_
, css::uno::UNO_QUERY_THROW
);
1490 for (Data::ImplementationMap::const_iterator
i(
1491 extra
.singletons
.begin());
1492 i
!= extra
.singletons
.end(); ++i
)
1494 rtl::OUString
name("/singletons/" + i
->first
);
1495 //TODO: Update should be atomic:
1497 cont
->removeByName(name
+ "/arguments");
1498 } catch (const css::container::NoSuchElementException
&) {}
1499 assert(!i
->second
.empty());
1500 assert(i
->second
[0].get() != 0);
1502 i
->second
.size() > 1, "cppuhelper",
1503 "Arbitrarily chosing " << i
->second
[0]->info
->name
1504 << " among multiple implementations for singleton "
1508 name
+ "/service", css::uno::Any(i
->second
[0]->info
->name
));
1509 } catch (css::container::ElementExistException
&) {
1510 cont
->replaceByName(
1511 name
+ "/service", css::uno::Any(i
->second
[0]->info
->name
));
1514 cont
->insertByName(name
, css::uno::Any());
1515 } catch (css::container::ElementExistException
&) {
1516 SAL_INFO("cppuhelper", "Overwriting singleton " << i
->first
);
1517 cont
->replaceByName(name
, css::uno::Any());
1524 void cppuhelper::ServiceManager::removeRdbFiles(
1525 std::vector
< rtl::OUString
> const & uris
)
1527 // The underlying data structures make this function somewhat inefficient,
1528 // but the assumption is that it is rarely called (and that if it is called,
1529 // it is called with a uris vector of size one):
1530 std::vector
< boost::shared_ptr
< Data::Implementation
> > clear
;
1532 osl::MutexGuard
g(rBHelper
.rMutex
);
1533 for (std::vector
< rtl::OUString
>::const_iterator
i(uris
.begin());
1534 i
!= uris
.end(); ++i
)
1536 for (Data::NamedImplementations::iterator
j(
1537 data_
.namedImplementations
.begin());
1538 j
!= data_
.namedImplementations
.end();)
1540 assert(j
->second
.get() != 0);
1541 if (j
->second
->info
->rdbFile
== *i
) {
1542 clear
.push_back(j
->second
);
1543 //TODO: The below leaves data_ in an inconsistent state upon
1545 removeFromImplementationMap(
1546 &data_
.services
, j
->second
->info
->services
, j
->second
);
1547 removeFromImplementationMap(
1548 &data_
.singletons
, j
->second
->info
->singletons
,
1550 data_
.namedImplementations
.erase(j
++);
1557 //TODO: Update the component context singleton data
1560 bool cppuhelper::ServiceManager::removeLegacyFactory(
1561 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
,
1562 bool removeListener
)
1564 assert(factoryInfo
.is());
1565 boost::shared_ptr
< Data::Implementation
> clear
;
1566 css::uno::Reference
< css::lang::XComponent
> comp
;
1568 osl::MutexGuard
g(rBHelper
.rMutex
);
1569 Data::DynamicImplementations::iterator
i(
1570 data_
.dynamicImplementations
.find(factoryInfo
));
1571 if (i
== data_
.dynamicImplementations
.end()) {
1572 return isDisposed();
1574 assert(i
->second
.get() != 0);
1576 if (removeListener
) {
1577 comp
= i
->second
->component
;
1579 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1580 removeFromImplementationMap(
1581 &data_
.services
, i
->second
->info
->services
, i
->second
);
1582 removeFromImplementationMap(
1583 &data_
.singletons
, i
->second
->info
->singletons
, i
->second
);
1584 if (!i
->second
->info
->name
.isEmpty()) {
1585 data_
.namedImplementations
.erase(i
->second
->info
->name
);
1587 data_
.dynamicImplementations
.erase(i
);
1590 removeEventListenerFromComponent(comp
);
1595 void cppuhelper::ServiceManager::removeImplementation(rtl::OUString name
) {
1596 // The underlying data structures make this function somewhat inefficient,
1597 // but the assumption is that it is rarely called:
1598 boost::shared_ptr
< Data::Implementation
> clear
;
1600 osl::MutexGuard
g(rBHelper
.rMutex
);
1604 Data::NamedImplementations::iterator
i(
1605 data_
.namedImplementations
.find(name
));
1606 if (i
== data_
.namedImplementations
.end()) {
1607 throw css::container::NoSuchElementException(
1608 "Remove non-inserted implementation " + name
,
1609 static_cast< cppu::OWeakObject
* >(this));
1611 assert(i
->second
.get() != 0);
1613 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1614 removeFromImplementationMap(
1615 &data_
.services
, i
->second
->info
->services
, i
->second
);
1616 removeFromImplementationMap(
1617 &data_
.singletons
, i
->second
->info
->singletons
, i
->second
);
1618 for (Data::DynamicImplementations::iterator
j(
1619 data_
.dynamicImplementations
.begin());
1620 j
!= data_
.dynamicImplementations
.end(); ++j
)
1622 if (j
->second
== i
->second
) {
1623 data_
.dynamicImplementations
.erase(j
);
1627 data_
.namedImplementations
.erase(i
);
1631 boost::shared_ptr
< cppuhelper::ServiceManager::Data::Implementation
>
1632 cppuhelper::ServiceManager::findServiceImplementation(
1633 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
1634 rtl::OUString
const & specifier
)
1636 boost::shared_ptr
< Data::Implementation
> impl
;
1639 osl::MutexGuard
g(rBHelper
.rMutex
);
1640 Data::ImplementationMap::const_iterator
i(
1641 data_
.services
.find(specifier
));
1642 if (i
== data_
.services
.end()) {
1643 Data::NamedImplementations::const_iterator
j(
1644 data_
.namedImplementations
.find(specifier
));
1645 if (j
== data_
.namedImplementations
.end()) {
1646 SAL_INFO("cppuhelper", "No implementation for " << specifier
);
1647 return boost::shared_ptr
< Data::Implementation
>();
1651 assert(!i
->second
.empty());
1653 i
->second
.size() > 1, "cppuhelper",
1654 "Arbitrarily chosing " << i
->second
[0]->info
->name
1655 << " among multiple implementations for " << i
->first
);
1656 impl
= i
->second
[0];
1658 assert(impl
.get() != 0);
1659 loaded
= impl
->loaded
;
1661 //TODO: There is a race here, as the relevant service factory can be removed
1662 // while the mutex is unlocked and loading can thus fail, as the entity from
1663 // which to load can disappear once the service factory is removed.
1665 css::uno::Reference
< css::lang::XSingleComponentFactory
> f1
;
1666 css::uno::Reference
< css::lang::XSingleServiceFactory
> f2
;
1667 loadImplementation(context
, impl
->info
, &f1
, &f2
);
1668 osl::MutexGuard
g(rBHelper
.rMutex
);
1669 if (!(isDisposed() || impl
->loaded
)) {
1670 impl
->loaded
= true;
1671 impl
->factory1
= f1
;
1672 impl
->factory2
= f2
;
1678 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */