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