Revert "new change in helpcontent2"
[LibreOffice.git] / cppuhelper / source / defaultbootstrap.cxx
blobccf744769d4b028a546d224fd811bbdbd6bb26b8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
13 * License.
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"
32 #include <algorithm>
33 #include <cassert>
34 #include <cstring>
35 #include <map>
36 #include <vector>
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"
75 #include "paths.hxx"
76 #include "servicefactory_detail.hxx"
78 namespace {
80 namespace css = com::sun::star;
82 bool nextDirectoryItem(osl::Directory & directory, rtl::OUString * url) {
83 assert(url != 0);
84 for (;;) {
85 osl::DirectoryItem i;
86 switch (directory.getNextItem(i, SAL_MAX_UINT32)) {
87 case osl::FileBase::E_None:
88 break;
89 case osl::FileBase::E_NOENT:
90 return false;
91 default:
92 throw css::uno::DeploymentException(
93 "Cannot iterate directory",
94 css::uno::Reference< css::uno::XInterface >());
96 osl::FileStatus stat(
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();
109 return true;
115 void decodeRdbUri(rtl::OUString * uri, bool * optional, bool * directory) {
116 assert(uri != 0 && optional != 0 && directory != 0);
117 *optional = (*uri)[0] == '?';
118 if (*optional) {
119 *uri = uri->copy(1);
121 *directory = uri->getLength() >= 3 && (*uri)[0] == '<'
122 && (*uri)[uri->getLength() - 2] == '>'
123 && (*uri)[uri->getLength() - 1] == '*';
124 if (*directory) {
125 *uri = uri->copy(1, uri->getLength() - 3);
129 struct ImplementationInfo: private boost::noncopyable {
130 ImplementationInfo(
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 &
134 theAlienContext,
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 {
153 Implementation(
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):
158 info(
159 new ImplementationInfo(
160 name, loader, uri, prefix, alienContext, rdbFile)),
161 loaded(false)
164 Implementation(
165 rtl::OUString const & name,
166 css::uno::Reference< css::lang::XSingleComponentFactory > const &
167 theFactory1,
168 css::uno::Reference< css::lang::XSingleServiceFactory > const &
169 theFactory2,
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;
179 bool loaded;
182 typedef std::map< rtl::OUString, boost::shared_ptr< Implementation > >
183 NamedImplementations;
185 typedef
186 std::map<
187 css::uno::Reference< css::lang::XServiceInfo >,
188 boost::shared_ptr< Implementation > >
189 DynamicImplementations;
191 typedef
192 std::map<
193 rtl::OUString, std::vector< boost::shared_ptr< Implementation > > >
194 ImplementationMap;
196 void insertImplementationMap(
197 ImplementationMap * destination, ImplementationMap const & source)
199 assert(destination != 0);
200 for (ImplementationMap::const_iterator i(source.begin()); i != source.end();
201 ++i)
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:
215 assert(map != 0);
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());
224 j->second.erase(k);
225 if (j->second.empty()) {
226 map->erase(j);
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 {
246 public:
247 Parser(
248 rtl::OUString const & uri,
249 css::uno::Reference< css::uno::XComponentContext > const & alienContext,
250 Data * data);
252 private:
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_;
265 Data * data_;
266 rtl::OUString attrLoader_;
267 rtl::OUString attrUri_;
268 rtl::OUString attrPrefix_;
269 rtl::OUString attrImplementation_;
270 boost::shared_ptr< Implementation > implementation_;
273 Parser::Parser(
274 rtl::OUString const & uri,
275 css::uno::Reference< css::uno::XComponentContext > const & alienContext,
276 Data * data):
277 reader_(uri), alienContext_(alienContext), data_(data)
279 assert(data != 0);
280 int ucNsId = reader_.registerNamespaceIri(
281 xmlreader::Span(
282 RTL_CONSTASCII_STRINGPARAM(
283 "http://openoffice.org/2010/uno-components")));
284 enum State {
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;
289 int nsId;
290 xmlreader::XmlReader::Result res = reader_.nextItem(
291 xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
292 switch (state) {
293 case STATE_BEGIN:
294 if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
295 && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
297 state = STATE_COMPONENTS;
298 break;
300 throw css::registry::InvalidRegistryException(
301 reader_.getUrl() + ": unexpected item in outer level",
302 css::uno::Reference< css::uno::XInterface >());
303 case STATE_END:
304 if (res == xmlreader::XmlReader::RESULT_DONE) {
305 return;
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) {
312 state = STATE_END;
313 break;
315 if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
316 && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
318 handleComponent();
319 state = STATE_COMPONENT_INITIAL;
320 break;
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;
328 break;
330 // fall through
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;
337 break;
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;
345 break;
347 if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
348 && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
350 handleService();
351 state = STATE_SERVICE;
352 break;
354 if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
355 && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
357 handleSingleton();
358 state = STATE_SINGLETON;
359 break;
361 throw css::registry::InvalidRegistryException(
362 reader_.getUrl() + ": unexpected item in <implementation>",
363 css::uno::Reference< css::uno::XInterface >());
364 case STATE_SERVICE:
365 if (res == xmlreader::XmlReader::RESULT_END) {
366 state = STATE_IMPLEMENTATION;
367 break;
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;
375 break;
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;
389 int nsId;
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(
396 (reader_.getUrl()
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(
403 (reader_.getUrl()
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(
412 (reader_.getUrl()
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(
419 (reader_.getUrl()
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(
428 (reader_.getUrl() +
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(
435 (reader_.getUrl() +
436 ": <component> has empty \"prefix\" attribute"),
437 css::uno::Reference< css::uno::XInterface >());
439 } else {
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
457 try {
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 >());
464 #endif
467 void Parser::handleImplementation() {
468 attrImplementation_ = getNameAttribute();
469 implementation_.reset(
470 new Implementation(
471 attrImplementation_, attrLoader_, attrUri_, attrPrefix_,
472 alienContext_, reader_.getUrl()));
473 if (!data_->namedImplementations.insert(
474 NamedImplementations::value_type(
475 attrImplementation_, implementation_)).
476 second)
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;
500 int nsId;
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(
507 (reader_.getUrl()
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 >());
517 } else {
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 >());
528 return attrName;
531 class ContentEnumeration:
532 public cppu::WeakImplHelper1< css::container::XEnumeration >,
533 private boost::noncopyable
535 public:
536 explicit ContentEnumeration(std::vector< css::uno::Any > const & factories):
537 factories_(factories), iterator_(factories_.begin()) {}
539 private:
540 virtual ~ContentEnumeration() {}
542 virtual sal_Bool SAL_CALL hasMoreElements()
543 throw (css::uno::RuntimeException);
545 virtual css::uno::Any SAL_CALL nextElement()
546 throw (
547 css::container::NoSuchElementException,
548 css::lang::WrappedTargetException, css::uno::RuntimeException);
550 osl::Mutex mutex_;
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()
563 throw (
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));
573 return *iterator_++;
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 >
588 ServiceManagerBase;
590 class ServiceManager:
591 private osl::Mutex, public ServiceManagerBase, private boost::noncopyable
593 public:
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;
601 void setContext(
602 css::uno::Reference< css::uno::XComponentContext > const & context)
604 assert(context.is());
605 assert(!context_.is());
606 context_ = context;
609 css::uno::Reference< css::uno::XComponentContext > getContext() const {
610 assert(context_.is());
611 return context_;
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)
669 throw (
670 css::lang::IllegalArgumentException,
671 css::container::ElementExistException, css::uno::RuntimeException);
673 virtual void SAL_CALL remove(css::uno::Any const & aElement)
674 throw (
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)
687 throw (
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)
695 throw (
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 &
702 xListener)
703 throw (
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 &
710 aListener)
711 throw (
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 &
718 aListener)
719 throw (
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 &
726 aListener)
727 throw (
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)
736 throw (
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);
745 private:
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);
772 void insertRdbFiles(
773 std::vector< rtl::OUString > const & uris,
774 css::uno::Reference< css::uno::XComponentContext > const &
775 alientContext);
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_;
795 Data data_;
798 class FactoryWrapper:
799 public cppu::WeakImplHelper3<
800 css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
801 css::lang::XServiceInfo >,
802 private boost::noncopyable
804 public:
805 FactoryWrapper(
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); }
811 private:
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_;
848 osl::Mutex mutex_;
849 bool loaded_;
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)
860 assert(
861 info.get() != 0 && factory1 != 0 && !factory1->is() && factory2 != 0
862 && !factory2->is());
863 rtl::OUString uri;
864 try {
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()) {
880 prefix += "_";
882 f0 = cppu::loadSharedLibComponentFactory(
883 uri, rtl::OUString(), info->name, this,
884 css::uno::Reference< css::registry::XRegistryKey >(), prefix);
885 } else {
886 SAL_INFO_IF(
887 !info->prefix.isEmpty(), "cppuhelper",
888 "Loader " << info->loader << " and non-empty prefix "
889 << info->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);
896 } else {
897 assert(context.is());
898 ctxt = context;
899 smgr = this;
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";
933 return names;
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);
959 if (isDisposed()) {
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));
969 sal_Int32 i = 0;
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());
976 return names;
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);
1033 return
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)
1054 throw (
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") {
1064 rtl::OUString uri;
1065 if (!(args[i].Value >>= uri)) {
1066 throw css::lang::IllegalArgumentException(
1067 "Bad uri argument",
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);
1082 } else {
1083 throw css::lang::IllegalArgumentException(
1084 "Bad argument " + args[i].Name,
1085 static_cast< cppu::OWeakObject * >(this), 0);
1088 insertRdbFiles(uris, alienContext);
1089 return;
1091 css::uno::Reference< css::lang::XServiceInfo > info;
1092 if ((aElement >>= info) && info.is()) {
1093 insertLegacyFactory(info);
1094 return;
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):
1105 #if SUPD < 400
1106 css::uno::Reference< css::lang::XSingleComponentFactory > legacy;
1107 if ((aElement >>= legacy) && legacy.is()) {
1108 SAL_WARN(
1109 "cppuhelper",
1110 "Ignored XSingleComponentFactory not implementing XServiceInfo");
1111 return;
1113 #endif
1114 throw css::lang::IllegalArgumentException(
1115 "Bad insert element", static_cast< cppu::OWeakObject * >(this), 0);
1118 void ServiceManager::remove(css::uno::Any const & aElement)
1119 throw (
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") {
1128 rtl::OUString uri;
1129 if (!(args[i].Value >>= uri)) {
1130 throw css::lang::IllegalArgumentException(
1131 "Bad uri argument",
1132 static_cast< cppu::OWeakObject * >(this), 0);
1134 uris.push_back(uri);
1135 } else {
1136 throw css::lang::IllegalArgumentException(
1137 "Bad argument " + args[i].Name,
1138 static_cast< cppu::OWeakObject * >(this), 0);
1141 removeRdbFiles(uris);
1142 return;
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));
1151 return;
1153 rtl::OUString impl;
1154 if (aElement >>= impl) {
1155 // For live-removal of extensions:
1156 removeImplementation(impl);
1157 return;
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()) {
1172 impls = i->second;
1175 std::vector< css::uno::Any > factories;
1176 for (std::vector< boost::shared_ptr< Implementation > >::const_iterator i(
1177 impls.begin());
1178 i != impls.end(); ++i)
1180 Implementation * impl = i->get();
1181 assert(impl != 0);
1183 osl::MutexGuard g(rBHelper.rMutex);
1184 if (isDisposed()) {
1185 factories.clear();
1186 break;
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));
1202 } else {
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) {
1214 return this;
1217 void ServiceManager::setPropertyValue(
1218 rtl::OUString const & aPropertyName, css::uno::Any const &)
1219 throw (
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));
1227 } else {
1228 throw css::beans::UnknownPropertyException(
1229 aPropertyName, static_cast< cppu::OWeakObject * >(this));
1233 css::uno::Any ServiceManager::getPropertyValue(
1234 rtl::OUString const & PropertyName)
1235 throw (
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 &
1250 xListener)
1251 throw (
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 &
1266 aListener)
1267 throw (
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 &
1282 aListener)
1283 throw (
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 &
1298 aListener)
1299 throw (
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();
1316 return props;
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),
1342 false);
1345 void ServiceManager::disposing() {
1346 std::vector< css::uno::Reference< css::lang::XComponent > > comps;
1347 Data clear;
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);
1364 for (std::vector<
1365 css::uno::Reference< css::lang::XComponent > >::const_iterator i(
1366 comps.begin());
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());
1377 try {
1378 component->removeEventListener(this);
1379 } catch (css::uno::RuntimeException & e) {
1380 SAL_INFO(
1381 "cppuhelper",
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()) {
1390 continue;
1392 bool optional;
1393 bool directory;
1394 decodeRdbUri(&uri, &optional, &directory);
1395 if (directory) {
1396 readRdbDirectory(uri, optional);
1397 } else {
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:
1408 break;
1409 case osl::FileBase::E_NOENT:
1410 if (optional) {
1411 SAL_INFO("cppuhelper", "Ignored optional " << uri);
1412 return;
1414 // fall through
1415 default:
1416 throw css::uno::DeploymentException(
1417 "Cannot open directory " + uri,
1418 static_cast< cppu::OWeakObject * >(this));
1420 for (;;) {
1421 rtl::OUString url;
1422 if (!nextDirectoryItem(dir, &url)) {
1423 break;
1425 readRdbFile(url, false);
1429 void ServiceManager::readRdbFile(rtl::OUString const & uri, bool optional) {
1430 try {
1431 Parser(
1432 uri, css::uno::Reference< css::uno::XComponentContext >(), &data_);
1433 } catch (css::container::NoSuchElementException &) {
1434 if (!optional) {
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)) {
1448 throw;
1453 bool ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) {
1454 Registry reg;
1455 switch (reg.open(uri, REG_READONLY)) {
1456 case REG_NO_ERROR:
1457 break;
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)
1470 return true;
1474 // fall through
1475 default:
1476 return false;
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)) {
1486 case REG_NO_ERROR:
1487 break;
1488 case REG_KEY_NOT_EXISTS:
1489 return true;
1490 default:
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/"));
1498 rtl::OUString name(
1499 implKey.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1500 boost::shared_ptr< Implementation > impl(
1501 new Implementation(
1502 name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"),
1503 readLegacyRdbString(uri, implKey, "UNO/LOCATION"),
1504 rtl::OUString(),
1505 css::uno::Reference< css::uno::XComponentContext >(), uri));
1506 if (!data_.namedImplementations.insert(
1507 NamedImplementations::value_type(name, impl)).
1508 second)
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);
1531 return true;
1534 rtl::OUString ServiceManager::readLegacyRdbString(
1535 rtl::OUString const & uri, RegistryKey & key, rtl::OUString const & path)
1537 RegistryKey subkey;
1538 RegValueType t;
1539 sal_uInt32 s(0);
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));
1549 rtl::OUString val;
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
1552 || v.back() != '\0'
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));
1564 return val;
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);
1572 RegistryKey subkey;
1573 switch (key.openKey(path, subkey)) {
1574 case REG_NO_ERROR:
1575 break;
1576 case REG_KEY_NOT_EXISTS:
1577 return;
1578 default:
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)
1600 Data extra;
1601 for (std::vector< rtl::OUString >::const_iterator i(uris.begin());
1602 i != uris.end(); ++i)
1604 try {
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;
1627 if (!f1.is()) {
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));
1635 Data extra;
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);
1656 if (isDisposed()) {
1657 return false;
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:
1704 try {
1705 cont->removeByName(name + "/arguments");
1706 } catch (const css::container::NoSuchElementException &) {}
1707 assert(!i->second.empty());
1708 assert(i->second[0].get() != 0);
1709 SAL_INFO_IF(
1710 i->second.size() > 1, "cppuhelper",
1711 "Arbitrarily chosing " << i->second[0]->info->name
1712 << " among multiple implementations for singleton "
1713 << i->first);
1714 try {
1715 cont->insertByName(
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));
1721 try {
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());
1729 return true;
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
1750 // exceptions:
1751 removeFromImplementationMap(
1752 &data_.services, j->second->info->services, j->second);
1753 removeFromImplementationMap(
1754 &data_.singletons, j->second->info->singletons,
1755 j->second);
1756 data_.namedImplementations.erase(j++);
1757 } else {
1758 ++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);
1781 clear = i->second;
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;
1795 if (comp.is()) {
1796 removeEventListenerFromComponent(comp);
1798 return true;
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);
1807 if (isDisposed()) {
1808 return;
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);
1817 clear = i->second;
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);
1829 break;
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;
1841 bool loaded;
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 >();
1852 impl = j->second;
1853 } else {
1854 assert(!i->second.empty());
1855 SAL_INFO_IF(
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.
1867 if (!loaded) {
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;
1878 return impl;
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)
1928 return info_->name;
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()));
1947 sal_Int32 i = 0;
1948 for (std::vector< rtl::OUString >::const_iterator j(
1949 info_->services.begin());
1950 j != info_->services.end(); ++j)
1952 names[i++] = *j;
1954 return names;
1957 void FactoryWrapper::loadImplementation(
1958 css::uno::Reference< css::uno::XComponentContext > const & context)
1961 osl::MutexGuard g(mutex_);
1962 if (loaded_) {
1963 return;
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_);
1978 if (!loaded_) {
1979 loaded_ = true;
1980 factory1_ = f1;
1981 factory2_ = f2;
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",
1995 css::uno::makeAny(
1996 css::uno::Reference< css::uno::XInterface >(
1997 static_cast< cppu::OWeakObject * >(smgr.get()))),
1998 false));
1999 context_values.push_back( //TODO: from services.rdb?
2000 cppu::ContextEntry_Init(
2001 "/singletons/com.sun.star.reflection.theTypeDescriptionManager",
2002 css::uno::makeAny(
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",
2008 css::uno::makeAny(
2009 cppuhelper::detail::create_bootstrap_macro_expander_factory()),
2010 true));
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);
2017 SAL_INFO_IF(
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)->
2042 insert(
2043 css::uno::makeAny(
2044 smgr->createInstanceWithArgumentsAndContext(
2045 ("com.sun.star.comp.stoc"
2046 ".RegistryTypeDescriptionProvider"),
2047 arg, context)));
2049 cppu::installTypeDescriptionManager(tdmgr);
2050 return context;
2053 rtl::OUString getBootstrapVariable(
2054 rtl::Bootstrap const & bootstrap, rtl::OUString const & name)
2056 rtl::OUString v;
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 >());
2062 return v;
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());
2074 try {
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;
2084 args[1] <<= simple;
2085 css::uno::Reference< css::lang::XInitialization >(
2086 nested, css::uno::UNO_QUERY_THROW)->
2087 initialize(args);
2088 return nested;
2089 } else {
2090 return simple;
2092 } catch (css::registry::InvalidRegistryException & e) {
2093 if (!optional) {
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:
2115 break;
2116 case osl::FileBase::E_NOENT:
2117 if (optional) {
2118 SAL_INFO("cppuhelper", "Ignored optional " << uri);
2119 return lastRegistry;
2121 // fall through
2122 default:
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);
2128 for (;;) {
2129 rtl::OUString fileUri;
2130 if (!nextDirectoryItem(dir, &fileUri)) {
2131 break;
2133 last = readTypeRdbFile(
2134 fileUri, optional, last, simpleRegistryFactory,
2135 nestedRegistryFactory);
2137 return last;
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()) {
2165 continue;
2167 bool optional;
2168 bool directory;
2169 decodeRdbUri(&uri, &optional, &directory);
2170 reg = directory
2171 ? readTypeRdbDirectory(uri, optional, reg, simpleRegs, nestedRegs)
2172 : readTypeRdbFile(uri, optional, reg, simpleRegs, nestedRegs);
2174 return reg;
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(
2190 createTypeRegistry(
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: */