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