1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License or as specified alternatively below. You may obtain a copy of
8 * the License at http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * Major Contributor(s):
16 * [ Copyright (C) 2012 Red Hat, Inc., Stephan Bergmann <sbergman@redhat.com>
17 * (initial developer) ]
19 * All Rights Reserved.
21 * For minor contributions see the git repository.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
25 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
26 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
27 * instead of those above.
30 #include "sal/config.h"
38 #include "boost/noncopyable.hpp"
39 #include "boost/shared_ptr.hpp"
40 #include "com/sun/star/beans/NamedValue.hpp"
41 #include "com/sun/star/beans/PropertyAttribute.hpp"
42 #include "com/sun/star/beans/XPropertySet.hpp"
43 #include "com/sun/star/container/ElementExistException.hpp"
44 #include "com/sun/star/container/XContentEnumerationAccess.hpp"
45 #include "com/sun/star/container/XEnumeration.hpp"
46 #include "com/sun/star/container/XHierarchicalNameAccess.hpp"
47 #include "com/sun/star/container/XNameContainer.hpp"
48 #include "com/sun/star/container/XSet.hpp"
49 #include "com/sun/star/lang/XInitialization.hpp"
50 #include "com/sun/star/lang/XServiceInfo.hpp"
51 #include "com/sun/star/lang/XSingleComponentFactory.hpp"
52 #include "com/sun/star/lang/XSingleServiceFactory.hpp"
53 #include "com/sun/star/loader/XImplementationLoader.hpp"
54 #include "com/sun/star/registry/InvalidRegistryException.hpp"
55 #include "com/sun/star/registry/XSimpleRegistry.hpp"
56 #include "com/sun/star/uno/DeploymentException.hpp"
57 #include "com/sun/star/uno/Reference.hxx"
58 #include "com/sun/star/uno/XComponentContext.hpp"
59 #include "cppuhelper/bootstrap.hxx"
60 #include "cppuhelper/compbase8.hxx"
61 #include "cppuhelper/component_context.hxx"
62 #include "cppuhelper/implbase1.hxx"
63 #include "cppuhelper/implbase3.hxx"
64 #include "cppuhelper/shlib.hxx"
65 #include "cppuhelper/supportsservice.hxx"
66 #include "osl/file.hxx"
67 #include "registry/registry.hxx"
68 #include "rtl/bootstrap.hxx"
69 #include "rtl/ref.hxx"
70 #include "rtl/uri.hxx"
71 #include "rtl/ustring.hxx"
72 #include "xmlreader/xmlreader.hxx"
74 #include "macro_expander.hxx"
76 #include "servicefactory_detail.hxx"
80 namespace css
= com::sun::star
;
82 bool nextDirectoryItem(osl::Directory
& directory
, rtl::OUString
* url
) {
86 switch (directory
.getNextItem(i
, SAL_MAX_UINT32
)) {
87 case osl::FileBase::E_None
:
89 case osl::FileBase::E_NOENT
:
92 throw css::uno::DeploymentException(
93 "Cannot iterate directory",
94 css::uno::Reference
< css::uno::XInterface
>());
97 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
|
98 osl_FileStatus_Mask_FileURL
);
99 if (i
.getFileStatus(stat
) != osl::FileBase::E_None
) {
100 throw css::uno::DeploymentException(
101 "Cannot stat in directory",
102 css::uno::Reference
< css::uno::XInterface
>());
104 if (stat
.getFileType() != osl::FileStatus::Directory
) { //TODO: symlinks
105 // Ignore backup files:
106 rtl::OUString
name(stat
.getFileName());
107 if (!(name
.match(".") || name
.endsWith("~"))) {
108 *url
= stat
.getFileURL();
115 void decodeRdbUri(rtl::OUString
* uri
, bool * optional
, bool * directory
) {
116 assert(uri
!= 0 && optional
!= 0 && directory
!= 0);
117 *optional
= (*uri
)[0] == '?';
121 *directory
= uri
->getLength() >= 3 && (*uri
)[0] == '<'
122 && (*uri
)[uri
->getLength() - 2] == '>'
123 && (*uri
)[uri
->getLength() - 1] == '*';
125 *uri
= uri
->copy(1, uri
->getLength() - 3);
129 struct ImplementationInfo
: private boost::noncopyable
{
131 rtl::OUString
const & theName
, rtl::OUString
const & theLoader
,
132 rtl::OUString
const & theUri
, rtl::OUString
const & thePrefix
,
133 css::uno::Reference
< css::uno::XComponentContext
> const &
135 rtl::OUString
const & theRdbFile
):
136 name(theName
), loader(theLoader
), uri(theUri
), prefix(thePrefix
),
137 alienContext(theAlienContext
), rdbFile(theRdbFile
)
140 explicit ImplementationInfo(rtl::OUString
const & theName
): name(theName
) {}
142 rtl::OUString
const name
;
143 rtl::OUString
const loader
;
144 rtl::OUString
const uri
;
145 rtl::OUString
const prefix
;
146 css::uno::Reference
< css::uno::XComponentContext
> const alienContext
;
147 rtl::OUString
const rdbFile
;
148 std::vector
< rtl::OUString
> services
;
149 std::vector
< rtl::OUString
> singletons
;
152 struct Implementation
: private boost::noncopyable
{
154 rtl::OUString
const & name
, rtl::OUString
const & loader
,
155 rtl::OUString
const & uri
, rtl::OUString
const & prefix
,
156 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
,
157 rtl::OUString
const & rdbFile
):
159 new ImplementationInfo(
160 name
, loader
, uri
, prefix
, alienContext
, rdbFile
)),
165 rtl::OUString
const & name
,
166 css::uno::Reference
< css::lang::XSingleComponentFactory
> const &
168 css::uno::Reference
< css::lang::XSingleServiceFactory
> const &
170 css::uno::Reference
< css::lang::XComponent
> const & theComponent
):
171 info(new ImplementationInfo(name
)), factory1(theFactory1
),
172 factory2(theFactory2
), component(theComponent
), loaded(true)
175 boost::shared_ptr
< ImplementationInfo
> info
;
176 css::uno::Reference
< css::lang::XSingleComponentFactory
> factory1
;
177 css::uno::Reference
< css::lang::XSingleServiceFactory
> factory2
;
178 css::uno::Reference
< css::lang::XComponent
> component
;
182 typedef std::map
< rtl::OUString
, boost::shared_ptr
< Implementation
> >
183 NamedImplementations
;
187 css::uno::Reference
< css::lang::XServiceInfo
>,
188 boost::shared_ptr
< Implementation
> >
189 DynamicImplementations
;
193 rtl::OUString
, std::vector
< boost::shared_ptr
< Implementation
> > >
196 void insertImplementationMap(
197 ImplementationMap
* destination
, ImplementationMap
const & source
)
199 assert(destination
!= 0);
200 for (ImplementationMap::const_iterator
i(source
.begin()); i
!= source
.end();
203 std::vector
< boost::shared_ptr
< Implementation
> > & impls
204 = (*destination
)[i
->first
];
205 impls
.insert(impls
.end(), i
->second
.begin(), i
->second
.end());
209 void removeFromImplementationMap(
210 ImplementationMap
* map
, std::vector
< rtl::OUString
> const & elements
,
211 boost::shared_ptr
< Implementation
> const & implementation
)
213 // The underlying data structures make this function somewhat inefficient,
214 // but the assumption is that it is rarely called:
216 for (std::vector
< rtl::OUString
>::const_iterator
i(elements
.begin());
217 i
!= elements
.end(); ++i
)
219 ImplementationMap::iterator
j(map
->find(*i
));
220 assert(j
!= map
->end());
221 std::vector
< boost::shared_ptr
< Implementation
> >::iterator
k(
222 std::find(j
->second
.begin(), j
->second
.end(), implementation
));
223 assert(k
!= j
->second
.end());
225 if (j
->second
.empty()) {
231 struct Data
: private boost::noncopyable
{
232 NamedImplementations namedImplementations
;
233 DynamicImplementations dynamicImplementations
;
234 ImplementationMap services
;
235 ImplementationMap singletons
;
238 // This is largely a copy from stoc/source/simpleregistry/textualservices.cxx
239 // (which it obsoletes); cppuhelper's published interface concept makes it
240 // difficult to make both places use a shared Parser implementation, so I
241 // created a copy for now (until the whole stoc/source/simpleregistry stuff can
242 // be removed in an incompatible LibreOffice version). For simplicity, this
243 // code keeps throwing css::registry::InvalidRegistryException for invalid XML
244 // rdbs (even though that does not fit the exception's name):
245 class Parser
: private boost::noncopyable
{
248 rtl::OUString
const & uri
,
249 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
,
253 void handleComponent();
255 void handleImplementation();
257 void handleService();
259 void handleSingleton();
261 rtl::OUString
getNameAttribute();
263 xmlreader::XmlReader reader_
;
264 css::uno::Reference
< css::uno::XComponentContext
> alienContext_
;
266 rtl::OUString attrLoader_
;
267 rtl::OUString attrUri_
;
268 rtl::OUString attrPrefix_
;
269 rtl::OUString attrImplementation_
;
270 boost::shared_ptr
< Implementation
> implementation_
;
274 rtl::OUString
const & uri
,
275 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
,
277 reader_(uri
), alienContext_(alienContext
), data_(data
)
280 int ucNsId
= reader_
.registerNamespaceIri(
282 RTL_CONSTASCII_STRINGPARAM(
283 "http://openoffice.org/2010/uno-components")));
285 STATE_BEGIN
, STATE_END
, STATE_COMPONENTS
, STATE_COMPONENT_INITIAL
,
286 STATE_COMPONENT
, STATE_IMPLEMENTATION
, STATE_SERVICE
, STATE_SINGLETON
};
287 for (State state
= STATE_BEGIN
;;) {
288 xmlreader::Span name
;
290 xmlreader::XmlReader::Result res
= reader_
.nextItem(
291 xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
294 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
295 && name
.equals(RTL_CONSTASCII_STRINGPARAM("components")))
297 state
= STATE_COMPONENTS
;
300 throw css::registry::InvalidRegistryException(
301 reader_
.getUrl() + ": unexpected item in outer level",
302 css::uno::Reference
< css::uno::XInterface
>());
304 if (res
== xmlreader::XmlReader::RESULT_DONE
) {
307 throw css::registry::InvalidRegistryException(
308 reader_
.getUrl() + ": unexpected item in outer level",
309 css::uno::Reference
< css::uno::XInterface
>());
310 case STATE_COMPONENTS
:
311 if (res
== xmlreader::XmlReader::RESULT_END
) {
315 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
316 && name
.equals(RTL_CONSTASCII_STRINGPARAM("component")))
319 state
= STATE_COMPONENT_INITIAL
;
322 throw css::registry::InvalidRegistryException(
323 reader_
.getUrl() + ": unexpected item in <components>",
324 css::uno::Reference
< css::uno::XInterface
>());
325 case STATE_COMPONENT
:
326 if (res
== xmlreader::XmlReader::RESULT_END
) {
327 state
= STATE_COMPONENTS
;
331 case STATE_COMPONENT_INITIAL
:
332 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
333 && name
.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
335 handleImplementation();
336 state
= STATE_IMPLEMENTATION
;
339 throw css::registry::InvalidRegistryException(
340 reader_
.getUrl() + ": unexpected item in <component>",
341 css::uno::Reference
< css::uno::XInterface
>());
342 case STATE_IMPLEMENTATION
:
343 if (res
== xmlreader::XmlReader::RESULT_END
) {
344 state
= STATE_COMPONENT
;
347 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
348 && name
.equals(RTL_CONSTASCII_STRINGPARAM("service")))
351 state
= STATE_SERVICE
;
354 if (res
== xmlreader::XmlReader::RESULT_BEGIN
&& nsId
== ucNsId
355 && name
.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
358 state
= STATE_SINGLETON
;
361 throw css::registry::InvalidRegistryException(
362 reader_
.getUrl() + ": unexpected item in <implementation>",
363 css::uno::Reference
< css::uno::XInterface
>());
365 if (res
== xmlreader::XmlReader::RESULT_END
) {
366 state
= STATE_IMPLEMENTATION
;
369 throw css::registry::InvalidRegistryException(
370 reader_
.getUrl() + ": unexpected item in <service>",
371 css::uno::Reference
< css::uno::XInterface
>());
372 case STATE_SINGLETON
:
373 if (res
== xmlreader::XmlReader::RESULT_END
) {
374 state
= STATE_IMPLEMENTATION
;
377 throw css::registry::InvalidRegistryException(
378 reader_
.getUrl() + ": unexpected item in <service>",
379 css::uno::Reference
< css::uno::XInterface
>());
384 void Parser::handleComponent() {
385 attrLoader_
= rtl::OUString();
386 attrUri_
= rtl::OUString();
387 attrPrefix_
= rtl::OUString();
388 xmlreader::Span name
;
390 while (reader_
.nextAttribute(&nsId
, &name
)) {
391 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
392 && name
.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
394 if (!attrLoader_
.isEmpty()) {
395 throw css::registry::InvalidRegistryException(
397 + ": <component> has multiple \"loader\" attributes"),
398 css::uno::Reference
< css::uno::XInterface
>());
400 attrLoader_
= reader_
.getAttributeValue(false).convertFromUtf8();
401 if (attrLoader_
.isEmpty()) {
402 throw css::registry::InvalidRegistryException(
404 + ": <component> has empty \"loader\" attribute"),
405 css::uno::Reference
< css::uno::XInterface
>());
407 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
408 && name
.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
410 if (!attrUri_
.isEmpty()) {
411 throw css::registry::InvalidRegistryException(
413 + ": <component> has multiple \"uri\" attributes"),
414 css::uno::Reference
< css::uno::XInterface
>());
416 attrUri_
= reader_
.getAttributeValue(false).convertFromUtf8();
417 if (attrUri_
.isEmpty()) {
418 throw css::registry::InvalidRegistryException(
420 + ": <component> has empty \"uri\" attribute"),
421 css::uno::Reference
< css::uno::XInterface
>());
423 } else if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
424 && name
.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
426 if (!attrPrefix_
.isEmpty()) {
427 throw css::registry::InvalidRegistryException(
429 ": <component> has multiple \"prefix\" attributes"),
430 css::uno::Reference
< css::uno::XInterface
>());
432 attrPrefix_
= reader_
.getAttributeValue(false).convertFromUtf8();
433 if (attrPrefix_
.isEmpty()) {
434 throw css::registry::InvalidRegistryException(
436 ": <component> has empty \"prefix\" attribute"),
437 css::uno::Reference
< css::uno::XInterface
>());
440 throw css::registry::InvalidRegistryException(
441 (reader_
.getUrl() + ": unexpected attribute \""
442 + name
.convertFromUtf8() + "\" in <component>"),
443 css::uno::Reference
< css::uno::XInterface
>());
446 if (attrLoader_
.isEmpty()) {
447 throw css::registry::InvalidRegistryException(
448 reader_
.getUrl() + ": <component> is missing \"loader\" attribute",
449 css::uno::Reference
< css::uno::XInterface
>());
451 if (attrUri_
.isEmpty()) {
452 throw css::registry::InvalidRegistryException(
453 reader_
.getUrl() + ": <component> is missing \"uri\" attribute",
454 css::uno::Reference
< css::uno::XInterface
>());
456 #ifndef DISABLE_DYNLOADING
458 attrUri_
= rtl::Uri::convertRelToAbs(reader_
.getUrl(), attrUri_
);
459 } catch (const rtl::MalformedUriException
& e
) {
460 throw css::registry::InvalidRegistryException(
461 reader_
.getUrl() + ": bad \"uri\" attribute: " + e
.getMessage(),
462 css::uno::Reference
< css::uno::XInterface
>());
467 void Parser::handleImplementation() {
468 attrImplementation_
= getNameAttribute();
469 implementation_
.reset(
471 attrImplementation_
, attrLoader_
, attrUri_
, attrPrefix_
,
472 alienContext_
, reader_
.getUrl()));
473 if (!data_
->namedImplementations
.insert(
474 NamedImplementations::value_type(
475 attrImplementation_
, implementation_
)).
478 throw css::registry::InvalidRegistryException(
479 (reader_
.getUrl() + ": duplicate <implementation name=\""
480 + attrImplementation_
+ "\">"),
481 css::uno::Reference
< css::uno::XInterface
>());
485 void Parser::handleService() {
486 rtl::OUString
name(getNameAttribute());
487 implementation_
->info
->services
.push_back(name
);
488 data_
->services
[name
].push_back(implementation_
);
491 void Parser::handleSingleton() {
492 rtl::OUString
name(getNameAttribute());
493 implementation_
->info
->singletons
.push_back(name
);
494 data_
->singletons
[name
].push_back(implementation_
);
497 rtl::OUString
Parser::getNameAttribute() {
498 rtl::OUString attrName
;
499 xmlreader::Span name
;
501 while (reader_
.nextAttribute(&nsId
, &name
)) {
502 if (nsId
== xmlreader::XmlReader::NAMESPACE_NONE
503 && name
.equals(RTL_CONSTASCII_STRINGPARAM("name")))
505 if (!attrName
.isEmpty()) {
506 throw css::registry::InvalidRegistryException(
508 + ": element has multiple \"name\" attributes"),
509 css::uno::Reference
< css::uno::XInterface
>());
511 attrName
= reader_
.getAttributeValue(false).convertFromUtf8();
512 if (attrName
.isEmpty()) {
513 throw css::registry::InvalidRegistryException(
514 reader_
.getUrl() + ": element has empty \"name\" attribute",
515 css::uno::Reference
< css::uno::XInterface
>());
518 throw css::registry::InvalidRegistryException(
519 reader_
.getUrl() + ": expected element attribute \"name\"",
520 css::uno::Reference
< css::uno::XInterface
>());
523 if (attrName
.isEmpty()) {
524 throw css::registry::InvalidRegistryException(
525 reader_
.getUrl() + ": element is missing \"name\" attribute",
526 css::uno::Reference
< css::uno::XInterface
>());
531 class ContentEnumeration
:
532 public cppu::WeakImplHelper1
< css::container::XEnumeration
>,
533 private boost::noncopyable
536 explicit ContentEnumeration(std::vector
< css::uno::Any
> const & factories
):
537 factories_(factories
), iterator_(factories_
.begin()) {}
540 virtual ~ContentEnumeration() {}
542 virtual sal_Bool SAL_CALL
hasMoreElements()
543 throw (css::uno::RuntimeException
);
545 virtual css::uno::Any SAL_CALL
nextElement()
547 css::container::NoSuchElementException
,
548 css::lang::WrappedTargetException
, css::uno::RuntimeException
);
551 std::vector
< css::uno::Any
> factories_
;
552 std::vector
< css::uno::Any
>::const_iterator iterator_
;
555 sal_Bool
ContentEnumeration::hasMoreElements()
556 throw (css::uno::RuntimeException
)
558 osl::MutexGuard
g(mutex_
);
559 return iterator_
!= factories_
.end();
562 css::uno::Any
ContentEnumeration::nextElement()
564 css::container::NoSuchElementException
,
565 css::lang::WrappedTargetException
, css::uno::RuntimeException
)
567 osl::MutexGuard
g(mutex_
);
568 if (iterator_
== factories_
.end()) {
569 throw css::container::NoSuchElementException(
570 "Bootstrap service manager service enumerator has no more elements",
571 static_cast< cppu::OWeakObject
* >(this));
576 css::beans::Property
getDefaultContextProperty() {
577 return css::beans::Property(
578 "DefaultContext", -1,
579 cppu::UnoType
< css::uno::XComponentContext
>::get(),
580 css::beans::PropertyAttribute::READONLY
);
583 typedef cppu::WeakComponentImplHelper8
<
584 css::lang::XServiceInfo
, css::lang::XMultiServiceFactory
,
585 css::lang::XMultiComponentFactory
, css::container::XSet
,
586 css::container::XContentEnumerationAccess
, css::beans::XPropertySet
,
587 css::beans::XPropertySetInfo
, css::lang::XEventListener
>
590 class ServiceManager
:
591 private osl::Mutex
, public ServiceManagerBase
, private boost::noncopyable
594 explicit ServiceManager(rtl::OUString
const & rdbUris
):
595 ServiceManagerBase(*static_cast< osl::Mutex
* >(this))
596 { readRdbs(rdbUris
); }
598 using ServiceManagerBase::acquire
;
599 using ServiceManagerBase::release
;
602 css::uno::Reference
< css::uno::XComponentContext
> const & context
)
604 assert(context
.is());
605 assert(!context_
.is());
609 css::uno::Reference
< css::uno::XComponentContext
> getContext() const {
610 assert(context_
.is());
614 Data
const & getData() const { return data_
; }
616 void loadImplementation(
617 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
618 boost::shared_ptr
< ImplementationInfo
> const & info
,
619 css::uno::Reference
< css::lang::XSingleComponentFactory
> * factory1
,
620 css::uno::Reference
< css::lang::XSingleServiceFactory
> * factory2
);
622 virtual rtl::OUString SAL_CALL
getImplementationName()
623 throw (css::uno::RuntimeException
);
625 virtual sal_Bool SAL_CALL
supportsService(rtl::OUString
const & ServiceName
)
626 throw (css::uno::RuntimeException
);
628 virtual css::uno::Sequence
< rtl::OUString
> SAL_CALL
629 getSupportedServiceNames() throw (css::uno::RuntimeException
);
631 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
createInstance(
632 rtl::OUString
const & aServiceSpecifier
)
633 throw (css::uno::Exception
, css::uno::RuntimeException
);
635 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
636 createInstanceWithArguments(
637 rtl::OUString
const & ServiceSpecifier
,
638 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
639 throw (css::uno::Exception
, css::uno::RuntimeException
);
641 virtual css::uno::Sequence
< rtl::OUString
> SAL_CALL
642 getAvailableServiceNames() throw (css::uno::RuntimeException
);
644 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
645 createInstanceWithContext(
646 rtl::OUString
const & aServiceSpecifier
,
647 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
648 throw (css::uno::Exception
, css::uno::RuntimeException
);
650 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
651 createInstanceWithArgumentsAndContext(
652 rtl::OUString
const & ServiceSpecifier
,
653 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
654 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
655 throw (css::uno::Exception
, css::uno::RuntimeException
);
657 virtual css::uno::Type SAL_CALL
getElementType()
658 throw (css::uno::RuntimeException
);
660 virtual sal_Bool SAL_CALL
hasElements() throw (css::uno::RuntimeException
);
662 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
663 createEnumeration() throw (css::uno::RuntimeException
);
665 virtual sal_Bool SAL_CALL
has(css::uno::Any
const & aElement
)
666 throw (css::uno::RuntimeException
);
668 virtual void SAL_CALL
insert(css::uno::Any
const & aElement
)
670 css::lang::IllegalArgumentException
,
671 css::container::ElementExistException
, css::uno::RuntimeException
);
673 virtual void SAL_CALL
remove(css::uno::Any
const & aElement
)
675 css::lang::IllegalArgumentException
,
676 css::container::NoSuchElementException
, css::uno::RuntimeException
);
678 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
679 createContentEnumeration(rtl::OUString
const & aServiceName
)
680 throw (css::uno::RuntimeException
);
682 virtual css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
683 getPropertySetInfo() throw (css::uno::RuntimeException
);
685 virtual void SAL_CALL
setPropertyValue(
686 rtl::OUString
const & aPropertyName
, css::uno::Any
const & aValue
)
688 css::beans::UnknownPropertyException
,
689 css::beans::PropertyVetoException
,
690 css::lang::IllegalArgumentException
,
691 css::lang::WrappedTargetException
, css::uno::RuntimeException
);
693 virtual css::uno::Any SAL_CALL
getPropertyValue(
694 rtl::OUString
const & PropertyName
)
696 css::beans::UnknownPropertyException
,
697 css::lang::WrappedTargetException
, css::uno::RuntimeException
);
699 virtual void SAL_CALL
addPropertyChangeListener(
700 rtl::OUString
const & aPropertyName
,
701 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
704 css::beans::UnknownPropertyException
,
705 css::lang::WrappedTargetException
, css::uno::RuntimeException
);
707 virtual void SAL_CALL
removePropertyChangeListener(
708 rtl::OUString
const & aPropertyName
,
709 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
712 css::beans::UnknownPropertyException
,
713 css::lang::WrappedTargetException
, css::uno::RuntimeException
);
715 virtual void SAL_CALL
addVetoableChangeListener(
716 rtl::OUString
const & PropertyName
,
717 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
720 css::beans::UnknownPropertyException
,
721 css::lang::WrappedTargetException
, css::uno::RuntimeException
);
723 virtual void SAL_CALL
removeVetoableChangeListener(
724 rtl::OUString
const & PropertyName
,
725 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
728 css::beans::UnknownPropertyException
,
729 css::lang::WrappedTargetException
, css::uno::RuntimeException
);
731 virtual css::uno::Sequence
< css::beans::Property
> SAL_CALL
getProperties()
732 throw (css::uno::RuntimeException
);
734 virtual css::beans::Property SAL_CALL
getPropertyByName(
735 rtl::OUString
const & aName
)
737 css::beans::UnknownPropertyException
, css::uno::RuntimeException
);
739 virtual sal_Bool SAL_CALL
hasPropertyByName(rtl::OUString
const & Name
)
740 throw (css::uno::RuntimeException
);
742 virtual void SAL_CALL
disposing(css::lang::EventObject
const & Source
)
743 throw (css::uno::RuntimeException
);
746 virtual ~ServiceManager() {}
748 virtual void SAL_CALL
disposing();
750 // needs to be called with rBHelper.rMutex locked:
751 bool isDisposed() { return rBHelper
.bDisposed
|| rBHelper
.bInDispose
; }
753 void removeEventListenerFromComponent(
754 css::uno::Reference
< css::lang::XComponent
> const & component
);
756 void readRdbs(rtl::OUString
const & uris
);
758 void readRdbDirectory(rtl::OUString
const & uri
, bool optional
);
760 void readRdbFile(rtl::OUString
const & uri
, bool optional
);
762 bool readLegacyRdbFile(rtl::OUString
const & uri
);
764 rtl::OUString
readLegacyRdbString(
765 rtl::OUString
const & uri
, RegistryKey
& key
,
766 rtl::OUString
const & path
);
768 void readLegacyRdbStrings(
769 rtl::OUString
const & uri
, RegistryKey
& key
,
770 rtl::OUString
const & path
, std::vector
< rtl::OUString
> * strings
);
773 std::vector
< rtl::OUString
> const & uris
,
774 css::uno::Reference
< css::uno::XComponentContext
> const &
777 void insertLegacyFactory(
778 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
);
780 bool insertExtraData(Data
const & extra
);
782 void removeRdbFiles(std::vector
< rtl::OUString
> const & uris
);
784 bool removeLegacyFactory(
785 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
,
786 bool removeListener
);
788 void removeImplementation(rtl::OUString name
);
790 boost::shared_ptr
< Implementation
> findServiceImplementation(
791 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
792 rtl::OUString
const & specifier
);
794 css::uno::Reference
< css::uno::XComponentContext
> context_
;
798 class FactoryWrapper
:
799 public cppu::WeakImplHelper3
<
800 css::lang::XSingleComponentFactory
, css::lang::XSingleServiceFactory
,
801 css::lang::XServiceInfo
>,
802 private boost::noncopyable
806 rtl::Reference
< ServiceManager
> const & manager
,
807 boost::shared_ptr
< ImplementationInfo
> const & info
):
808 manager_(manager
), info_(info
), loaded_(false)
809 { assert(manager
.is() && info
.get() != 0); }
812 virtual ~FactoryWrapper() {}
814 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
815 createInstanceWithContext(
816 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
817 throw (css::uno::Exception
, css::uno::RuntimeException
);
819 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
820 createInstanceWithArgumentsAndContext(
821 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
822 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
823 throw (css::uno::Exception
, css::uno::RuntimeException
);
825 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
826 createInstance() throw (css::uno::Exception
, css::uno::RuntimeException
);
828 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
829 createInstanceWithArguments(
830 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
831 throw (css::uno::Exception
, css::uno::RuntimeException
);
833 virtual rtl::OUString SAL_CALL
getImplementationName()
834 throw (css::uno::RuntimeException
);
836 virtual sal_Bool SAL_CALL
supportsService(rtl::OUString
const & ServiceName
)
837 throw (css::uno::RuntimeException
);
839 virtual css::uno::Sequence
< rtl::OUString
> SAL_CALL
840 getSupportedServiceNames() throw (css::uno::RuntimeException
);
842 void loadImplementation(
843 css::uno::Reference
< css::uno::XComponentContext
> const & context
);
845 rtl::Reference
< ServiceManager
> manager_
;
846 boost::shared_ptr
< ImplementationInfo
> info_
;
850 css::uno::Reference
< css::lang::XSingleComponentFactory
> factory1_
;
851 css::uno::Reference
< css::lang::XSingleServiceFactory
> factory2_
;
854 void ServiceManager::loadImplementation(
855 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
856 boost::shared_ptr
< ImplementationInfo
> const & info
,
857 css::uno::Reference
< css::lang::XSingleComponentFactory
> * factory1
,
858 css::uno::Reference
< css::lang::XSingleServiceFactory
> * factory2
)
861 info
.get() != 0 && factory1
!= 0 && !factory1
->is() && factory2
!= 0
865 uri
= cppu::bootstrap_expandUri(info
->uri
);
866 } catch (css::lang::IllegalArgumentException
& e
) {
867 throw css::uno::DeploymentException(
868 "Cannot expand URI" + info
->uri
+ ": " + e
.Message
,
869 static_cast< cppu::OWeakObject
* >(this));
871 css::uno::Reference
< css::uno::XInterface
> f0
;
872 // Shortcut loading via SharedLibrary loader, to pass in prefix argument
873 // (which the loader's activate implementation would normally obtain through
874 // the legacy xKey argument):
875 if (!info
->alienContext
.is()
876 && info
->loader
== "com.sun.star.loader.SharedLibrary")
878 rtl::OUString
prefix(info
->prefix
);
879 if (!prefix
.isEmpty()) {
882 f0
= cppu::loadSharedLibComponentFactory(
883 uri
, rtl::OUString(), info
->name
, this,
884 css::uno::Reference
< css::registry::XRegistryKey
>(), prefix
);
887 !info
->prefix
.isEmpty(), "cppuhelper",
888 "Loader " << info
->loader
<< " and non-empty prefix "
890 css::uno::Reference
< css::uno::XComponentContext
> ctxt
;
891 css::uno::Reference
< css::lang::XMultiComponentFactory
> smgr
;
892 if (info
->alienContext
.is()) {
893 ctxt
= info
->alienContext
;
894 smgr
= css::uno::Reference
< css::lang::XMultiComponentFactory
>(
895 ctxt
->getServiceManager(), css::uno::UNO_SET_THROW
);
897 assert(context
.is());
901 css::uno::Reference
< css::loader::XImplementationLoader
> loader(
902 smgr
->createInstanceWithContext(info
->loader
, ctxt
),
903 css::uno::UNO_QUERY_THROW
);
904 f0
= loader
->activate(
905 info
->name
, rtl::OUString(), uri
,
906 css::uno::Reference
< css::registry::XRegistryKey
>());
908 factory1
->set(f0
, css::uno::UNO_QUERY
);
909 if (!factory1
->is()) {
910 factory2
->set(f0
, css::uno::UNO_QUERY
);
914 rtl::OUString
ServiceManager::getImplementationName()
915 throw (css::uno::RuntimeException
)
917 return rtl::OUString(
918 "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager");
921 sal_Bool
ServiceManager::supportsService(rtl::OUString
const & ServiceName
)
922 throw (css::uno::RuntimeException
)
924 return cppu::supportsService(this, ServiceName
);
927 css::uno::Sequence
< rtl::OUString
> ServiceManager::getSupportedServiceNames()
928 throw (css::uno::RuntimeException
)
930 css::uno::Sequence
< rtl::OUString
> names(2);
931 names
[0] = "com.sun.star.lang.MultiServiceFactory";
932 names
[1] = "com.sun.star.lang.ServiceManager";
936 css::uno::Reference
< css::uno::XInterface
> ServiceManager::createInstance(
937 rtl::OUString
const & aServiceSpecifier
)
938 throw (css::uno::Exception
, css::uno::RuntimeException
)
940 assert(context_
.is());
941 return createInstanceWithContext(aServiceSpecifier
, context_
);
944 css::uno::Reference
< css::uno::XInterface
>
945 ServiceManager::createInstanceWithArguments(
946 rtl::OUString
const & ServiceSpecifier
,
947 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
948 throw (css::uno::Exception
, css::uno::RuntimeException
)
950 assert(context_
.is());
951 return createInstanceWithArgumentsAndContext(
952 ServiceSpecifier
, Arguments
, context_
);
955 css::uno::Sequence
< rtl::OUString
> ServiceManager::getAvailableServiceNames()
956 throw (css::uno::RuntimeException
)
958 osl::MutexGuard
g(rBHelper
.rMutex
);
960 return css::uno::Sequence
< rtl::OUString
>();
962 ImplementationMap::size_type n
= data_
.services
.size();
963 if (n
> static_cast< sal_uInt32
>(SAL_MAX_INT32
)) {
964 throw css::uno::RuntimeException(
965 "getAvailableServiceNames: too many services",
966 static_cast< cppu::OWeakObject
* >(this));
968 css::uno::Sequence
< rtl::OUString
> names(static_cast< sal_Int32
>(n
));
970 for (ImplementationMap::const_iterator
j(data_
.services
.begin());
971 j
!= data_
.services
.end(); ++j
)
973 names
[i
++] = j
->first
;
975 assert(i
== names
.getLength());
979 css::uno::Reference
< css::uno::XInterface
>
980 ServiceManager::createInstanceWithContext(
981 rtl::OUString
const & aServiceSpecifier
,
982 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
983 throw (css::uno::Exception
, css::uno::RuntimeException
)
985 boost::shared_ptr
< Implementation
> impl(
986 findServiceImplementation(Context
, aServiceSpecifier
));
987 if (impl
.get() == 0) {
988 return css::uno::Reference
< css::uno::XInterface
>();
990 if (impl
->factory1
.is()) {
991 return impl
->factory1
->createInstanceWithContext(Context
);
993 if (impl
->factory2
.is()) {
994 return impl
->factory2
->createInstance();
996 throw css::uno::DeploymentException(
997 "Implementation " + impl
->info
->name
+ " does not provide a factory",
998 static_cast< cppu::OWeakObject
* >(this));
1001 css::uno::Reference
< css::uno::XInterface
>
1002 ServiceManager::createInstanceWithArgumentsAndContext(
1003 rtl::OUString
const & ServiceSpecifier
,
1004 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
1005 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
1006 throw (css::uno::Exception
, css::uno::RuntimeException
)
1008 boost::shared_ptr
< Implementation
> impl(
1009 findServiceImplementation(Context
, ServiceSpecifier
));
1010 if (impl
.get() == 0) {
1011 return css::uno::Reference
< css::uno::XInterface
>();
1013 if (impl
->factory1
.is()) {
1014 return impl
->factory1
->createInstanceWithArgumentsAndContext(
1015 Arguments
, Context
);
1017 if (impl
->factory2
.is()) {
1018 return impl
->factory2
->createInstanceWithArguments(Arguments
);
1020 throw css::uno::DeploymentException(
1021 "Implementation " + impl
->info
->name
+ " does not provide a factory",
1022 static_cast< cppu::OWeakObject
* >(this));
1025 css::uno::Type
ServiceManager::getElementType()
1026 throw (css::uno::RuntimeException
)
1028 return css::uno::Type();
1031 sal_Bool
ServiceManager::hasElements() throw (css::uno::RuntimeException
) {
1032 osl::MutexGuard
g(rBHelper
.rMutex
);
1034 !(data_
.namedImplementations
.empty()
1035 && data_
.dynamicImplementations
.empty());
1038 css::uno::Reference
< css::container::XEnumeration
>
1039 ServiceManager::createEnumeration() throw (css::uno::RuntimeException
) {
1040 throw css::uno::RuntimeException(
1041 "ServiceManager createEnumeration: method not supported",
1042 static_cast< cppu::OWeakObject
* >(this));
1045 sal_Bool
ServiceManager::has(css::uno::Any
const &)
1046 throw (css::uno::RuntimeException
)
1048 throw css::uno::RuntimeException(
1049 "ServiceManager has: method not supported",
1050 static_cast< cppu::OWeakObject
* >(this));
1053 void ServiceManager::insert(css::uno::Any
const & aElement
)
1055 css::lang::IllegalArgumentException
,
1056 css::container::ElementExistException
, css::uno::RuntimeException
)
1058 css::uno::Sequence
< css::beans::NamedValue
> args
;
1059 if (aElement
>>= args
) {
1060 std::vector
< rtl::OUString
> uris
;
1061 css::uno::Reference
< css::uno::XComponentContext
> alienContext
;
1062 for (sal_Int32 i
= 0; i
< args
.getLength(); ++i
) {
1063 if (args
[i
].Name
== "uri") {
1065 if (!(args
[i
].Value
>>= uri
)) {
1066 throw css::lang::IllegalArgumentException(
1068 static_cast< cppu::OWeakObject
* >(this), 0);
1070 uris
.push_back(uri
);
1071 } else if (args
[i
].Name
== "component-context") {
1072 if (alienContext
.is()) {
1073 throw css::lang::IllegalArgumentException(
1074 "Multiple component-context arguments",
1075 static_cast< cppu::OWeakObject
* >(this), 0);
1077 if (!(args
[i
].Value
>>= alienContext
) || !alienContext
.is()) {
1078 throw css::lang::IllegalArgumentException(
1079 "Bad component-context argument",
1080 static_cast< cppu::OWeakObject
* >(this), 0);
1083 throw css::lang::IllegalArgumentException(
1084 "Bad argument " + args
[i
].Name
,
1085 static_cast< cppu::OWeakObject
* >(this), 0);
1088 insertRdbFiles(uris
, alienContext
);
1091 css::uno::Reference
< css::lang::XServiceInfo
> info
;
1092 if ((aElement
>>= info
) && info
.is()) {
1093 insertLegacyFactory(info
);
1096 // At least revisions up to 1.7 of LanguageTool.oxt (incl. the bundled 1.4.0 in
1097 // module languagetool) contain an (actively registered) factory that does not
1098 // implement XServiceInfo (see <http://sourceforge.net/tracker/?
1099 // func=detail&aid=3526635&group_id=110216&atid=655717> "SingletonFactory should
1100 // implement XServiceInfo"); the old OServiceManager::insert
1101 // (stoc/source/servicemanager/servicemanager.cxx) silently did not add such
1102 // broken factories to its m_ImplementationNameMap, so ignore them here for
1103 // backwards compatibility of live-insertion of extensions, too (can go again
1104 // for incompatible LO 4):
1106 css::uno::Reference
< css::lang::XSingleComponentFactory
> legacy
;
1107 if ((aElement
>>= legacy
) && legacy
.is()) {
1110 "Ignored XSingleComponentFactory not implementing XServiceInfo");
1114 throw css::lang::IllegalArgumentException(
1115 "Bad insert element", static_cast< cppu::OWeakObject
* >(this), 0);
1118 void ServiceManager::remove(css::uno::Any
const & aElement
)
1120 css::lang::IllegalArgumentException
,
1121 css::container::NoSuchElementException
, css::uno::RuntimeException
)
1123 css::uno::Sequence
< css::beans::NamedValue
> args
;
1124 if (aElement
>>= args
) {
1125 std::vector
< rtl::OUString
> uris
;
1126 for (sal_Int32 i
= 0; i
< args
.getLength(); ++i
) {
1127 if (args
[i
].Name
== "uri") {
1129 if (!(args
[i
].Value
>>= uri
)) {
1130 throw css::lang::IllegalArgumentException(
1132 static_cast< cppu::OWeakObject
* >(this), 0);
1134 uris
.push_back(uri
);
1136 throw css::lang::IllegalArgumentException(
1137 "Bad argument " + args
[i
].Name
,
1138 static_cast< cppu::OWeakObject
* >(this), 0);
1141 removeRdbFiles(uris
);
1144 css::uno::Reference
< css::lang::XServiceInfo
> info
;
1145 if ((aElement
>>= info
) && info
.is()) {
1146 if (!removeLegacyFactory(info
, true)) {
1147 throw css::container::NoSuchElementException(
1148 "Remove non-inserted factory object",
1149 static_cast< cppu::OWeakObject
* >(this));
1154 if (aElement
>>= impl
) {
1155 // For live-removal of extensions:
1156 removeImplementation(impl
);
1159 throw css::lang::IllegalArgumentException(
1160 "Bad remove element", static_cast< cppu::OWeakObject
* >(this), 0);
1163 css::uno::Reference
< css::container::XEnumeration
>
1164 ServiceManager::createContentEnumeration(rtl::OUString
const & aServiceName
)
1165 throw (css::uno::RuntimeException
)
1167 std::vector
< boost::shared_ptr
< Implementation
> > impls
;
1169 osl::MutexGuard
g(rBHelper
.rMutex
);
1170 ImplementationMap::const_iterator
i(data_
.services
.find(aServiceName
));
1171 if (i
!= data_
.services
.end()) {
1175 std::vector
< css::uno::Any
> factories
;
1176 for (std::vector
< boost::shared_ptr
< Implementation
> >::const_iterator
i(
1178 i
!= impls
.end(); ++i
)
1180 Implementation
* impl
= i
->get();
1183 osl::MutexGuard
g(rBHelper
.rMutex
);
1188 if (!impl
->loaded
) {
1189 // Postpone actual factory instantiation as long as possible (so
1190 // that e.g. opening LO's "Tools - Macros" menu does not try to
1191 // instantiate a JVM, which can lead to a synchronous error
1192 // dialog when no JVM is specified, and showing the dialog while
1193 // hovering over a menu can cause trouble):
1194 impl
->factory1
= new FactoryWrapper(this, impl
->info
);
1195 impl
->loaded
= true;
1198 if (impl
->factory1
.is()) {
1199 factories
.push_back(css::uno::makeAny(impl
->factory1
));
1200 } else if (impl
->factory2
.is()) {
1201 factories
.push_back(css::uno::makeAny(impl
->factory2
));
1203 throw css::uno::DeploymentException(
1204 ("Implementation " + impl
->info
->name
1205 + " does not provide a factory"),
1206 static_cast< cppu::OWeakObject
* >(this));
1209 return new ContentEnumeration(factories
);
1212 css::uno::Reference
< css::beans::XPropertySetInfo
>
1213 ServiceManager::getPropertySetInfo() throw (css::uno::RuntimeException
) {
1217 void ServiceManager::setPropertyValue(
1218 rtl::OUString
const & aPropertyName
, css::uno::Any
const &)
1220 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1221 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1222 css::uno::RuntimeException
)
1224 if (aPropertyName
== "DefaultContext") {
1225 throw css::beans::PropertyVetoException(
1226 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1228 throw css::beans::UnknownPropertyException(
1229 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1233 css::uno::Any
ServiceManager::getPropertyValue(
1234 rtl::OUString
const & PropertyName
)
1236 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1237 css::uno::RuntimeException
)
1239 if (PropertyName
!= "DefaultContext") {
1240 throw css::beans::UnknownPropertyException(
1241 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1243 assert(context_
.is());
1244 return css::uno::makeAny(context_
);
1247 void ServiceManager::addPropertyChangeListener(
1248 rtl::OUString
const & aPropertyName
,
1249 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
1252 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1253 css::uno::RuntimeException
)
1255 if (!aPropertyName
.isEmpty() && aPropertyName
!= "DefaultContext") {
1256 throw css::beans::UnknownPropertyException(
1257 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1259 // DefaultContext does not change, so just treat it as an event listener:
1260 return addEventListener(xListener
.get());
1263 void ServiceManager::removePropertyChangeListener(
1264 rtl::OUString
const & aPropertyName
,
1265 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
1268 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1269 css::uno::RuntimeException
)
1271 if (!aPropertyName
.isEmpty() && aPropertyName
!= "DefaultContext") {
1272 throw css::beans::UnknownPropertyException(
1273 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
1275 // DefaultContext does not change, so just treat it as an event listener:
1276 return removeEventListener(aListener
.get());
1279 void ServiceManager::addVetoableChangeListener(
1280 rtl::OUString
const & PropertyName
,
1281 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
1284 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1285 css::uno::RuntimeException
)
1287 if (!PropertyName
.isEmpty() && PropertyName
!= "DefaultContext") {
1288 throw css::beans::UnknownPropertyException(
1289 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1291 // DefaultContext does not change, so just treat it as an event listener:
1292 return addEventListener(aListener
.get());
1295 void ServiceManager::removeVetoableChangeListener(
1296 rtl::OUString
const & PropertyName
,
1297 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
1300 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1301 css::uno::RuntimeException
)
1303 if (!PropertyName
.isEmpty() && PropertyName
!= "DefaultContext") {
1304 throw css::beans::UnknownPropertyException(
1305 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
1307 // DefaultContext does not change, so just treat it as an event listener:
1308 return removeEventListener(aListener
.get());
1311 css::uno::Sequence
< css::beans::Property
> ServiceManager::getProperties()
1312 throw (css::uno::RuntimeException
)
1314 css::uno::Sequence
< css::beans::Property
> props(1);
1315 props
[0] = getDefaultContextProperty();
1319 css::beans::Property
ServiceManager::getPropertyByName(
1320 rtl::OUString
const & aName
)
1321 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
)
1323 if (aName
!= "DefaultContext") {
1324 throw css::beans::UnknownPropertyException(
1325 aName
, static_cast< cppu::OWeakObject
* >(this));
1327 return getDefaultContextProperty();
1330 sal_Bool
ServiceManager::hasPropertyByName(rtl::OUString
const & Name
)
1331 throw (css::uno::RuntimeException
)
1333 return Name
== "DefaultContext";
1336 void ServiceManager::disposing(css::lang::EventObject
const & Source
)
1337 throw (css::uno::RuntimeException
)
1339 removeLegacyFactory(
1340 css::uno::Reference
< css::lang::XServiceInfo
>(
1341 Source
.Source
, css::uno::UNO_QUERY_THROW
),
1345 void ServiceManager::disposing() {
1346 std::vector
< css::uno::Reference
< css::lang::XComponent
> > comps
;
1349 osl::MutexGuard
g(rBHelper
.rMutex
);
1350 for (DynamicImplementations::const_iterator
i(
1351 data_
.dynamicImplementations
.begin());
1352 i
!= data_
.dynamicImplementations
.end(); ++i
)
1354 assert(i
->second
.get() != 0);
1355 if (i
->second
->component
.is()) {
1356 comps
.push_back(i
->second
->component
);
1359 data_
.namedImplementations
.swap(clear
.namedImplementations
);
1360 data_
.dynamicImplementations
.swap(clear
.dynamicImplementations
);
1361 data_
.services
.swap(clear
.services
);
1362 data_
.singletons
.swap(clear
.singletons
);
1365 css::uno::Reference
< css::lang::XComponent
> >::const_iterator
i(
1367 i
!= comps
.end(); ++i
)
1369 removeEventListenerFromComponent(*i
);
1373 void ServiceManager::removeEventListenerFromComponent(
1374 css::uno::Reference
< css::lang::XComponent
> const & component
)
1376 assert(component
.is());
1378 component
->removeEventListener(this);
1379 } catch (css::uno::RuntimeException
& e
) {
1382 "Ignored removeEventListener RuntimeException " + e
.Message
);
1386 void ServiceManager::readRdbs(rtl::OUString
const & uris
) {
1387 for (sal_Int32 i
= 0; i
!= -1;) {
1388 rtl::OUString
uri(uris
.getToken(0, ' ', i
));
1389 if (uri
.isEmpty()) {
1394 decodeRdbUri(&uri
, &optional
, &directory
);
1396 readRdbDirectory(uri
, optional
);
1398 readRdbFile(uri
, optional
);
1403 void ServiceManager::readRdbDirectory(rtl::OUString
const & uri
, bool optional
)
1405 osl::Directory
dir(uri
);
1406 switch (dir
.open()) {
1407 case osl::FileBase::E_None
:
1409 case osl::FileBase::E_NOENT
:
1411 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
1416 throw css::uno::DeploymentException(
1417 "Cannot open directory " + uri
,
1418 static_cast< cppu::OWeakObject
* >(this));
1422 if (!nextDirectoryItem(dir
, &url
)) {
1425 readRdbFile(url
, false);
1429 void ServiceManager::readRdbFile(rtl::OUString
const & uri
, bool optional
) {
1432 uri
, css::uno::Reference
< css::uno::XComponentContext
>(), &data_
);
1433 } catch (css::container::NoSuchElementException
&) {
1435 throw css::uno::DeploymentException(
1436 uri
+ ": no such file",
1437 static_cast< cppu::OWeakObject
* >(this));
1439 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
1440 } catch (css::registry::InvalidRegistryException
& e
) {
1441 if (!readLegacyRdbFile(uri
)) {
1442 throw css::uno::DeploymentException(
1443 "InvalidRegistryException: " + e
.Message
,
1444 static_cast< cppu::OWeakObject
* >(this));
1446 } catch (css::uno::RuntimeException
&) {
1447 if (!readLegacyRdbFile(uri
)) {
1453 bool ServiceManager::readLegacyRdbFile(rtl::OUString
const & uri
) {
1455 switch (reg
.open(uri
, REG_READONLY
)) {
1458 case REG_REGISTRY_NOT_EXISTS
:
1459 case REG_INVALID_REGISTRY
:
1461 // Ignore empty rdb files (which are at least seen by subordinate
1462 // uno processes during extension registration; Registry::open can
1463 // fail on them if mmap(2) returns EINVAL for a zero length):
1464 osl::DirectoryItem item
;
1465 if (osl::DirectoryItem::get(uri
, item
) == osl::FileBase::E_None
) {
1466 osl::FileStatus
status(osl_FileStatus_Mask_FileSize
);
1467 if (item
.getFileStatus(status
) == osl::FileBase::E_None
1468 && status
.getFileSize() == 0)
1478 RegistryKey rootKey
;
1479 if (reg
.openRootKey(rootKey
) != REG_NO_ERROR
) {
1480 throw css::uno::DeploymentException(
1481 "Failure reading legacy rdb file " + uri
,
1482 static_cast< cppu::OWeakObject
* >(this));
1484 RegistryKeyArray impls
;
1485 switch (rootKey
.openSubKeys("IMPLEMENTATIONS", impls
)) {
1488 case REG_KEY_NOT_EXISTS
:
1491 throw css::uno::DeploymentException(
1492 "Failure reading legacy rdb file " + uri
,
1493 static_cast< cppu::OWeakObject
* >(this));
1495 for (sal_uInt32 i
= 0; i
!= impls
.getLength(); ++i
) {
1496 RegistryKey
implKey(impls
.getElement(i
));
1497 assert(implKey
.getName().match("/IMPLEMENTATIONS/"));
1499 implKey
.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1500 boost::shared_ptr
< Implementation
> impl(
1502 name
, readLegacyRdbString(uri
, implKey
, "UNO/ACTIVATOR"),
1503 readLegacyRdbString(uri
, implKey
, "UNO/LOCATION"),
1505 css::uno::Reference
< css::uno::XComponentContext
>(), uri
));
1506 if (!data_
.namedImplementations
.insert(
1507 NamedImplementations::value_type(name
, impl
)).
1510 throw css::registry::InvalidRegistryException(
1511 uri
+ ": duplicate <implementation name=\"" + name
+ "\">",
1512 css::uno::Reference
< css::uno::XInterface
>());
1514 readLegacyRdbStrings(
1515 uri
, implKey
, "UNO/SERVICES", &impl
->info
->services
);
1516 for (std::vector
< rtl::OUString
>::const_iterator
j(
1517 impl
->info
->services
.begin());
1518 j
!= impl
->info
->services
.end(); ++j
)
1520 data_
.services
[*j
].push_back(impl
);
1522 readLegacyRdbStrings(
1523 uri
, implKey
, "UNO/SINGLETONS", &impl
->info
->singletons
);
1524 for (std::vector
< rtl::OUString
>::const_iterator
j(
1525 impl
->info
->singletons
.begin());
1526 j
!= impl
->info
->singletons
.end(); ++j
)
1528 data_
.singletons
[*j
].push_back(impl
);
1534 rtl::OUString
ServiceManager::readLegacyRdbString(
1535 rtl::OUString
const & uri
, RegistryKey
& key
, rtl::OUString
const & path
)
1540 if (key
.openKey(path
, subkey
) != REG_NO_ERROR
1541 || subkey
.getValueInfo(rtl::OUString(), &t
, &s
) != REG_NO_ERROR
1542 || t
!= RG_VALUETYPE_STRING
1543 || s
== 0 || s
> static_cast< sal_uInt32
>(SAL_MAX_INT32
))
1545 throw css::uno::DeploymentException(
1546 "Failure reading legacy rdb file " + uri
,
1547 static_cast< cppu::OWeakObject
* >(this));
1550 std::vector
< char > v(s
); // assuming sal_uInt32 fits into vector::size_type
1551 if (subkey
.getValue(rtl::OUString(), &v
[0]) != REG_NO_ERROR
1553 || !rtl_convertStringToUString(
1554 &val
.pData
, &v
[0], static_cast< sal_Int32
>(s
- 1),
1555 RTL_TEXTENCODING_UTF8
,
1556 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1557 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1558 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
)))
1560 throw css::uno::DeploymentException(
1561 "Failure reading legacy rdb file " + uri
,
1562 static_cast< cppu::OWeakObject
* >(this));
1567 void ServiceManager::readLegacyRdbStrings(
1568 rtl::OUString
const & uri
, RegistryKey
& key
, rtl::OUString
const & path
,
1569 std::vector
< rtl::OUString
> * strings
)
1571 assert(strings
!= 0);
1573 switch (key
.openKey(path
, subkey
)) {
1576 case REG_KEY_NOT_EXISTS
:
1579 throw css::uno::DeploymentException(
1580 "Failure reading legacy rdb file " + uri
,
1581 static_cast< cppu::OWeakObject
* >(this));
1583 rtl::OUString
prefix(subkey
.getName() + "/");
1584 RegistryKeyNames names
;
1585 if (subkey
.getKeyNames(rtl::OUString(), names
) != REG_NO_ERROR
) {
1586 throw css::uno::DeploymentException(
1587 "Failure reading legacy rdb file " + uri
,
1588 static_cast< cppu::OWeakObject
* >(this));
1590 for (sal_uInt32 i
= 0; i
!= names
.getLength(); ++i
) {
1591 assert(names
.getElement(i
).match(prefix
));
1592 strings
->push_back(names
.getElement(i
).copy(prefix
.getLength()));
1596 void ServiceManager::insertRdbFiles(
1597 std::vector
< rtl::OUString
> const & uris
,
1598 css::uno::Reference
< css::uno::XComponentContext
> const & alienContext
)
1601 for (std::vector
< rtl::OUString
>::const_iterator
i(uris
.begin());
1602 i
!= uris
.end(); ++i
)
1605 Parser(*i
, alienContext
, &extra
);
1606 } catch (css::container::NoSuchElementException
&) {
1607 throw css::lang::IllegalArgumentException(
1608 *i
+ ": no such file", static_cast< cppu::OWeakObject
* >(this),
1610 } catch (css::registry::InvalidRegistryException
& e
) {
1611 throw css::lang::IllegalArgumentException(
1612 "InvalidRegistryException: " + e
.Message
,
1613 static_cast< cppu::OWeakObject
* >(this), 0);
1616 insertExtraData(extra
);
1619 void ServiceManager::insertLegacyFactory(
1620 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
)
1622 assert(factoryInfo
.is());
1623 rtl::OUString
name(factoryInfo
->getImplementationName());
1624 css::uno::Reference
< css::lang::XSingleComponentFactory
> f1(
1625 factoryInfo
, css::uno::UNO_QUERY
);
1626 css::uno::Reference
< css::lang::XSingleServiceFactory
> f2
;
1628 f2
= css::uno::Reference
< css::lang::XSingleServiceFactory
>(
1629 factoryInfo
, css::uno::UNO_QUERY
);
1631 css::uno::Reference
< css::lang::XComponent
> comp(
1632 factoryInfo
, css::uno::UNO_QUERY
);
1633 boost::shared_ptr
< Implementation
> impl(
1634 new Implementation(name
, f1
, f2
, comp
));
1636 if (!name
.isEmpty()) {
1637 extra
.namedImplementations
.insert(
1638 NamedImplementations::value_type(name
, impl
));
1640 extra
.dynamicImplementations
.insert(
1641 DynamicImplementations::value_type(factoryInfo
, impl
));
1642 css::uno::Sequence
< rtl::OUString
> services(
1643 factoryInfo
->getSupportedServiceNames());
1644 for (sal_Int32 i
= 0; i
!= services
.getLength(); ++i
) {
1645 impl
->info
->services
.push_back(services
[i
]);
1646 extra
.services
[services
[i
]].push_back(impl
);
1648 if (insertExtraData(extra
) && comp
.is()) {
1649 comp
->addEventListener(this);
1653 bool ServiceManager::insertExtraData(Data
const & extra
) {
1655 osl::MutexGuard
g(rBHelper
.rMutex
);
1659 for (NamedImplementations::const_iterator
i(
1660 extra
.namedImplementations
.begin());
1661 i
!= extra
.namedImplementations
.end(); ++i
)
1663 if (data_
.namedImplementations
.find(i
->first
)
1664 != data_
.namedImplementations
.end())
1666 throw css::lang::IllegalArgumentException(
1667 "Insert duplicate implementation name " + i
->first
,
1668 static_cast< cppu::OWeakObject
* >(this), 0);
1671 for (DynamicImplementations::const_iterator
i(
1672 extra
.dynamicImplementations
.begin());
1673 i
!= extra
.dynamicImplementations
.end(); ++i
)
1675 if (data_
.dynamicImplementations
.find(i
->first
)
1676 != data_
.dynamicImplementations
.end())
1678 throw css::lang::IllegalArgumentException(
1679 "Insert duplicate factory object",
1680 static_cast< cppu::OWeakObject
* >(this), 0);
1683 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1684 data_
.namedImplementations
.insert(
1685 extra
.namedImplementations
.begin(),
1686 extra
.namedImplementations
.end());
1687 data_
.dynamicImplementations
.insert(
1688 extra
.dynamicImplementations
.begin(),
1689 extra
.dynamicImplementations
.end());
1690 insertImplementationMap(&data_
.services
, extra
.services
);
1691 insertImplementationMap(&data_
.singletons
, extra
.singletons
);
1693 //TODO: Updating the component context singleton data should be part of the
1694 // atomic service manager update:
1695 if (!extra
.singletons
.empty()) {
1696 assert(context_
.is());
1697 css::uno::Reference
< css::container::XNameContainer
> cont(
1698 context_
, css::uno::UNO_QUERY_THROW
);
1699 for (ImplementationMap::const_iterator
i(extra
.singletons
.begin());
1700 i
!= extra
.singletons
.end(); ++i
)
1702 rtl::OUString
name("/singletons/" + i
->first
);
1703 //TODO: Update should be atomic:
1705 cont
->removeByName(name
+ "/arguments");
1706 } catch (const css::container::NoSuchElementException
&) {}
1707 assert(!i
->second
.empty());
1708 assert(i
->second
[0].get() != 0);
1710 i
->second
.size() > 1, "cppuhelper",
1711 "Arbitrarily chosing " << i
->second
[0]->info
->name
1712 << " among multiple implementations for singleton "
1716 name
+ "/service", css::uno::Any(i
->second
[0]->info
->name
));
1717 } catch (css::container::ElementExistException
&) {
1718 cont
->replaceByName(
1719 name
+ "/service", css::uno::Any(i
->second
[0]->info
->name
));
1722 cont
->insertByName(name
, css::uno::Any());
1723 } catch (css::container::ElementExistException
&) {
1724 SAL_INFO("cppuhelper", "Overwriting singleton " << i
->first
);
1725 cont
->replaceByName(name
, css::uno::Any());
1732 void ServiceManager::removeRdbFiles(std::vector
< rtl::OUString
> const & uris
) {
1733 // The underlying data structures make this function somewhat inefficient,
1734 // but the assumption is that it is rarely called (and that if it is called,
1735 // it is called with a uris vector of size one):
1736 std::vector
< boost::shared_ptr
< Implementation
> > clear
;
1738 osl::MutexGuard
g(rBHelper
.rMutex
);
1739 for (std::vector
< rtl::OUString
>::const_iterator
i(uris
.begin());
1740 i
!= uris
.end(); ++i
)
1742 for (NamedImplementations::iterator
j(
1743 data_
.namedImplementations
.begin());
1744 j
!= data_
.namedImplementations
.end();)
1746 assert(j
->second
.get() != 0);
1747 if (j
->second
->info
->rdbFile
== *i
) {
1748 clear
.push_back(j
->second
);
1749 //TODO: The below leaves data_ in an inconsistent state upon
1751 removeFromImplementationMap(
1752 &data_
.services
, j
->second
->info
->services
, j
->second
);
1753 removeFromImplementationMap(
1754 &data_
.singletons
, j
->second
->info
->singletons
,
1756 data_
.namedImplementations
.erase(j
++);
1763 //TODO: Update the component context singleton data
1766 bool ServiceManager::removeLegacyFactory(
1767 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
,
1768 bool removeListener
)
1770 assert(factoryInfo
.is());
1771 boost::shared_ptr
< Implementation
> clear
;
1772 css::uno::Reference
< css::lang::XComponent
> comp
;
1774 osl::MutexGuard
g(rBHelper
.rMutex
);
1775 DynamicImplementations::iterator
i(
1776 data_
.dynamicImplementations
.find(factoryInfo
));
1777 if (i
== data_
.dynamicImplementations
.end()) {
1778 return isDisposed();
1780 assert(i
->second
.get() != 0);
1782 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1783 removeFromImplementationMap(
1784 &data_
.services
, i
->second
->info
->services
, i
->second
);
1785 removeFromImplementationMap(
1786 &data_
.singletons
, i
->second
->info
->singletons
, i
->second
);
1787 if (!i
->second
->info
->name
.isEmpty()) {
1788 data_
.namedImplementations
.erase(i
->second
->info
->name
);
1790 data_
.dynamicImplementations
.erase(i
);
1791 if (removeListener
) {
1792 comp
= i
->second
->component
;
1796 removeEventListenerFromComponent(comp
);
1801 void ServiceManager::removeImplementation(rtl::OUString name
) {
1802 // The underlying data structures make this function somewhat inefficient,
1803 // but the assumption is that it is rarely called:
1804 boost::shared_ptr
< Implementation
> clear
;
1806 osl::MutexGuard
g(rBHelper
.rMutex
);
1810 NamedImplementations::iterator
i(data_
.namedImplementations
.find(name
));
1811 if (i
== data_
.namedImplementations
.end()) {
1812 throw css::container::NoSuchElementException(
1813 "Remove non-inserted implementation " + name
,
1814 static_cast< cppu::OWeakObject
* >(this));
1816 assert(i
->second
.get() != 0);
1818 //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1819 removeFromImplementationMap(
1820 &data_
.services
, i
->second
->info
->services
, i
->second
);
1821 removeFromImplementationMap(
1822 &data_
.singletons
, i
->second
->info
->singletons
, i
->second
);
1823 for (DynamicImplementations::iterator
j(
1824 data_
.dynamicImplementations
.begin());
1825 j
!= data_
.dynamicImplementations
.end(); ++j
)
1827 if (j
->second
== i
->second
) {
1828 data_
.dynamicImplementations
.erase(j
);
1832 data_
.namedImplementations
.erase(i
);
1836 boost::shared_ptr
< Implementation
> ServiceManager::findServiceImplementation(
1837 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
1838 rtl::OUString
const & specifier
)
1840 boost::shared_ptr
< Implementation
> impl
;
1843 osl::MutexGuard
g(rBHelper
.rMutex
);
1844 ImplementationMap::const_iterator
i(data_
.services
.find(specifier
));
1845 if (i
== data_
.services
.end()) {
1846 NamedImplementations::const_iterator
j(
1847 data_
.namedImplementations
.find(specifier
));
1848 if (j
== data_
.namedImplementations
.end()) {
1849 SAL_INFO("cppuhelper", "No implementation for " << specifier
);
1850 return boost::shared_ptr
< Implementation
>();
1854 assert(!i
->second
.empty());
1856 i
->second
.size() > 1, "cppuhelper",
1857 "Arbitrarily chosing " << i
->second
[0]->info
->name
1858 << " among multiple implementations for " << i
->first
);
1859 impl
= i
->second
[0];
1861 assert(impl
.get() != 0);
1862 loaded
= impl
->loaded
;
1864 //TODO: There is a race here, as the relevant service factory can be removed
1865 // while the mutex is unlocked and loading can thus fail, as the entity from
1866 // which to load can disappear once the service factory is removed.
1868 css::uno::Reference
< css::lang::XSingleComponentFactory
> f1
;
1869 css::uno::Reference
< css::lang::XSingleServiceFactory
> f2
;
1870 loadImplementation(context
, impl
->info
, &f1
, &f2
);
1871 osl::MutexGuard
g(rBHelper
.rMutex
);
1872 if (!(isDisposed() || impl
->loaded
)) {
1873 impl
->loaded
= true;
1874 impl
->factory1
= f1
;
1875 impl
->factory2
= f2
;
1881 css::uno::Reference
< css::uno::XInterface
>
1882 FactoryWrapper::createInstanceWithContext(
1883 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
1884 throw (css::uno::Exception
, css::uno::RuntimeException
)
1886 loadImplementation(Context
);
1887 return factory1_
.is()
1888 ? factory1_
->createInstanceWithContext(Context
)
1889 : factory2_
->createInstance();
1892 css::uno::Reference
< css::uno::XInterface
>
1893 FactoryWrapper::createInstanceWithArgumentsAndContext(
1894 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
1895 css::uno::Reference
< css::uno::XComponentContext
> const & Context
)
1896 throw (css::uno::Exception
, css::uno::RuntimeException
)
1898 loadImplementation(Context
);
1899 return factory1_
.is()
1900 ? factory1_
->createInstanceWithArgumentsAndContext(Arguments
, Context
)
1901 : factory2_
->createInstanceWithArguments(Arguments
);
1904 css::uno::Reference
< css::uno::XInterface
> FactoryWrapper::createInstance()
1905 throw (css::uno::Exception
, css::uno::RuntimeException
)
1907 loadImplementation(manager_
->getContext());
1908 return factory1_
.is()
1909 ? factory1_
->createInstanceWithContext(manager_
->getContext())
1910 : factory2_
->createInstance();
1913 css::uno::Reference
< css::uno::XInterface
>
1914 FactoryWrapper::createInstanceWithArguments(
1915 css::uno::Sequence
< css::uno::Any
> const & Arguments
)
1916 throw (css::uno::Exception
, css::uno::RuntimeException
)
1918 loadImplementation(manager_
->getContext());
1919 return factory1_
.is()
1920 ? factory1_
->createInstanceWithArgumentsAndContext(
1921 Arguments
, manager_
->getContext())
1922 : factory2_
->createInstanceWithArguments(Arguments
);
1925 rtl::OUString
FactoryWrapper::getImplementationName()
1926 throw (css::uno::RuntimeException
)
1931 sal_Bool
FactoryWrapper::supportsService(rtl::OUString
const & ServiceName
)
1932 throw (css::uno::RuntimeException
)
1934 return cppu::supportsService(this, ServiceName
);
1937 css::uno::Sequence
< rtl::OUString
> FactoryWrapper::getSupportedServiceNames()
1938 throw (css::uno::RuntimeException
)
1940 if (info_
->services
.size() > static_cast< sal_uInt32
>(SAL_MAX_INT32
)) {
1941 throw css::uno::RuntimeException(
1942 "Implementation " + info_
->name
+ " supports too many services",
1943 static_cast< cppu::OWeakObject
* >(this));
1945 css::uno::Sequence
< rtl::OUString
> names(
1946 static_cast< sal_Int32
>(info_
->services
.size()));
1948 for (std::vector
< rtl::OUString
>::const_iterator
j(
1949 info_
->services
.begin());
1950 j
!= info_
->services
.end(); ++j
)
1957 void FactoryWrapper::loadImplementation(
1958 css::uno::Reference
< css::uno::XComponentContext
> const & context
)
1961 osl::MutexGuard
g(mutex_
);
1966 css::uno::Reference
< css::lang::XSingleComponentFactory
> f1
;
1967 css::uno::Reference
< css::lang::XSingleServiceFactory
> f2
;
1968 //TODO: There is a race here, as the relevant service factory can already
1969 // have been removed and loading can thus fail, as the entity from which to
1970 // load can disappear once the service factory is removed:
1971 manager_
->loadImplementation(context
, info_
, &f1
, &f2
);
1972 if (!(f1
.is() || f2
.is())) {
1973 throw css::uno::DeploymentException(
1974 "Implementation " + info_
->name
+ " does not provide a factory",
1975 static_cast< cppu::OWeakObject
* >(this));
1977 osl::MutexGuard
g(mutex_
);
1985 css::uno::Reference
< css::uno::XComponentContext
> bootstrapComponentContext(
1986 css::uno::Reference
< css::registry::XSimpleRegistry
> const & typeRegistry
,
1987 rtl::OUString
const & serviceUris
, rtl::Bootstrap
const & bootstrap
)
1989 rtl::Reference
< ServiceManager
> smgr(new ServiceManager(serviceUris
));
1990 cppu::ContextEntry_Init entry
;
1991 std::vector
< cppu::ContextEntry_Init
> context_values
;
1992 context_values
.push_back(
1993 cppu::ContextEntry_Init(
1994 "/singletons/com.sun.star.lang.theServiceManager",
1996 css::uno::Reference
< css::uno::XInterface
>(
1997 static_cast< cppu::OWeakObject
* >(smgr
.get()))),
1999 context_values
.push_back( //TODO: from services.rdb?
2000 cppu::ContextEntry_Init(
2001 "/singletons/com.sun.star.reflection.theTypeDescriptionManager",
2003 rtl::OUString("com.sun.star.comp.stoc.TypeDescriptionManager")),
2004 true /*TODO: false?*/));
2005 context_values
.push_back( //TODO: from services.rdb?
2006 cppu::ContextEntry_Init(
2007 "/singletons/com.sun.star.util.theMacroExpander",
2009 cppuhelper::detail::create_bootstrap_macro_expander_factory()),
2011 Data
const & data
= smgr
->getData();
2012 for (ImplementationMap::const_iterator
i(data
.singletons
.begin());
2013 i
!= data
.singletons
.end(); ++i
)
2015 assert(!i
->second
.empty());
2016 assert(i
->second
[0].get() != 0);
2018 i
->second
.size() > 1, "cppuhelper",
2019 "Arbitrarily chosing " << i
->second
[0]->info
->name
2020 << " among multiple implementations for " << i
->first
);
2021 context_values
.push_back(
2022 cppu::ContextEntry_Init(
2023 "/singletons/" + i
->first
,
2024 css::uno::makeAny(i
->second
[0]->info
->name
), true));
2026 cppu::add_access_control_entries(&context_values
, bootstrap
);
2027 assert(!context_values
.empty());
2028 css::uno::Reference
< css::uno::XComponentContext
> context(
2029 createComponentContext(
2030 &context_values
[0], context_values
.size(),
2031 css::uno::Reference
< css::uno::XComponentContext
>()));
2032 smgr
->setContext(context
);
2033 css::uno::Reference
< css::container::XHierarchicalNameAccess
> tdmgr(
2034 context
->getValueByName(
2035 "/singletons/com.sun.star.reflection.theTypeDescriptionManager"),
2036 css::uno::UNO_QUERY_THROW
);
2037 if (typeRegistry
.is()) {
2038 css::uno::Sequence
< css::uno::Any
> arg(1);
2039 arg
[0] <<= typeRegistry
;
2040 css::uno::Reference
< css::container::XSet
>(
2041 tdmgr
, css::uno::UNO_QUERY_THROW
)->
2044 smgr
->createInstanceWithArgumentsAndContext(
2045 ("com.sun.star.comp.stoc"
2046 ".RegistryTypeDescriptionProvider"),
2049 cppu::installTypeDescriptionManager(tdmgr
);
2053 rtl::OUString
getBootstrapVariable(
2054 rtl::Bootstrap
const & bootstrap
, rtl::OUString
const & name
)
2057 if (!bootstrap
.getFrom(name
, v
)) {
2058 throw css::uno::DeploymentException(
2059 "Cannot obtain " + name
+ " from uno ini",
2060 css::uno::Reference
< css::uno::XInterface
>());
2065 css::uno::Reference
< css::registry::XSimpleRegistry
> readTypeRdbFile(
2066 rtl::OUString
const & uri
, bool optional
,
2067 css::uno::Reference
< css::registry::XSimpleRegistry
> const & lastRegistry
,
2068 css::uno::Reference
< css::lang::XSingleServiceFactory
> const &
2069 simpleRegistryFactory
,
2070 css::uno::Reference
< css::lang::XSingleServiceFactory
> const &
2071 nestedRegistryFactory
)
2073 assert(simpleRegistryFactory
.is() && nestedRegistryFactory
.is());
2075 css::uno::Reference
< css::registry::XSimpleRegistry
> simple(
2076 simpleRegistryFactory
->createInstance(), css::uno::UNO_QUERY_THROW
);
2077 simple
->open(uri
, true, false);
2078 if (lastRegistry
.is()) {
2079 css::uno::Reference
< css::registry::XSimpleRegistry
> nested(
2080 nestedRegistryFactory
->createInstance(),
2081 css::uno::UNO_QUERY_THROW
);
2082 css::uno::Sequence
< css::uno::Any
> args(2);
2083 args
[0] <<= lastRegistry
;
2085 css::uno::Reference
< css::lang::XInitialization
>(
2086 nested
, css::uno::UNO_QUERY_THROW
)->
2092 } catch (css::registry::InvalidRegistryException
& e
) {
2094 throw css::uno::DeploymentException(
2095 "Invalid registry " + uri
+ ":" + e
.Message
,
2096 css::uno::Reference
< css::uno::XInterface
>());
2098 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
2099 return lastRegistry
;
2103 css::uno::Reference
< css::registry::XSimpleRegistry
> readTypeRdbDirectory(
2104 rtl::OUString
const & uri
, bool optional
,
2105 css::uno::Reference
< css::registry::XSimpleRegistry
> const & lastRegistry
,
2106 css::uno::Reference
< css::lang::XSingleServiceFactory
> const &
2107 simpleRegistryFactory
,
2108 css::uno::Reference
< css::lang::XSingleServiceFactory
> const &
2109 nestedRegistryFactory
)
2111 assert(simpleRegistryFactory
.is() && nestedRegistryFactory
.is());
2112 osl::Directory
dir(uri
);
2113 switch (dir
.open()) {
2114 case osl::FileBase::E_None
:
2116 case osl::FileBase::E_NOENT
:
2118 SAL_INFO("cppuhelper", "Ignored optional " << uri
);
2119 return lastRegistry
;
2123 throw css::uno::DeploymentException(
2124 "Cannot open directory " + uri
,
2125 css::uno::Reference
< css::uno::XInterface
>());
2127 css::uno::Reference
< css::registry::XSimpleRegistry
> last(lastRegistry
);
2129 rtl::OUString fileUri
;
2130 if (!nextDirectoryItem(dir
, &fileUri
)) {
2133 last
= readTypeRdbFile(
2134 fileUri
, optional
, last
, simpleRegistryFactory
,
2135 nestedRegistryFactory
);
2140 css::uno::Reference
< css::registry::XSimpleRegistry
> createTypeRegistry(
2141 rtl::OUString
const & uris
, rtl::OUString
const & libraryDirectoryUri
)
2143 css::uno::Reference
< css::lang::XMultiComponentFactory
> factory(
2144 cppu::bootstrapInitialSF(libraryDirectoryUri
));
2145 css::uno::Reference
< css::lang::XSingleServiceFactory
> simpleRegs(
2146 cppu::loadSharedLibComponentFactory(
2147 "bootstrap.uno" SAL_DLLEXTENSION
, libraryDirectoryUri
,
2148 "com.sun.star.comp.stoc.SimpleRegistry",
2149 css::uno::Reference
< css::lang::XMultiServiceFactory
>(
2150 factory
, css::uno::UNO_QUERY_THROW
),
2151 css::uno::Reference
< css::registry::XRegistryKey
>()),
2152 css::uno::UNO_QUERY_THROW
);
2153 css::uno::Reference
< css::lang::XSingleServiceFactory
> nestedRegs(
2154 cppu::loadSharedLibComponentFactory(
2155 "bootstrap.uno" SAL_DLLEXTENSION
, libraryDirectoryUri
,
2156 "com.sun.star.comp.stoc.NestedRegistry",
2157 css::uno::Reference
< css::lang::XMultiServiceFactory
>(
2158 factory
, css::uno::UNO_QUERY_THROW
),
2159 css::uno::Reference
< css::registry::XRegistryKey
>()),
2160 css::uno::UNO_QUERY_THROW
);
2161 css::uno::Reference
< css::registry::XSimpleRegistry
> reg
;
2162 for (sal_Int32 i
= 0; i
!= -1;) {
2163 rtl::OUString
uri(uris
.getToken(0, ' ', i
));
2164 if (uri
.isEmpty()) {
2169 decodeRdbUri(&uri
, &optional
, &directory
);
2171 ? readTypeRdbDirectory(uri
, optional
, reg
, simpleRegs
, nestedRegs
)
2172 : readTypeRdbFile(uri
, optional
, reg
, simpleRegs
, nestedRegs
);
2179 css::uno::Reference
< css::uno::XComponentContext
>
2180 cppu::defaultBootstrap_InitialComponentContext(rtl::OUString
const & iniUri
)
2181 SAL_THROW((css::uno::Exception
))
2183 rtl::Bootstrap
bs(iniUri
);
2184 if (bs
.getHandle() == 0) {
2185 throw css::uno::DeploymentException(
2186 "Cannot open uno ini " + iniUri
,
2187 css::uno::Reference
< css::uno::XInterface
>());
2189 return bootstrapComponentContext(
2191 getBootstrapVariable(bs
, "UNO_TYPES"),
2192 getBootstrapVariable(bs
, "URE_INTERNAL_LIB_DIR")),
2193 getBootstrapVariable(bs
, "UNO_SERVICES"), bs
);
2196 css::uno::Reference
< css::uno::XComponentContext
>
2197 cppu::defaultBootstrap_InitialComponentContext()
2198 SAL_THROW((css::uno::Exception
))
2200 return defaultBootstrap_InitialComponentContext(getUnoIniUri());
2203 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */