Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include "sal/config.h"
11 :
12 : #include <algorithm>
13 : #include <cassert>
14 : #include <vector>
15 :
16 : #include "boost/noncopyable.hpp"
17 : #include "boost/shared_ptr.hpp"
18 : #include "com/sun/star/beans/NamedValue.hpp"
19 : #include "com/sun/star/beans/PropertyAttribute.hpp"
20 : #include "com/sun/star/container/ElementExistException.hpp"
21 : #include "com/sun/star/container/XEnumeration.hpp"
22 : #include "com/sun/star/container/XNameContainer.hpp"
23 : #include "com/sun/star/lang/XServiceInfo.hpp"
24 : #include "com/sun/star/lang/XSingleComponentFactory.hpp"
25 : #include "com/sun/star/lang/XSingleServiceFactory.hpp"
26 : #include "com/sun/star/loader/XImplementationLoader.hpp"
27 : #include "com/sun/star/registry/InvalidRegistryException.hpp"
28 : #include "com/sun/star/uno/DeploymentException.hpp"
29 : #include "com/sun/star/uno/Reference.hxx"
30 : #include "com/sun/star/uno/XComponentContext.hpp"
31 : #include "cppuhelper/bootstrap.hxx"
32 : #include "cppuhelper/component_context.hxx"
33 : #include "cppuhelper/implbase1.hxx"
34 : #include "cppuhelper/implbase3.hxx"
35 : #include "cppuhelper/shlib.hxx"
36 : #include "cppuhelper/supportsservice.hxx"
37 : #include "osl/file.hxx"
38 : #include "rtl/ref.hxx"
39 : #include "rtl/uri.hxx"
40 : #include "rtl/ustring.hxx"
41 : #include "rtl/strbuf.hxx"
42 : #include "sal/log.hxx"
43 :
44 : using rtl::OUString;
45 : using rtl::OString;
46 : using rtl::OStringBuffer;
47 :
48 : #include "registry/registry.hxx"
49 : #include "xmlreader/xmlreader.hxx"
50 :
51 : #include "paths.hxx"
52 : #include "servicemanager.hxx"
53 :
54 : namespace {
55 :
56 830 : void insertImplementationMap(
57 : cppuhelper::ServiceManager::Data::ImplementationMap * destination,
58 : cppuhelper::ServiceManager::Data::ImplementationMap const & source)
59 : {
60 : assert(destination != 0);
61 3735 : for (cppuhelper::ServiceManager::Data::ImplementationMap::const_iterator i(
62 830 : source.begin());
63 2490 : i != source.end(); ++i)
64 : {
65 : std::vector<
66 : boost::shared_ptr<
67 : cppuhelper::ServiceManager::Data::Implementation > > & impls
68 415 : = (*destination)[i->first];
69 415 : impls.insert(impls.end(), i->second.begin(), i->second.end());
70 : }
71 830 : }
72 :
73 14 : void removeFromImplementationMap(
74 : cppuhelper::ServiceManager::Data::ImplementationMap * map,
75 : std::vector< rtl::OUString > const & elements,
76 : boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
77 : const & implementation)
78 : {
79 : // The underlying data structures make this function somewhat inefficient,
80 : // but the assumption is that it is rarely called:
81 : assert(map != 0);
82 63 : for (std::vector< rtl::OUString >::const_iterator i(elements.begin());
83 42 : i != elements.end(); ++i)
84 : {
85 : cppuhelper::ServiceManager::Data::ImplementationMap::iterator j(
86 7 : map->find(*i));
87 : assert(j != map->end());
88 : std::vector<
89 : boost::shared_ptr<
90 : cppuhelper::ServiceManager::Data::Implementation > >::iterator
91 7 : k(std::find(j->second.begin(), j->second.end(), implementation));
92 : assert(k != j->second.end());
93 7 : j->second.erase(k);
94 7 : if (j->second.empty()) {
95 7 : map->erase(j);
96 : }
97 : }
98 14 : }
99 :
100 : // For simplicity, this code keeps throwing
101 : // css::registry::InvalidRegistryException for invalid XML rdbs (even though
102 : // that does not fit the exception's name):
103 2565 : class Parser: private boost::noncopyable {
104 : public:
105 : Parser(
106 : rtl::OUString const & uri,
107 : css::uno::Reference< css::uno::XComponentContext > const & alienContext,
108 : cppuhelper::ServiceManager::Data * data);
109 :
110 : private:
111 : void handleComponent();
112 :
113 : void handleImplementation();
114 :
115 : void handleService();
116 :
117 : void handleSingleton();
118 :
119 : rtl::OUString getNameAttribute();
120 :
121 : xmlreader::XmlReader reader_;
122 : css::uno::Reference< css::uno::XComponentContext > alienContext_;
123 : cppuhelper::ServiceManager::Data * data_;
124 : rtl::OUString attrLoader_;
125 : rtl::OUString attrUri_;
126 : rtl::OUString attrPrefix_;
127 : rtl::OUString attrImplementation_;
128 : boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
129 : implementation_;
130 : };
131 :
132 2567 : Parser::Parser(
133 : rtl::OUString const & uri,
134 : css::uno::Reference< css::uno::XComponentContext > const & alienContext,
135 : cppuhelper::ServiceManager::Data * data):
136 2567 : reader_(uri), alienContext_(alienContext), data_(data)
137 : {
138 : assert(data != 0);
139 : int ucNsId = reader_.registerNamespaceIri(
140 : xmlreader::Span(
141 : RTL_CONSTASCII_STRINGPARAM(
142 2565 : "http://openoffice.org/2010/uno-components")));
143 : enum State {
144 : STATE_BEGIN, STATE_END, STATE_COMPONENTS, STATE_COMPONENT_INITIAL,
145 : STATE_COMPONENT, STATE_IMPLEMENTATION, STATE_SERVICE, STATE_SINGLETON };
146 2565 : for (State state = STATE_BEGIN;;) {
147 626549 : xmlreader::Span name;
148 : int nsId;
149 : xmlreader::XmlReader::Result res = reader_.nextItem(
150 626549 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
151 626549 : switch (state) {
152 : case STATE_BEGIN:
153 5130 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
154 5130 : && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
155 : {
156 2565 : state = STATE_COMPONENTS;
157 2565 : break;
158 : }
159 : throw css::registry::InvalidRegistryException(
160 0 : reader_.getUrl() + ": unexpected item in outer level",
161 0 : css::uno::Reference< css::uno::XInterface >());
162 : case STATE_END:
163 2565 : if (res == xmlreader::XmlReader::RESULT_DONE) {
164 5130 : return;
165 : }
166 : throw css::registry::InvalidRegistryException(
167 0 : reader_.getUrl() + ": unexpected item in outer level",
168 0 : css::uno::Reference< css::uno::XInterface >());
169 : case STATE_COMPONENTS:
170 26944 : if (res == xmlreader::XmlReader::RESULT_END) {
171 2565 : state = STATE_END;
172 2565 : break;
173 : }
174 48758 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
175 48758 : && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
176 : {
177 24379 : handleComponent();
178 24379 : state = STATE_COMPONENT_INITIAL;
179 24379 : break;
180 : }
181 : throw css::registry::InvalidRegistryException(
182 0 : reader_.getUrl() + ": unexpected item in <components>",
183 0 : css::uno::Reference< css::uno::XInterface >());
184 : case STATE_COMPONENT:
185 126974 : if (res == xmlreader::XmlReader::RESULT_END) {
186 24379 : state = STATE_COMPONENTS;
187 24379 : break;
188 : }
189 : // fall through
190 : case STATE_COMPONENT_INITIAL:
191 253948 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
192 253948 : && name.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
193 : {
194 126974 : handleImplementation();
195 126974 : state = STATE_IMPLEMENTATION;
196 126974 : break;
197 : }
198 : throw css::registry::InvalidRegistryException(
199 0 : reader_.getUrl() + ": unexpected item in <component>",
200 0 : css::uno::Reference< css::uno::XInterface >());
201 : case STATE_IMPLEMENTATION:
202 285048 : if (res == xmlreader::XmlReader::RESULT_END) {
203 126974 : state = STATE_COMPONENT;
204 126974 : break;
205 : }
206 316148 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
207 316148 : && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
208 : {
209 155695 : handleService();
210 155695 : state = STATE_SERVICE;
211 155695 : break;
212 : }
213 4758 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
214 4758 : && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
215 : {
216 2379 : handleSingleton();
217 2379 : state = STATE_SINGLETON;
218 2379 : break;
219 : }
220 : throw css::registry::InvalidRegistryException(
221 0 : reader_.getUrl() + ": unexpected item in <implementation>",
222 0 : css::uno::Reference< css::uno::XInterface >());
223 : case STATE_SERVICE:
224 155695 : if (res == xmlreader::XmlReader::RESULT_END) {
225 155695 : state = STATE_IMPLEMENTATION;
226 155695 : break;
227 : }
228 : throw css::registry::InvalidRegistryException(
229 0 : reader_.getUrl() + ": unexpected item in <service>",
230 0 : css::uno::Reference< css::uno::XInterface >());
231 : case STATE_SINGLETON:
232 2379 : if (res == xmlreader::XmlReader::RESULT_END) {
233 2379 : state = STATE_IMPLEMENTATION;
234 2379 : break;
235 : }
236 : throw css::registry::InvalidRegistryException(
237 0 : reader_.getUrl() + ": unexpected item in <service>",
238 0 : css::uno::Reference< css::uno::XInterface >());
239 : }
240 623984 : }
241 : }
242 :
243 24379 : void Parser::handleComponent() {
244 24379 : attrLoader_ = rtl::OUString();
245 24379 : attrUri_ = rtl::OUString();
246 24379 : attrPrefix_ = rtl::OUString();
247 24379 : xmlreader::Span name;
248 : int nsId;
249 24379 : while (reader_.nextAttribute(&nsId, &name)) {
250 143376 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
251 71688 : && name.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
252 : {
253 24379 : if (!attrLoader_.isEmpty()) {
254 : throw css::registry::InvalidRegistryException(
255 : (reader_.getUrl()
256 0 : + ": <component> has multiple \"loader\" attributes"),
257 0 : css::uno::Reference< css::uno::XInterface >());
258 : }
259 24379 : attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8();
260 24379 : if (attrLoader_.isEmpty()) {
261 : throw css::registry::InvalidRegistryException(
262 : (reader_.getUrl()
263 0 : + ": <component> has empty \"loader\" attribute"),
264 0 : css::uno::Reference< css::uno::XInterface >());
265 : }
266 94618 : } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
267 47309 : && name.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
268 : {
269 24379 : if (!attrUri_.isEmpty()) {
270 : throw css::registry::InvalidRegistryException(
271 : (reader_.getUrl()
272 0 : + ": <component> has multiple \"uri\" attributes"),
273 0 : css::uno::Reference< css::uno::XInterface >());
274 : }
275 24379 : attrUri_ = reader_.getAttributeValue(false).convertFromUtf8();
276 24379 : if (attrUri_.isEmpty()) {
277 : throw css::registry::InvalidRegistryException(
278 : (reader_.getUrl()
279 0 : + ": <component> has empty \"uri\" attribute"),
280 0 : css::uno::Reference< css::uno::XInterface >());
281 : }
282 45860 : } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
283 22930 : && name.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
284 : {
285 22930 : if (!attrPrefix_.isEmpty()) {
286 : throw css::registry::InvalidRegistryException(
287 0 : (reader_.getUrl() +
288 0 : ": <component> has multiple \"prefix\" attributes"),
289 0 : css::uno::Reference< css::uno::XInterface >());
290 : }
291 22930 : attrPrefix_ = reader_.getAttributeValue(false).convertFromUtf8();
292 22930 : if (attrPrefix_.isEmpty()) {
293 : throw css::registry::InvalidRegistryException(
294 0 : (reader_.getUrl() +
295 0 : ": <component> has empty \"prefix\" attribute"),
296 0 : css::uno::Reference< css::uno::XInterface >());
297 : }
298 : } else {
299 : throw css::registry::InvalidRegistryException(
300 0 : (reader_.getUrl() + ": unexpected attribute \""
301 0 : + name.convertFromUtf8() + "\" in <component>"),
302 0 : css::uno::Reference< css::uno::XInterface >());
303 : }
304 : }
305 24379 : if (attrLoader_.isEmpty()) {
306 : throw css::registry::InvalidRegistryException(
307 0 : reader_.getUrl() + ": <component> is missing \"loader\" attribute",
308 0 : css::uno::Reference< css::uno::XInterface >());
309 : }
310 24379 : if (attrUri_.isEmpty()) {
311 : throw css::registry::InvalidRegistryException(
312 0 : reader_.getUrl() + ": <component> is missing \"uri\" attribute",
313 0 : css::uno::Reference< css::uno::XInterface >());
314 : }
315 : #ifndef DISABLE_DYNLOADING
316 : try {
317 24379 : attrUri_ = rtl::Uri::convertRelToAbs(reader_.getUrl(), attrUri_);
318 0 : } catch (const rtl::MalformedUriException & e) {
319 : throw css::registry::InvalidRegistryException(
320 0 : reader_.getUrl() + ": bad \"uri\" attribute: " + e.getMessage(),
321 0 : css::uno::Reference< css::uno::XInterface >());
322 : }
323 : #endif
324 24379 : }
325 :
326 126974 : void Parser::handleImplementation() {
327 126974 : attrImplementation_ = getNameAttribute();
328 : implementation_.reset(
329 : new cppuhelper::ServiceManager::Data::Implementation(
330 : attrImplementation_, attrLoader_, attrUri_, attrPrefix_,
331 126974 : alienContext_, reader_.getUrl()));
332 253948 : if (!data_->namedImplementations.insert(
333 : cppuhelper::ServiceManager::Data::NamedImplementations::value_type(
334 253948 : attrImplementation_, implementation_)).
335 253948 : second)
336 : {
337 : throw css::registry::InvalidRegistryException(
338 0 : (reader_.getUrl() + ": duplicate <implementation name=\""
339 0 : + attrImplementation_ + "\">"),
340 0 : css::uno::Reference< css::uno::XInterface >());
341 : }
342 126974 : }
343 :
344 155695 : void Parser::handleService() {
345 155695 : rtl::OUString name(getNameAttribute());
346 155695 : implementation_->info->services.push_back(name);
347 155695 : data_->services[name].push_back(implementation_);
348 155695 : }
349 :
350 2379 : void Parser::handleSingleton() {
351 2379 : rtl::OUString name(getNameAttribute());
352 2379 : implementation_->info->singletons.push_back(name);
353 2379 : data_->singletons[name].push_back(implementation_);
354 2379 : }
355 :
356 285048 : rtl::OUString Parser::getNameAttribute() {
357 285048 : rtl::OUString attrName;
358 285048 : xmlreader::Span name;
359 : int nsId;
360 285048 : while (reader_.nextAttribute(&nsId, &name)) {
361 570096 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
362 285048 : && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
363 : {
364 285048 : if (!attrName.isEmpty()) {
365 : throw css::registry::InvalidRegistryException(
366 : (reader_.getUrl()
367 0 : + ": element has multiple \"name\" attributes"),
368 0 : css::uno::Reference< css::uno::XInterface >());
369 : }
370 285048 : attrName = reader_.getAttributeValue(false).convertFromUtf8();
371 285048 : if (attrName.isEmpty()) {
372 : throw css::registry::InvalidRegistryException(
373 0 : reader_.getUrl() + ": element has empty \"name\" attribute",
374 0 : css::uno::Reference< css::uno::XInterface >());
375 : }
376 : } else {
377 : throw css::registry::InvalidRegistryException(
378 0 : reader_.getUrl() + ": expected element attribute \"name\"",
379 0 : css::uno::Reference< css::uno::XInterface >());
380 : }
381 : }
382 285048 : if (attrName.isEmpty()) {
383 : throw css::registry::InvalidRegistryException(
384 0 : reader_.getUrl() + ": element is missing \"name\" attribute",
385 0 : css::uno::Reference< css::uno::XInterface >());
386 : }
387 285048 : return attrName;
388 : }
389 :
390 : class ContentEnumeration:
391 : public cppu::WeakImplHelper1< css::container::XEnumeration >,
392 : private boost::noncopyable
393 : {
394 : public:
395 805 : explicit ContentEnumeration(std::vector< css::uno::Any > const & factories):
396 805 : factories_(factories), iterator_(factories_.begin()) {}
397 :
398 : private:
399 1610 : virtual ~ContentEnumeration() {}
400 :
401 : virtual sal_Bool SAL_CALL hasMoreElements()
402 : throw (css::uno::RuntimeException);
403 :
404 : virtual css::uno::Any SAL_CALL nextElement()
405 : throw (
406 : css::container::NoSuchElementException,
407 : css::lang::WrappedTargetException, css::uno::RuntimeException);
408 :
409 : osl::Mutex mutex_;
410 : std::vector< css::uno::Any > factories_;
411 : std::vector< css::uno::Any >::const_iterator iterator_;
412 : };
413 :
414 2501 : sal_Bool ContentEnumeration::hasMoreElements()
415 : throw (css::uno::RuntimeException)
416 : {
417 2501 : osl::MutexGuard g(mutex_);
418 2501 : return iterator_ != factories_.end();
419 : }
420 :
421 1697 : css::uno::Any ContentEnumeration::nextElement()
422 : throw (
423 : css::container::NoSuchElementException,
424 : css::lang::WrappedTargetException, css::uno::RuntimeException)
425 : {
426 1697 : osl::MutexGuard g(mutex_);
427 1697 : if (iterator_ == factories_.end()) {
428 : throw css::container::NoSuchElementException(
429 : "Bootstrap service manager service enumerator has no more elements",
430 0 : static_cast< cppu::OWeakObject * >(this));
431 : }
432 1697 : return *iterator_++;
433 : }
434 :
435 1 : css::beans::Property getDefaultContextProperty() {
436 : return css::beans::Property(
437 : "DefaultContext", -1,
438 1 : cppu::UnoType< css::uno::XComponentContext >::get(),
439 1 : css::beans::PropertyAttribute::READONLY);
440 : }
441 :
442 : class FactoryWrapper:
443 : public cppu::WeakImplHelper3<
444 : css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
445 : css::lang::XServiceInfo >,
446 : private boost::noncopyable
447 : {
448 : public:
449 529 : FactoryWrapper(
450 : rtl::Reference< cppuhelper::ServiceManager > const & manager,
451 : boost::shared_ptr<
452 : cppuhelper::ServiceManager::Data::ImplementationInfo > const &
453 : info):
454 529 : manager_(manager), info_(info), loaded_(false)
455 529 : { assert(manager.is() && info.get() != 0); }
456 :
457 : private:
458 956 : virtual ~FactoryWrapper() {}
459 :
460 : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
461 : createInstanceWithContext(
462 : css::uno::Reference< css::uno::XComponentContext > const & Context)
463 : throw (css::uno::Exception, css::uno::RuntimeException);
464 :
465 : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
466 : createInstanceWithArgumentsAndContext(
467 : css::uno::Sequence< css::uno::Any > const & Arguments,
468 : css::uno::Reference< css::uno::XComponentContext > const & Context)
469 : throw (css::uno::Exception, css::uno::RuntimeException);
470 :
471 : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
472 : createInstance() throw (css::uno::Exception, css::uno::RuntimeException);
473 :
474 : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
475 : createInstanceWithArguments(
476 : css::uno::Sequence< css::uno::Any > const & Arguments)
477 : throw (css::uno::Exception, css::uno::RuntimeException);
478 :
479 : virtual rtl::OUString SAL_CALL getImplementationName()
480 : throw (css::uno::RuntimeException);
481 :
482 : virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
483 : throw (css::uno::RuntimeException);
484 :
485 : virtual css::uno::Sequence< rtl::OUString > SAL_CALL
486 : getSupportedServiceNames() throw (css::uno::RuntimeException);
487 :
488 : void loadImplementation(
489 : css::uno::Reference< css::uno::XComponentContext > const & context);
490 :
491 : rtl::Reference< cppuhelper::ServiceManager > manager_;
492 : boost::shared_ptr< cppuhelper::ServiceManager::Data::ImplementationInfo >
493 : info_;
494 :
495 : osl::Mutex mutex_;
496 : bool loaded_;
497 : css::uno::Reference< css::lang::XSingleComponentFactory > factory1_;
498 : css::uno::Reference< css::lang::XSingleServiceFactory > factory2_;
499 : };
500 :
501 : css::uno::Reference< css::uno::XInterface >
502 96 : FactoryWrapper::createInstanceWithContext(
503 : css::uno::Reference< css::uno::XComponentContext > const & Context)
504 : throw (css::uno::Exception, css::uno::RuntimeException)
505 : {
506 96 : loadImplementation(Context);
507 96 : return factory1_.is()
508 96 : ? factory1_->createInstanceWithContext(Context)
509 192 : : factory2_->createInstance();
510 : }
511 :
512 : css::uno::Reference< css::uno::XInterface >
513 1647 : FactoryWrapper::createInstanceWithArgumentsAndContext(
514 : css::uno::Sequence< css::uno::Any > const & Arguments,
515 : css::uno::Reference< css::uno::XComponentContext > const & Context)
516 : throw (css::uno::Exception, css::uno::RuntimeException)
517 : {
518 1647 : loadImplementation(Context);
519 1647 : return factory1_.is()
520 1647 : ? factory1_->createInstanceWithArgumentsAndContext(Arguments, Context)
521 3294 : : factory2_->createInstanceWithArguments(Arguments);
522 : }
523 :
524 0 : css::uno::Reference< css::uno::XInterface > FactoryWrapper::createInstance()
525 : throw (css::uno::Exception, css::uno::RuntimeException)
526 : {
527 0 : loadImplementation(manager_->getContext());
528 0 : return factory1_.is()
529 0 : ? factory1_->createInstanceWithContext(manager_->getContext())
530 0 : : factory2_->createInstance();
531 : }
532 :
533 : css::uno::Reference< css::uno::XInterface >
534 0 : FactoryWrapper::createInstanceWithArguments(
535 : css::uno::Sequence< css::uno::Any > const & Arguments)
536 : throw (css::uno::Exception, css::uno::RuntimeException)
537 : {
538 0 : loadImplementation(manager_->getContext());
539 0 : return factory1_.is()
540 0 : ? factory1_->createInstanceWithArgumentsAndContext(
541 0 : Arguments, manager_->getContext())
542 0 : : factory2_->createInstanceWithArguments(Arguments);
543 : }
544 :
545 1570 : rtl::OUString FactoryWrapper::getImplementationName()
546 : throw (css::uno::RuntimeException)
547 : {
548 1570 : return info_->name;
549 : }
550 :
551 0 : sal_Bool FactoryWrapper::supportsService(rtl::OUString const & ServiceName)
552 : throw (css::uno::RuntimeException)
553 : {
554 0 : return cppu::supportsService(this, ServiceName);
555 : }
556 :
557 36 : css::uno::Sequence< rtl::OUString > FactoryWrapper::getSupportedServiceNames()
558 : throw (css::uno::RuntimeException)
559 : {
560 36 : if (info_->services.size() > static_cast< sal_uInt32 >(SAL_MAX_INT32)) {
561 : throw css::uno::RuntimeException(
562 0 : "Implementation " + info_->name + " supports too many services",
563 0 : static_cast< cppu::OWeakObject * >(this));
564 : }
565 : css::uno::Sequence< rtl::OUString > names(
566 36 : static_cast< sal_Int32 >(info_->services.size()));
567 36 : sal_Int32 i = 0;
568 528 : for (std::vector< rtl::OUString >::const_iterator j(
569 36 : info_->services.begin());
570 352 : j != info_->services.end(); ++j)
571 : {
572 140 : names[i++] = *j;
573 : }
574 36 : return names;
575 : }
576 :
577 1743 : void FactoryWrapper::loadImplementation(
578 : css::uno::Reference< css::uno::XComponentContext > const & context)
579 : {
580 : {
581 1743 : osl::MutexGuard g(mutex_);
582 1743 : if (loaded_) {
583 3011 : return;
584 475 : }
585 : }
586 475 : css::uno::Reference< css::lang::XSingleComponentFactory > f1;
587 950 : css::uno::Reference< css::lang::XSingleServiceFactory > f2;
588 : //TODO: There is a race here, as the relevant service factory can already
589 : // have been removed and loading can thus fail, as the entity from which to
590 : // load can disappear once the service factory is removed:
591 475 : manager_->loadImplementation(context, info_, &f1, &f2);
592 475 : if (!(f1.is() || f2.is())) {
593 : throw css::uno::DeploymentException(
594 0 : "Implementation " + info_->name + " does not provide a factory",
595 0 : static_cast< cppu::OWeakObject * >(this));
596 : }
597 950 : osl::MutexGuard g(mutex_);
598 475 : if (!loaded_) {
599 475 : loaded_ = true;
600 475 : factory1_ = f1;
601 475 : factory2_ = f2;
602 475 : }
603 : }
604 :
605 : }
606 :
607 391 : void cppuhelper::ServiceManager::addSingletonContextEntries(
608 : std::vector< cppu::ContextEntry_Init > * entries) const
609 : {
610 : assert(entries != 0);
611 8310 : for (Data::ImplementationMap::const_iterator i(data_.singletons.begin());
612 5540 : i != data_.singletons.end(); ++i)
613 : {
614 : assert(!i->second.empty());
615 : assert(i->second[0].get() != 0);
616 : SAL_INFO_IF(
617 : i->second.size() > 1, "cppuhelper",
618 : "Arbitrarily chosing " << i->second[0]->info->name
619 : << " among multiple implementations for " << i->first);
620 : entries->push_back(
621 : cppu::ContextEntry_Init(
622 4758 : "/singletons/" + i->first,
623 7137 : css::uno::makeAny(i->second[0]->info->name), true));
624 : }
625 391 : }
626 :
627 9445 : void cppuhelper::ServiceManager::loadImplementation(
628 : css::uno::Reference< css::uno::XComponentContext > const & context,
629 : boost::shared_ptr< Data::ImplementationInfo > const & info,
630 : css::uno::Reference< css::lang::XSingleComponentFactory > * factory1,
631 : css::uno::Reference< css::lang::XSingleServiceFactory > * factory2)
632 : {
633 : assert(
634 : info.get() != 0 && factory1 != 0 && !factory1->is() && factory2 != 0
635 : && !factory2->is());
636 9445 : rtl::OUString uri;
637 : try {
638 9445 : uri = cppu::bootstrap_expandUri(info->uri);
639 0 : } catch (css::lang::IllegalArgumentException & e) {
640 : throw css::uno::DeploymentException(
641 0 : "Cannot expand URI" + info->uri + ": " + e.Message,
642 0 : static_cast< cppu::OWeakObject * >(this));
643 : }
644 18890 : css::uno::Reference< css::uno::XInterface > f0;
645 : // Shortcut loading via SharedLibrary loader, to pass in prefix argument
646 : // (which the loader's activate implementation would normally obtain through
647 : // the legacy xKey argument):
648 18890 : if (!info->alienContext.is()
649 9445 : && info->loader == "com.sun.star.loader.SharedLibrary")
650 : {
651 9444 : rtl::OUString prefix(info->prefix);
652 9444 : if (!prefix.isEmpty()) {
653 9440 : prefix += "_";
654 : }
655 28332 : f0 = cppu::loadSharedLibComponentFactory(
656 9444 : uri, rtl::OUString(), info->name, this,
657 18888 : css::uno::Reference< css::registry::XRegistryKey >(), prefix);
658 : } else {
659 : SAL_INFO_IF(
660 : !info->prefix.isEmpty(), "cppuhelper",
661 : "Loader " << info->loader << " and non-empty prefix "
662 : << info->prefix);
663 1 : css::uno::Reference< css::uno::XComponentContext > ctxt;
664 2 : css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
665 1 : if (info->alienContext.is()) {
666 0 : ctxt = info->alienContext;
667 0 : smgr = css::uno::Reference< css::lang::XMultiComponentFactory >(
668 0 : ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
669 : } else {
670 : assert(context.is());
671 1 : ctxt = context;
672 1 : smgr = this;
673 : }
674 : css::uno::Reference< css::loader::XImplementationLoader > loader(
675 1 : smgr->createInstanceWithContext(info->loader, ctxt),
676 2 : css::uno::UNO_QUERY_THROW);
677 4 : f0 = loader->activate(
678 1 : info->name, rtl::OUString(), uri,
679 3 : css::uno::Reference< css::registry::XRegistryKey >());
680 : }
681 9445 : factory1->set(f0, css::uno::UNO_QUERY);
682 9445 : if (!factory1->is()) {
683 113 : factory2->set(f0, css::uno::UNO_QUERY);
684 9445 : }
685 9445 : }
686 :
687 166 : void cppuhelper::ServiceManager::disposing() {
688 166 : std::vector< css::uno::Reference< css::lang::XComponent > > comps;
689 332 : Data clear;
690 : {
691 166 : osl::MutexGuard g(rBHelper.rMutex);
692 1704 : for (Data::DynamicImplementations::const_iterator i(
693 166 : data_.dynamicImplementations.begin());
694 1136 : i != data_.dynamicImplementations.end(); ++i)
695 : {
696 : assert(i->second.get() != 0);
697 402 : if (i->second->component.is()) {
698 402 : comps.push_back(i->second->component);
699 : }
700 : }
701 166 : data_.namedImplementations.swap(clear.namedImplementations);
702 166 : data_.dynamicImplementations.swap(clear.dynamicImplementations);
703 166 : data_.services.swap(clear.services);
704 166 : data_.singletons.swap(clear.singletons);
705 : }
706 1704 : for (std::vector<
707 : css::uno::Reference< css::lang::XComponent > >::const_iterator i(
708 166 : comps.begin());
709 1136 : i != comps.end(); ++i)
710 : {
711 402 : removeEventListenerFromComponent(*i);
712 166 : }
713 166 : }
714 :
715 0 : rtl::OUString cppuhelper::ServiceManager::getImplementationName()
716 : throw (css::uno::RuntimeException)
717 : {
718 : return rtl::OUString(
719 0 : "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager");
720 : }
721 :
722 0 : sal_Bool cppuhelper::ServiceManager::supportsService(
723 : rtl::OUString const & ServiceName)
724 : throw (css::uno::RuntimeException)
725 : {
726 0 : return cppu::supportsService(this, ServiceName);
727 : }
728 :
729 : css::uno::Sequence< rtl::OUString >
730 0 : cppuhelper::ServiceManager::getSupportedServiceNames()
731 : throw (css::uno::RuntimeException)
732 : {
733 0 : css::uno::Sequence< rtl::OUString > names(2);
734 0 : names[0] = "com.sun.star.lang.MultiServiceFactory";
735 0 : names[1] = "com.sun.star.lang.ServiceManager";
736 0 : return names;
737 : }
738 :
739 : css::uno::Reference< css::uno::XInterface >
740 19360 : cppuhelper::ServiceManager::createInstance(
741 : rtl::OUString const & aServiceSpecifier)
742 : throw (css::uno::Exception, css::uno::RuntimeException)
743 : {
744 : assert(context_.is());
745 19360 : return createInstanceWithContext(aServiceSpecifier, context_);
746 : }
747 :
748 : css::uno::Reference< css::uno::XInterface >
749 505 : cppuhelper::ServiceManager::createInstanceWithArguments(
750 : rtl::OUString const & ServiceSpecifier,
751 : css::uno::Sequence< css::uno::Any > const & Arguments)
752 : throw (css::uno::Exception, css::uno::RuntimeException)
753 : {
754 : assert(context_.is());
755 : return createInstanceWithArgumentsAndContext(
756 505 : ServiceSpecifier, Arguments, context_);
757 : }
758 :
759 : css::uno::Sequence< rtl::OUString >
760 0 : cppuhelper::ServiceManager::getAvailableServiceNames()
761 : throw (css::uno::RuntimeException)
762 : {
763 0 : osl::MutexGuard g(rBHelper.rMutex);
764 0 : if (isDisposed()) {
765 0 : return css::uno::Sequence< rtl::OUString >();
766 : }
767 0 : Data::ImplementationMap::size_type n = data_.services.size();
768 0 : if (n > static_cast< sal_uInt32 >(SAL_MAX_INT32)) {
769 : throw css::uno::RuntimeException(
770 : "getAvailableServiceNames: too many services",
771 0 : static_cast< cppu::OWeakObject * >(this));
772 : }
773 0 : css::uno::Sequence< rtl::OUString > names(static_cast< sal_Int32 >(n));
774 0 : sal_Int32 i = 0;
775 0 : for (Data::ImplementationMap::const_iterator j(data_.services.begin());
776 0 : j != data_.services.end(); ++j)
777 : {
778 0 : names[i++] = j->first;
779 : }
780 : assert(i == names.getLength());
781 0 : return names;
782 : }
783 :
784 : css::uno::Reference< css::uno::XInterface >
785 637902 : cppuhelper::ServiceManager::createInstanceWithContext(
786 : rtl::OUString const & aServiceSpecifier,
787 : css::uno::Reference< css::uno::XComponentContext > const & Context)
788 : throw (css::uno::Exception, css::uno::RuntimeException)
789 : {
790 : boost::shared_ptr< Data::Implementation > impl(
791 637902 : findServiceImplementation(Context, aServiceSpecifier));
792 637902 : if (impl.get() == 0) {
793 52103 : return css::uno::Reference< css::uno::XInterface >();
794 : }
795 585799 : if (impl->factory1.is()) {
796 584551 : return impl->factory1->createInstanceWithContext(Context);
797 : }
798 1248 : if (impl->factory2.is()) {
799 1248 : return impl->factory2->createInstance();
800 : }
801 : throw css::uno::DeploymentException(
802 0 : "Implementation " + impl->info->name + " does not provide a factory",
803 0 : static_cast< cppu::OWeakObject * >(this));
804 : }
805 :
806 : css::uno::Reference< css::uno::XInterface >
807 121419 : cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
808 : rtl::OUString const & ServiceSpecifier,
809 : css::uno::Sequence< css::uno::Any > const & Arguments,
810 : css::uno::Reference< css::uno::XComponentContext > const & Context)
811 : throw (css::uno::Exception, css::uno::RuntimeException)
812 : {
813 : boost::shared_ptr< Data::Implementation > impl(
814 121419 : findServiceImplementation(Context, ServiceSpecifier));
815 121419 : if (impl.get() == 0) {
816 9423 : return css::uno::Reference< css::uno::XInterface >();
817 : }
818 111996 : if (impl->factory1.is()) {
819 111211 : return impl->factory1->createInstanceWithArgumentsAndContext(
820 111211 : Arguments, Context);
821 : }
822 785 : if (impl->factory2.is()) {
823 785 : return impl->factory2->createInstanceWithArguments(Arguments);
824 : }
825 : throw css::uno::DeploymentException(
826 0 : "Implementation " + impl->info->name + " does not provide a factory",
827 0 : static_cast< cppu::OWeakObject * >(this));
828 : }
829 :
830 0 : css::uno::Type cppuhelper::ServiceManager::getElementType()
831 : throw (css::uno::RuntimeException)
832 : {
833 0 : return css::uno::Type();
834 : }
835 :
836 0 : sal_Bool cppuhelper::ServiceManager::hasElements()
837 : throw (css::uno::RuntimeException)
838 : {
839 0 : osl::MutexGuard g(rBHelper.rMutex);
840 : return
841 0 : !(data_.namedImplementations.empty()
842 0 : && data_.dynamicImplementations.empty());
843 : }
844 :
845 : css::uno::Reference< css::container::XEnumeration >
846 0 : cppuhelper::ServiceManager::createEnumeration()
847 : throw (css::uno::RuntimeException)
848 : {
849 : throw css::uno::RuntimeException(
850 : "ServiceManager createEnumeration: method not supported",
851 0 : static_cast< cppu::OWeakObject * >(this));
852 : }
853 :
854 0 : sal_Bool cppuhelper::ServiceManager::has(css::uno::Any const &)
855 : throw (css::uno::RuntimeException)
856 : {
857 : throw css::uno::RuntimeException(
858 : "ServiceManager has: method not supported",
859 0 : static_cast< cppu::OWeakObject * >(this));
860 : }
861 :
862 415 : void cppuhelper::ServiceManager::insert(css::uno::Any const & aElement)
863 : throw (
864 : css::lang::IllegalArgumentException,
865 : css::container::ElementExistException, css::uno::RuntimeException)
866 : {
867 415 : css::uno::Sequence< css::beans::NamedValue > args;
868 415 : if (aElement >>= args) {
869 0 : std::vector< rtl::OUString > uris;
870 0 : css::uno::Reference< css::uno::XComponentContext > alienContext;
871 0 : for (sal_Int32 i = 0; i < args.getLength(); ++i) {
872 0 : if (args[i].Name == "uri") {
873 0 : rtl::OUString uri;
874 0 : if (!(args[i].Value >>= uri)) {
875 : throw css::lang::IllegalArgumentException(
876 : "Bad uri argument",
877 0 : static_cast< cppu::OWeakObject * >(this), 0);
878 : }
879 0 : uris.push_back(uri);
880 0 : } else if (args[i].Name == "component-context") {
881 0 : if (alienContext.is()) {
882 : throw css::lang::IllegalArgumentException(
883 : "Multiple component-context arguments",
884 0 : static_cast< cppu::OWeakObject * >(this), 0);
885 : }
886 0 : if (!(args[i].Value >>= alienContext) || !alienContext.is()) {
887 : throw css::lang::IllegalArgumentException(
888 : "Bad component-context argument",
889 0 : static_cast< cppu::OWeakObject * >(this), 0);
890 : }
891 : } else {
892 : throw css::lang::IllegalArgumentException(
893 0 : "Bad argument " + args[i].Name,
894 0 : static_cast< cppu::OWeakObject * >(this), 0);
895 : }
896 : }
897 0 : insertRdbFiles(uris, alienContext);
898 0 : return;
899 : }
900 830 : css::uno::Reference< css::lang::XServiceInfo > info;
901 415 : if ((aElement >>= info) && info.is()) {
902 415 : insertLegacyFactory(info);
903 415 : return;
904 : }
905 : // At least revisions up to 1.7 of LanguageTool.oxt (incl. the bundled 1.4.0 in
906 : // module languagetool) contain an (actively registered) factory that does not
907 : // implement XServiceInfo (see <http://sourceforge.net/tracker/?
908 : // func=detail&aid=3526635&group_id=110216&atid=655717> "SingletonFactory should
909 : // implement XServiceInfo"); the old OServiceManager::insert
910 : // (stoc/source/servicemanager/servicemanager.cxx) silently did not add such
911 : // broken factories to its m_ImplementationNameMap, so ignore them here for
912 : // backwards compatibility of live-insertion of extensions, too.
913 :
914 : // (The plan was that this warning would go away (and we would do the
915 : // throw instead) for the incompatible LO 4, but we changed our mind):
916 0 : css::uno::Reference< css::lang::XSingleComponentFactory > legacy;
917 0 : if ((aElement >>= legacy) && legacy.is()) {
918 : SAL_WARN(
919 : "cppuhelper",
920 : "Ignored XSingleComponentFactory not implementing XServiceInfo");
921 0 : return;
922 : }
923 :
924 : throw css::lang::IllegalArgumentException(
925 415 : "Bad insert element", static_cast< cppu::OWeakObject * >(this), 0);
926 : }
927 :
928 1 : void cppuhelper::ServiceManager::remove(css::uno::Any const & aElement)
929 : throw (
930 : css::lang::IllegalArgumentException,
931 : css::container::NoSuchElementException, css::uno::RuntimeException)
932 : {
933 1 : css::uno::Sequence< css::beans::NamedValue > args;
934 1 : if (aElement >>= args) {
935 0 : std::vector< rtl::OUString > uris;
936 0 : for (sal_Int32 i = 0; i < args.getLength(); ++i) {
937 0 : if (args[i].Name == "uri") {
938 0 : rtl::OUString uri;
939 0 : if (!(args[i].Value >>= uri)) {
940 : throw css::lang::IllegalArgumentException(
941 : "Bad uri argument",
942 0 : static_cast< cppu::OWeakObject * >(this), 0);
943 : }
944 0 : uris.push_back(uri);
945 : } else {
946 : throw css::lang::IllegalArgumentException(
947 0 : "Bad argument " + args[i].Name,
948 0 : static_cast< cppu::OWeakObject * >(this), 0);
949 : }
950 : }
951 0 : removeRdbFiles(uris);
952 0 : return;
953 : }
954 2 : css::uno::Reference< css::lang::XServiceInfo > info;
955 1 : if ((aElement >>= info) && info.is()) {
956 0 : if (!removeLegacyFactory(info, true)) {
957 : throw css::container::NoSuchElementException(
958 : "Remove non-inserted factory object",
959 0 : static_cast< cppu::OWeakObject * >(this));
960 : }
961 0 : return;
962 : }
963 2 : rtl::OUString impl;
964 1 : if (aElement >>= impl) {
965 : // For live-removal of extensions:
966 1 : removeImplementation(impl);
967 1 : return;
968 : }
969 : throw css::lang::IllegalArgumentException(
970 1 : "Bad remove element", static_cast< cppu::OWeakObject * >(this), 0);
971 : }
972 :
973 : css::uno::Reference< css::container::XEnumeration >
974 805 : cppuhelper::ServiceManager::createContentEnumeration(
975 : rtl::OUString const & aServiceName)
976 : throw (css::uno::RuntimeException)
977 : {
978 805 : std::vector< boost::shared_ptr< Data::Implementation > > impls;
979 : {
980 805 : osl::MutexGuard g(rBHelper.rMutex);
981 : Data::ImplementationMap::const_iterator i(
982 805 : data_.services.find(aServiceName));
983 805 : if (i != data_.services.end()) {
984 366 : impls = i->second;
985 805 : }
986 : }
987 1610 : std::vector< css::uno::Any > factories;
988 7521 : for (std::vector<
989 : boost::shared_ptr< Data::Implementation > >::const_iterator i(
990 805 : impls.begin());
991 5014 : i != impls.end(); ++i)
992 : {
993 1702 : Data::Implementation * impl = i->get();
994 : assert(impl != 0);
995 : {
996 1702 : osl::MutexGuard g(rBHelper.rMutex);
997 1702 : if (isDisposed()) {
998 0 : factories.clear();
999 0 : break;
1000 : }
1001 1702 : if (!impl->loaded) {
1002 : // Postpone actual factory instantiation as long as possible (so
1003 : // that e.g. opening LO's "Tools - Macros" menu does not try to
1004 : // instantiate a JVM, which can lead to a synchronous error
1005 : // dialog when no JVM is specified, and showing the dialog while
1006 : // hovering over a menu can cause trouble):
1007 529 : impl->factory1 = new FactoryWrapper(this, impl->info);
1008 529 : impl->loaded = true;
1009 1702 : }
1010 : }
1011 1702 : if (impl->factory1.is()) {
1012 1702 : factories.push_back(css::uno::makeAny(impl->factory1));
1013 0 : } else if (impl->factory2.is()) {
1014 0 : factories.push_back(css::uno::makeAny(impl->factory2));
1015 : } else {
1016 : throw css::uno::DeploymentException(
1017 0 : ("Implementation " + impl->info->name
1018 0 : + " does not provide a factory"),
1019 0 : static_cast< cppu::OWeakObject * >(this));
1020 : }
1021 : }
1022 1610 : return new ContentEnumeration(factories);
1023 : }
1024 :
1025 : css::uno::Reference< css::beans::XPropertySetInfo >
1026 6 : cppuhelper::ServiceManager::getPropertySetInfo()
1027 : throw (css::uno::RuntimeException)
1028 : {
1029 6 : return this;
1030 : }
1031 :
1032 0 : void cppuhelper::ServiceManager::setPropertyValue(
1033 : rtl::OUString const & aPropertyName, css::uno::Any const &)
1034 : throw (
1035 : css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
1036 : css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
1037 : css::uno::RuntimeException)
1038 : {
1039 0 : if (aPropertyName == "DefaultContext") {
1040 : throw css::beans::PropertyVetoException(
1041 0 : aPropertyName, static_cast< cppu::OWeakObject * >(this));
1042 : } else {
1043 : throw css::beans::UnknownPropertyException(
1044 0 : aPropertyName, static_cast< cppu::OWeakObject * >(this));
1045 : }
1046 : }
1047 :
1048 735610 : css::uno::Any cppuhelper::ServiceManager::getPropertyValue(
1049 : rtl::OUString const & PropertyName)
1050 : throw (
1051 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1052 : css::uno::RuntimeException)
1053 : {
1054 735610 : if (PropertyName != "DefaultContext") {
1055 : throw css::beans::UnknownPropertyException(
1056 0 : PropertyName, static_cast< cppu::OWeakObject * >(this));
1057 : }
1058 : assert(context_.is());
1059 735610 : return css::uno::makeAny(context_);
1060 : }
1061 :
1062 0 : void cppuhelper::ServiceManager::addPropertyChangeListener(
1063 : rtl::OUString const & aPropertyName,
1064 : css::uno::Reference< css::beans::XPropertyChangeListener > const &
1065 : xListener)
1066 : throw (
1067 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1068 : css::uno::RuntimeException)
1069 : {
1070 0 : if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1071 : throw css::beans::UnknownPropertyException(
1072 0 : aPropertyName, static_cast< cppu::OWeakObject * >(this));
1073 : }
1074 : // DefaultContext does not change, so just treat it as an event listener:
1075 0 : return addEventListener(xListener.get());
1076 : }
1077 :
1078 0 : void cppuhelper::ServiceManager::removePropertyChangeListener(
1079 : rtl::OUString const & aPropertyName,
1080 : css::uno::Reference< css::beans::XPropertyChangeListener > const &
1081 : aListener)
1082 : throw (
1083 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1084 : css::uno::RuntimeException)
1085 : {
1086 0 : if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
1087 : throw css::beans::UnknownPropertyException(
1088 0 : aPropertyName, static_cast< cppu::OWeakObject * >(this));
1089 : }
1090 : // DefaultContext does not change, so just treat it as an event listener:
1091 0 : return removeEventListener(aListener.get());
1092 : }
1093 :
1094 0 : void cppuhelper::ServiceManager::addVetoableChangeListener(
1095 : rtl::OUString const & PropertyName,
1096 : css::uno::Reference< css::beans::XVetoableChangeListener > const &
1097 : aListener)
1098 : throw (
1099 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1100 : css::uno::RuntimeException)
1101 : {
1102 0 : if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1103 : throw css::beans::UnknownPropertyException(
1104 0 : PropertyName, static_cast< cppu::OWeakObject * >(this));
1105 : }
1106 : // DefaultContext does not change, so just treat it as an event listener:
1107 0 : return addEventListener(aListener.get());
1108 : }
1109 :
1110 0 : void cppuhelper::ServiceManager::removeVetoableChangeListener(
1111 : rtl::OUString const & PropertyName,
1112 : css::uno::Reference< css::beans::XVetoableChangeListener > const &
1113 : aListener)
1114 : throw (
1115 : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1116 : css::uno::RuntimeException)
1117 : {
1118 0 : if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
1119 : throw css::beans::UnknownPropertyException(
1120 0 : PropertyName, static_cast< cppu::OWeakObject * >(this));
1121 : }
1122 : // DefaultContext does not change, so just treat it as an event listener:
1123 0 : return removeEventListener(aListener.get());
1124 : }
1125 :
1126 : css::uno::Sequence< css::beans::Property >
1127 1 : cppuhelper::ServiceManager::getProperties() throw (css::uno::RuntimeException) {
1128 1 : css::uno::Sequence< css::beans::Property > props(1);
1129 1 : props[0] = getDefaultContextProperty();
1130 1 : return props;
1131 : }
1132 :
1133 0 : css::beans::Property cppuhelper::ServiceManager::getPropertyByName(
1134 : rtl::OUString const & aName)
1135 : throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
1136 : {
1137 0 : if (aName != "DefaultContext") {
1138 : throw css::beans::UnknownPropertyException(
1139 0 : aName, static_cast< cppu::OWeakObject * >(this));
1140 : }
1141 0 : return getDefaultContextProperty();
1142 : }
1143 :
1144 0 : sal_Bool cppuhelper::ServiceManager::hasPropertyByName(
1145 : rtl::OUString const & Name)
1146 : throw (css::uno::RuntimeException)
1147 : {
1148 0 : return Name == "DefaultContext";
1149 : }
1150 :
1151 6 : void cppuhelper::ServiceManager::disposing(
1152 : css::lang::EventObject const & Source)
1153 : throw (css::uno::RuntimeException)
1154 : {
1155 : removeLegacyFactory(
1156 : css::uno::Reference< css::lang::XServiceInfo >(
1157 : Source.Source, css::uno::UNO_QUERY_THROW),
1158 6 : false);
1159 6 : }
1160 :
1161 402 : void cppuhelper::ServiceManager::removeEventListenerFromComponent(
1162 : css::uno::Reference< css::lang::XComponent > const & component)
1163 : {
1164 : assert(component.is());
1165 : try {
1166 402 : component->removeEventListener(this);
1167 0 : } catch (css::uno::RuntimeException & e) {
1168 : SAL_INFO(
1169 : "cppuhelper",
1170 : "Ignored removeEventListener RuntimeException " + e.Message);
1171 : }
1172 402 : }
1173 :
1174 391 : void cppuhelper::ServiceManager::readRdbs(rtl::OUString const & uris) {
1175 3302 : for (sal_Int32 i = 0; i != -1;) {
1176 2520 : rtl::OUString uri(uris.getToken(0, ' ', i));
1177 2520 : if (uri.isEmpty()) {
1178 378 : continue;
1179 : }
1180 : bool optional;
1181 : bool directory;
1182 2142 : cppu::decodeRdbUri(&uri, &optional, &directory);
1183 2142 : if (directory) {
1184 85 : readRdbDirectory(uri, optional);
1185 : } else {
1186 2057 : readRdbFile(uri, optional);
1187 : }
1188 2142 : }
1189 391 : }
1190 :
1191 85 : void cppuhelper::ServiceManager::readRdbDirectory(
1192 : rtl::OUString const & uri, bool optional)
1193 : {
1194 85 : osl::Directory dir(uri);
1195 85 : switch (dir.open()) {
1196 : case osl::FileBase::E_None:
1197 85 : break;
1198 : case osl::FileBase::E_NOENT:
1199 0 : if (optional) {
1200 : SAL_INFO("cppuhelper", "Ignored optional " << uri);
1201 85 : return;
1202 : }
1203 : // fall through
1204 : default:
1205 : throw css::uno::DeploymentException(
1206 0 : "Cannot open directory " + uri,
1207 0 : static_cast< cppu::OWeakObject * >(this));
1208 : }
1209 : for (;;) {
1210 595 : rtl::OUString url;
1211 595 : if (!cppu::nextDirectoryItem(dir, &url)) {
1212 85 : break;
1213 : }
1214 510 : readRdbFile(url, false);
1215 510 : }
1216 : }
1217 :
1218 2567 : void cppuhelper::ServiceManager::readRdbFile(
1219 : rtl::OUString const & uri, bool optional)
1220 : {
1221 : try {
1222 : Parser(
1223 2569 : uri, css::uno::Reference< css::uno::XComponentContext >(), &data_);
1224 0 : } catch (css::container::NoSuchElementException &) {
1225 0 : if (!optional) {
1226 : throw css::uno::DeploymentException(
1227 0 : uri + ": no such file",
1228 0 : static_cast< cppu::OWeakObject * >(this));
1229 : }
1230 : SAL_INFO("cppuhelper", "Ignored optional " << uri);
1231 0 : } catch (css::registry::InvalidRegistryException & e) {
1232 0 : if (!readLegacyRdbFile(uri)) {
1233 : throw css::uno::DeploymentException(
1234 0 : "InvalidRegistryException: " + e.Message,
1235 0 : static_cast< cppu::OWeakObject * >(this));
1236 : }
1237 4 : } catch (css::uno::RuntimeException &) {
1238 2 : if (!readLegacyRdbFile(uri)) {
1239 0 : throw;
1240 : }
1241 : }
1242 2567 : }
1243 :
1244 2 : bool cppuhelper::ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) {
1245 2 : Registry reg;
1246 2 : switch (reg.open(uri, REG_READONLY)) {
1247 : case REG_NO_ERROR:
1248 0 : break;
1249 : case REG_REGISTRY_NOT_EXISTS:
1250 : case REG_INVALID_REGISTRY:
1251 : {
1252 : // Ignore empty rdb files (which are at least seen by subordinate
1253 : // uno processes during extension registration; Registry::open can
1254 : // fail on them if mmap(2) returns EINVAL for a zero length):
1255 2 : osl::DirectoryItem item;
1256 2 : if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
1257 2 : osl::FileStatus status(osl_FileStatus_Mask_FileSize);
1258 4 : if (item.getFileStatus(status) == osl::FileBase::E_None
1259 2 : && status.getFileSize() == 0)
1260 : {
1261 2 : return true;
1262 0 : }
1263 0 : }
1264 : }
1265 : // fall through
1266 : default:
1267 0 : return false;
1268 : }
1269 0 : RegistryKey rootKey;
1270 0 : if (reg.openRootKey(rootKey) != REG_NO_ERROR) {
1271 : throw css::uno::DeploymentException(
1272 0 : "Failure reading legacy rdb file " + uri,
1273 0 : static_cast< cppu::OWeakObject * >(this));
1274 : }
1275 0 : RegistryKeyArray impls;
1276 0 : switch (rootKey.openSubKeys("IMPLEMENTATIONS", impls)) {
1277 : case REG_NO_ERROR:
1278 0 : break;
1279 : case REG_KEY_NOT_EXISTS:
1280 0 : return true;
1281 : default:
1282 : throw css::uno::DeploymentException(
1283 0 : "Failure reading legacy rdb file " + uri,
1284 0 : static_cast< cppu::OWeakObject * >(this));
1285 : }
1286 0 : for (sal_uInt32 i = 0; i != impls.getLength(); ++i) {
1287 0 : RegistryKey implKey(impls.getElement(i));
1288 : assert(implKey.getName().match("/IMPLEMENTATIONS/"));
1289 : rtl::OUString name(
1290 0 : implKey.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1291 : boost::shared_ptr< Data::Implementation > impl(
1292 : new Data::Implementation(
1293 : name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"),
1294 : readLegacyRdbString(uri, implKey, "UNO/LOCATION"),
1295 : rtl::OUString(),
1296 0 : css::uno::Reference< css::uno::XComponentContext >(), uri));
1297 0 : if (!data_.namedImplementations.insert(
1298 0 : Data::NamedImplementations::value_type(name, impl)).
1299 0 : second)
1300 : {
1301 : throw css::registry::InvalidRegistryException(
1302 0 : uri + ": duplicate <implementation name=\"" + name + "\">",
1303 0 : css::uno::Reference< css::uno::XInterface >());
1304 : }
1305 : readLegacyRdbStrings(
1306 0 : uri, implKey, "UNO/SERVICES", &impl->info->services);
1307 0 : for (std::vector< rtl::OUString >::const_iterator j(
1308 0 : impl->info->services.begin());
1309 0 : j != impl->info->services.end(); ++j)
1310 : {
1311 0 : data_.services[*j].push_back(impl);
1312 : }
1313 : readLegacyRdbStrings(
1314 0 : uri, implKey, "UNO/SINGLETONS", &impl->info->singletons);
1315 0 : for (std::vector< rtl::OUString >::const_iterator j(
1316 0 : impl->info->singletons.begin());
1317 0 : j != impl->info->singletons.end(); ++j)
1318 : {
1319 0 : data_.singletons[*j].push_back(impl);
1320 : }
1321 0 : }
1322 0 : return true;
1323 : }
1324 :
1325 0 : rtl::OUString cppuhelper::ServiceManager::readLegacyRdbString(
1326 : rtl::OUString const & uri, RegistryKey & key, rtl::OUString const & path)
1327 : {
1328 0 : RegistryKey subkey;
1329 : RegValueType t;
1330 0 : sal_uInt32 s(0);
1331 0 : if (key.openKey(path, subkey) != REG_NO_ERROR
1332 0 : || subkey.getValueInfo(rtl::OUString(), &t, &s) != REG_NO_ERROR
1333 0 : || t != RG_VALUETYPE_STRING
1334 0 : || s == 0 || s > static_cast< sal_uInt32 >(SAL_MAX_INT32))
1335 : {
1336 : throw css::uno::DeploymentException(
1337 0 : "Failure reading legacy rdb file " + uri,
1338 0 : static_cast< cppu::OWeakObject * >(this));
1339 : }
1340 0 : rtl::OUString val;
1341 0 : std::vector< char > v(s); // assuming sal_uInt32 fits into vector::size_type
1342 0 : if (subkey.getValue(rtl::OUString(), &v[0]) != REG_NO_ERROR
1343 0 : || v.back() != '\0'
1344 0 : || !rtl_convertStringToUString(
1345 0 : &val.pData, &v[0], static_cast< sal_Int32 >(s - 1),
1346 : RTL_TEXTENCODING_UTF8,
1347 : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1348 : | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1349 0 : | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
1350 : {
1351 : throw css::uno::DeploymentException(
1352 0 : "Failure reading legacy rdb file " + uri,
1353 0 : static_cast< cppu::OWeakObject * >(this));
1354 : }
1355 0 : return val;
1356 : }
1357 :
1358 0 : void cppuhelper::ServiceManager::readLegacyRdbStrings(
1359 : rtl::OUString const & uri, RegistryKey & key, rtl::OUString const & path,
1360 : std::vector< rtl::OUString > * strings)
1361 : {
1362 : assert(strings != 0);
1363 0 : RegistryKey subkey;
1364 0 : switch (key.openKey(path, subkey)) {
1365 : case REG_NO_ERROR:
1366 0 : break;
1367 : case REG_KEY_NOT_EXISTS:
1368 0 : return;
1369 : default:
1370 : throw css::uno::DeploymentException(
1371 0 : "Failure reading legacy rdb file " + uri,
1372 0 : static_cast< cppu::OWeakObject * >(this));
1373 : }
1374 0 : rtl::OUString prefix(subkey.getName() + "/");
1375 0 : RegistryKeyNames names;
1376 0 : if (subkey.getKeyNames(rtl::OUString(), names) != REG_NO_ERROR) {
1377 : throw css::uno::DeploymentException(
1378 0 : "Failure reading legacy rdb file " + uri,
1379 0 : static_cast< cppu::OWeakObject * >(this));
1380 : }
1381 0 : for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
1382 : assert(names.getElement(i).match(prefix));
1383 0 : strings->push_back(names.getElement(i).copy(prefix.getLength()));
1384 0 : }
1385 : }
1386 :
1387 0 : void cppuhelper::ServiceManager::insertRdbFiles(
1388 : std::vector< rtl::OUString > const & uris,
1389 : css::uno::Reference< css::uno::XComponentContext > const & alienContext)
1390 : {
1391 0 : Data extra;
1392 0 : for (std::vector< rtl::OUString >::const_iterator i(uris.begin());
1393 0 : i != uris.end(); ++i)
1394 : {
1395 : try {
1396 0 : Parser(*i, alienContext, &extra);
1397 0 : } catch (css::container::NoSuchElementException &) {
1398 : throw css::lang::IllegalArgumentException(
1399 0 : *i + ": no such file", static_cast< cppu::OWeakObject * >(this),
1400 0 : 0);
1401 0 : } catch (css::registry::InvalidRegistryException & e) {
1402 : throw css::lang::IllegalArgumentException(
1403 0 : "InvalidRegistryException: " + e.Message,
1404 0 : static_cast< cppu::OWeakObject * >(this), 0);
1405 : }
1406 : }
1407 0 : insertExtraData(extra);
1408 0 : }
1409 :
1410 415 : void cppuhelper::ServiceManager::insertLegacyFactory(
1411 : css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo)
1412 : {
1413 : assert(factoryInfo.is());
1414 415 : rtl::OUString name(factoryInfo->getImplementationName());
1415 : css::uno::Reference< css::lang::XSingleComponentFactory > f1(
1416 830 : factoryInfo, css::uno::UNO_QUERY);
1417 830 : css::uno::Reference< css::lang::XSingleServiceFactory > f2;
1418 415 : if (!f1.is()) {
1419 0 : f2 = css::uno::Reference< css::lang::XSingleServiceFactory >(
1420 0 : factoryInfo, css::uno::UNO_QUERY);
1421 : }
1422 : css::uno::Reference< css::lang::XComponent > comp(
1423 830 : factoryInfo, css::uno::UNO_QUERY);
1424 : boost::shared_ptr< Data::Implementation > impl(
1425 830 : new Data::Implementation(name, f1, f2, comp));
1426 830 : Data extra;
1427 415 : if (!name.isEmpty()) {
1428 : extra.namedImplementations.insert(
1429 75 : Data::NamedImplementations::value_type(name, impl));
1430 : }
1431 : extra.dynamicImplementations.insert(
1432 415 : Data::DynamicImplementations::value_type(factoryInfo, impl));
1433 : css::uno::Sequence< rtl::OUString > services(
1434 830 : factoryInfo->getSupportedServiceNames());
1435 830 : for (sal_Int32 i = 0; i != services.getLength(); ++i) {
1436 415 : impl->info->services.push_back(services[i]);
1437 415 : extra.services[services[i]].push_back(impl);
1438 : }
1439 415 : if (insertExtraData(extra) && comp.is()) {
1440 415 : comp->addEventListener(this);
1441 415 : }
1442 415 : }
1443 :
1444 415 : bool cppuhelper::ServiceManager::insertExtraData(Data const & extra) {
1445 : {
1446 415 : osl::MutexGuard g(rBHelper.rMutex);
1447 415 : if (isDisposed()) {
1448 0 : return false;
1449 : }
1450 1470 : for (Data::NamedImplementations::const_iterator i(
1451 415 : extra.namedImplementations.begin());
1452 980 : i != extra.namedImplementations.end(); ++i)
1453 : {
1454 225 : if (data_.namedImplementations.find(i->first)
1455 225 : != data_.namedImplementations.end())
1456 : {
1457 : throw css::lang::IllegalArgumentException(
1458 0 : "Insert duplicate implementation name " + i->first,
1459 0 : static_cast< cppu::OWeakObject * >(this), 0);
1460 : }
1461 : }
1462 2490 : for (Data::DynamicImplementations::const_iterator i(
1463 415 : extra.dynamicImplementations.begin());
1464 1660 : i != extra.dynamicImplementations.end(); ++i)
1465 : {
1466 1245 : if (data_.dynamicImplementations.find(i->first)
1467 1245 : != data_.dynamicImplementations.end())
1468 : {
1469 : throw css::lang::IllegalArgumentException(
1470 : "Insert duplicate factory object",
1471 0 : static_cast< cppu::OWeakObject * >(this), 0);
1472 : }
1473 : }
1474 : //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1475 : data_.namedImplementations.insert(
1476 : extra.namedImplementations.begin(),
1477 415 : extra.namedImplementations.end());
1478 : data_.dynamicImplementations.insert(
1479 : extra.dynamicImplementations.begin(),
1480 415 : extra.dynamicImplementations.end());
1481 415 : insertImplementationMap(&data_.services, extra.services);
1482 415 : insertImplementationMap(&data_.singletons, extra.singletons);
1483 : }
1484 : //TODO: Updating the component context singleton data should be part of the
1485 : // atomic service manager update:
1486 415 : if (!extra.singletons.empty()) {
1487 : assert(context_.is());
1488 : css::uno::Reference< css::container::XNameContainer > cont(
1489 0 : context_, css::uno::UNO_QUERY_THROW);
1490 0 : for (Data::ImplementationMap::const_iterator i(
1491 0 : extra.singletons.begin());
1492 0 : i != extra.singletons.end(); ++i)
1493 : {
1494 0 : rtl::OUString name("/singletons/" + i->first);
1495 : //TODO: Update should be atomic:
1496 : try {
1497 0 : cont->removeByName(name + "/arguments");
1498 0 : } catch (const css::container::NoSuchElementException &) {}
1499 : assert(!i->second.empty());
1500 : assert(i->second[0].get() != 0);
1501 : SAL_INFO_IF(
1502 : i->second.size() > 1, "cppuhelper",
1503 : "Arbitrarily chosing " << i->second[0]->info->name
1504 : << " among multiple implementations for singleton "
1505 : << i->first);
1506 : try {
1507 0 : cont->insertByName(
1508 0 : name + "/service", css::uno::Any(i->second[0]->info->name));
1509 0 : } catch (css::container::ElementExistException &) {
1510 0 : cont->replaceByName(
1511 0 : name + "/service", css::uno::Any(i->second[0]->info->name));
1512 : }
1513 : try {
1514 0 : cont->insertByName(name, css::uno::Any());
1515 0 : } catch (css::container::ElementExistException &) {
1516 : SAL_INFO("cppuhelper", "Overwriting singleton " << i->first);
1517 0 : cont->replaceByName(name, css::uno::Any());
1518 : }
1519 0 : }
1520 : }
1521 415 : return true;
1522 : }
1523 :
1524 0 : void cppuhelper::ServiceManager::removeRdbFiles(
1525 : std::vector< rtl::OUString > const & uris)
1526 : {
1527 : // The underlying data structures make this function somewhat inefficient,
1528 : // but the assumption is that it is rarely called (and that if it is called,
1529 : // it is called with a uris vector of size one):
1530 0 : std::vector< boost::shared_ptr< Data::Implementation > > clear;
1531 : {
1532 0 : osl::MutexGuard g(rBHelper.rMutex);
1533 0 : for (std::vector< rtl::OUString >::const_iterator i(uris.begin());
1534 0 : i != uris.end(); ++i)
1535 : {
1536 0 : for (Data::NamedImplementations::iterator j(
1537 0 : data_.namedImplementations.begin());
1538 0 : j != data_.namedImplementations.end();)
1539 : {
1540 : assert(j->second.get() != 0);
1541 0 : if (j->second->info->rdbFile == *i) {
1542 0 : clear.push_back(j->second);
1543 : //TODO: The below leaves data_ in an inconsistent state upon
1544 : // exceptions:
1545 : removeFromImplementationMap(
1546 0 : &data_.services, j->second->info->services, j->second);
1547 : removeFromImplementationMap(
1548 0 : &data_.singletons, j->second->info->singletons,
1549 0 : j->second);
1550 0 : data_.namedImplementations.erase(j++);
1551 : } else {
1552 0 : ++j;
1553 : }
1554 : }
1555 0 : }
1556 0 : }
1557 : //TODO: Update the component context singleton data
1558 0 : }
1559 :
1560 6 : bool cppuhelper::ServiceManager::removeLegacyFactory(
1561 : css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
1562 : bool removeListener)
1563 : {
1564 : assert(factoryInfo.is());
1565 6 : boost::shared_ptr< Data::Implementation > clear;
1566 12 : css::uno::Reference< css::lang::XComponent > comp;
1567 : {
1568 6 : osl::MutexGuard g(rBHelper.rMutex);
1569 : Data::DynamicImplementations::iterator i(
1570 6 : data_.dynamicImplementations.find(factoryInfo));
1571 6 : if (i == data_.dynamicImplementations.end()) {
1572 0 : return isDisposed();
1573 : }
1574 : assert(i->second.get() != 0);
1575 6 : clear = i->second;
1576 6 : if (removeListener) {
1577 0 : comp = i->second->component;
1578 : }
1579 : //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1580 : removeFromImplementationMap(
1581 6 : &data_.services, i->second->info->services, i->second);
1582 : removeFromImplementationMap(
1583 6 : &data_.singletons, i->second->info->singletons, i->second);
1584 6 : if (!i->second->info->name.isEmpty()) {
1585 6 : data_.namedImplementations.erase(i->second->info->name);
1586 : }
1587 6 : data_.dynamicImplementations.erase(i);
1588 : }
1589 6 : if (comp.is()) {
1590 0 : removeEventListenerFromComponent(comp);
1591 : }
1592 12 : return true;
1593 : }
1594 :
1595 1 : void cppuhelper::ServiceManager::removeImplementation(rtl::OUString name) {
1596 : // The underlying data structures make this function somewhat inefficient,
1597 : // but the assumption is that it is rarely called:
1598 1 : boost::shared_ptr< Data::Implementation > clear;
1599 : {
1600 1 : osl::MutexGuard g(rBHelper.rMutex);
1601 1 : if (isDisposed()) {
1602 1 : return;
1603 : }
1604 : Data::NamedImplementations::iterator i(
1605 1 : data_.namedImplementations.find(name));
1606 1 : if (i == data_.namedImplementations.end()) {
1607 : throw css::container::NoSuchElementException(
1608 0 : "Remove non-inserted implementation " + name,
1609 0 : static_cast< cppu::OWeakObject * >(this));
1610 : }
1611 : assert(i->second.get() != 0);
1612 1 : clear = i->second;
1613 : //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1614 : removeFromImplementationMap(
1615 1 : &data_.services, i->second->info->services, i->second);
1616 : removeFromImplementationMap(
1617 1 : &data_.singletons, i->second->info->singletons, i->second);
1618 21 : for (Data::DynamicImplementations::iterator j(
1619 1 : data_.dynamicImplementations.begin());
1620 14 : j != data_.dynamicImplementations.end(); ++j)
1621 : {
1622 7 : if (j->second == i->second) {
1623 1 : data_.dynamicImplementations.erase(j);
1624 1 : break;
1625 : }
1626 : }
1627 1 : data_.namedImplementations.erase(i);
1628 1 : }
1629 : }
1630 :
1631 : boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
1632 759321 : cppuhelper::ServiceManager::findServiceImplementation(
1633 : css::uno::Reference< css::uno::XComponentContext > const & context,
1634 : rtl::OUString const & specifier)
1635 : {
1636 759321 : boost::shared_ptr< Data::Implementation > impl;
1637 : bool loaded;
1638 : {
1639 759321 : osl::MutexGuard g(rBHelper.rMutex);
1640 : Data::ImplementationMap::const_iterator i(
1641 759321 : data_.services.find(specifier));
1642 759321 : if (i == data_.services.end()) {
1643 : Data::NamedImplementations::const_iterator j(
1644 81381 : data_.namedImplementations.find(specifier));
1645 81381 : if (j == data_.namedImplementations.end()) {
1646 : SAL_INFO("cppuhelper", "No implementation for " << specifier);
1647 61526 : return boost::shared_ptr< Data::Implementation >();
1648 : }
1649 19855 : impl = j->second;
1650 : } else {
1651 : assert(!i->second.empty());
1652 : SAL_INFO_IF(
1653 : i->second.size() > 1, "cppuhelper",
1654 : "Arbitrarily chosing " << i->second[0]->info->name
1655 : << " among multiple implementations for " << i->first);
1656 677940 : impl = i->second[0];
1657 : }
1658 : assert(impl.get() != 0);
1659 697795 : loaded = impl->loaded;
1660 : }
1661 : //TODO: There is a race here, as the relevant service factory can be removed
1662 : // while the mutex is unlocked and loading can thus fail, as the entity from
1663 : // which to load can disappear once the service factory is removed.
1664 697795 : if (!loaded) {
1665 8970 : css::uno::Reference< css::lang::XSingleComponentFactory > f1;
1666 17940 : css::uno::Reference< css::lang::XSingleServiceFactory > f2;
1667 8970 : loadImplementation(context, impl->info, &f1, &f2);
1668 17940 : osl::MutexGuard g(rBHelper.rMutex);
1669 8970 : if (!(isDisposed() || impl->loaded)) {
1670 8970 : impl->loaded = true;
1671 8970 : impl->factory1 = f1;
1672 8970 : impl->factory2 = f2;
1673 8970 : }
1674 : }
1675 697795 : return impl;
1676 : }
1677 :
1678 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|