Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License or as specified alternatively below. You may obtain a copy of
8 : : * the License at http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * Major Contributor(s):
16 : : * [ Copyright (C) 2012 Red Hat, Inc., Stephan Bergmann <sbergman@redhat.com>
17 : : * (initial developer) ]
18 : : *
19 : : * All Rights Reserved.
20 : : *
21 : : * For minor contributions see the git repository.
22 : : *
23 : : * Alternatively, the contents of this file may be used under the terms of
24 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
25 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
26 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
27 : : * instead of those above.
28 : : */
29 : :
30 : : #include "sal/config.h"
31 : :
32 : : #include <algorithm>
33 : : #include <cassert>
34 : : #include <cstring>
35 : : #include <map>
36 : : #include <vector>
37 : :
38 : : #include "boost/noncopyable.hpp"
39 : : #include "boost/shared_ptr.hpp"
40 : : #include "com/sun/star/beans/NamedValue.hpp"
41 : : #include "com/sun/star/beans/PropertyAttribute.hpp"
42 : : #include "com/sun/star/beans/XPropertySet.hpp"
43 : : #include "com/sun/star/container/ElementExistException.hpp"
44 : : #include "com/sun/star/container/XContentEnumerationAccess.hpp"
45 : : #include "com/sun/star/container/XEnumeration.hpp"
46 : : #include "com/sun/star/container/XHierarchicalNameAccess.hpp"
47 : : #include "com/sun/star/container/XNameContainer.hpp"
48 : : #include "com/sun/star/container/XSet.hpp"
49 : : #include "com/sun/star/lang/XInitialization.hpp"
50 : : #include "com/sun/star/lang/XServiceInfo.hpp"
51 : : #include "com/sun/star/lang/XSingleComponentFactory.hpp"
52 : : #include "com/sun/star/lang/XSingleServiceFactory.hpp"
53 : : #include "com/sun/star/loader/XImplementationLoader.hpp"
54 : : #include "com/sun/star/registry/InvalidRegistryException.hpp"
55 : : #include "com/sun/star/registry/XSimpleRegistry.hpp"
56 : : #include "com/sun/star/uno/DeploymentException.hpp"
57 : : #include "com/sun/star/uno/Reference.hxx"
58 : : #include "com/sun/star/uno/XComponentContext.hpp"
59 : : #include "cppuhelper/bootstrap.hxx"
60 : : #include "cppuhelper/compbase8.hxx"
61 : : #include "cppuhelper/component_context.hxx"
62 : : #include "cppuhelper/implbase1.hxx"
63 : : #include "cppuhelper/implbase3.hxx"
64 : : #include "cppuhelper/shlib.hxx"
65 : : #include "osl/file.hxx"
66 : : #include "registry/registry.hxx"
67 : : #include "rtl/bootstrap.hxx"
68 : : #include "rtl/ref.hxx"
69 : : #include "rtl/uri.hxx"
70 : : #include "rtl/ustring.hxx"
71 : : #include "xmlreader/xmlreader.hxx"
72 : :
73 : : #include "macro_expander.hxx"
74 : : #include "paths.hxx"
75 : : #include "servicefactory_detail.hxx"
76 : :
77 : : namespace {
78 : :
79 : : namespace css = com::sun::star;
80 : :
81 : 960 : bool nextDirectoryItem(osl::Directory & directory, rtl::OUString * url) {
82 : : assert(url != 0);
83 : 960 : for (;;) {
84 : 960 : osl::DirectoryItem i;
85 [ + + - ]: 960 : switch (directory.getNextItem(i, SAL_MAX_UINT32)) {
[ + - ]
86 : : case osl::FileBase::E_None:
87 : 640 : break;
88 : : case osl::FileBase::E_NOENT:
89 : 320 : return false;
90 : : default:
91 : : throw css::uno::DeploymentException(
92 : : "Cannot iterate directory",
93 [ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
94 : : }
95 : : osl::FileStatus stat(
96 : : osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |
97 : 640 : osl_FileStatus_Mask_FileURL);
98 [ - + ][ + - ]: 640 : if (i.getFileStatus(stat) != osl::FileBase::E_None) {
99 : : throw css::uno::DeploymentException(
100 : : "Cannot stat in directory",
101 [ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
102 : : }
103 [ + - ][ + - ]: 640 : if (stat.getFileType() != osl::FileStatus::Directory) { //TODO: symlinks
104 : : // Ignore backup files:
105 [ + - ]: 640 : rtl::OUString name(stat.getFileName());
106 [ + - ][ + - ]: 640 : if (!(name.match(".") || name.endsWith("~"))) {
[ + - ]
107 [ + - ]: 640 : *url = stat.getFileURL();
108 : 640 : return true;
109 [ - + ]: 640 : }
110 : : }
111 [ + - ][ + - ]: 960 : }
[ - + ]
112 : : }
113 : :
114 : 5348 : void decodeRdbUri(rtl::OUString * uri, bool * optional, bool * directory) {
115 : : assert(uri != 0 && optional != 0 && directory != 0);
116 : 5348 : *optional = (*uri)[0] == '?';
117 [ + + ]: 5348 : if (*optional) {
118 : 1330 : *uri = uri->copy(1);
119 : : }
120 : 10696 : *directory = uri->getLength() >= 3 && (*uri)[0] == '<'
121 : 320 : && (*uri)[uri->getLength() - 2] == '>'
122 [ + - ][ + - : 11016 : && (*uri)[uri->getLength() - 1] == '*';
+ + + - ]
123 [ + + ]: 5348 : if (*directory) {
124 : 320 : *uri = uri->copy(1, uri->getLength() - 3);
125 : : }
126 : 5348 : }
127 : :
128 : 224094 : struct ImplementationInfo: private boost::noncopyable {
129 : 223218 : ImplementationInfo(
130 : : rtl::OUString const & theName, rtl::OUString const & theLoader,
131 : : rtl::OUString const & theUri, rtl::OUString const & thePrefix,
132 : : css::uno::Reference< css::uno::XComponentContext > const &
133 : : theAlienContext):
134 : : name(theName), loader(theLoader), uri(theUri), prefix(thePrefix),
135 [ + - ][ + - ]: 223218 : alienContext(theAlienContext)
136 : 223218 : {}
137 : :
138 [ + - ][ + - ]: 1028 : explicit ImplementationInfo(rtl::OUString const & theName): name(theName) {}
139 : :
140 : : rtl::OUString const name;
141 : : rtl::OUString const loader;
142 : : rtl::OUString const uri;
143 : : rtl::OUString const prefix;
144 : : css::uno::Reference< css::uno::XComponentContext > const alienContext;
145 : : std::vector< rtl::OUString > services;
146 : : std::vector< rtl::OUString > singletons;
147 : : };
148 : :
149 [ + - ]: 224166 : struct Implementation: private boost::noncopyable {
150 : 223218 : Implementation(
151 : : rtl::OUString const & name, rtl::OUString const & loader,
152 : : rtl::OUString const & uri,
153 : : rtl::OUString const & prefix = rtl::OUString(),
154 : : css::uno::Reference< css::uno::XComponentContext > const &
155 : : alienContext
156 : : = css::uno::Reference< css::uno::XComponentContext >()):
157 [ + - ]: 223218 : info(new ImplementationInfo(name, loader, uri, prefix, alienContext)),
158 [ + - ][ + - ]: 446436 : loaded(false)
159 : 223218 : {}
160 : :
161 : 1028 : Implementation(
162 : : rtl::OUString const & name,
163 : : css::uno::Reference< css::lang::XSingleComponentFactory > const &
164 : : theFactory1,
165 : : css::uno::Reference< css::lang::XSingleServiceFactory > const &
166 : : theFactory2,
167 : : css::uno::Reference< css::lang::XComponent > const & theComponent):
168 [ + - ]: 1028 : info(new ImplementationInfo(name)), factory1(theFactory1),
169 [ + - ][ + - ]: 2056 : factory2(theFactory2), component(theComponent), loaded(true)
170 : 1028 : {}
171 : :
172 : : boost::shared_ptr< ImplementationInfo > info;
173 : : css::uno::Reference< css::lang::XSingleComponentFactory > factory1;
174 : : css::uno::Reference< css::lang::XSingleServiceFactory > factory2;
175 : : css::uno::Reference< css::lang::XComponent > component;
176 : : bool loaded;
177 : : };
178 : :
179 : : typedef std::map< rtl::OUString, boost::shared_ptr< Implementation > >
180 : : NamedImplementations;
181 : :
182 : : typedef
183 : : std::map<
184 : : css::uno::Reference< css::lang::XServiceInfo >,
185 : : boost::shared_ptr< Implementation > >
186 : : DynamicImplementations;
187 : :
188 : : typedef
189 : : std::map<
190 : : rtl::OUString, std::vector< boost::shared_ptr< Implementation > > >
191 : : ImplementationMap;
192 : :
193 : 2056 : void insertImplementationMap(
194 : : ImplementationMap * destination, ImplementationMap const & source)
195 : : {
196 : : assert(destination != 0);
197 [ + + ]: 3084 : for (ImplementationMap::const_iterator i(source.begin()); i != source.end();
198 : : ++i)
199 : : {
200 : : std::vector< boost::shared_ptr< Implementation > > & impls
201 [ + - ]: 1028 : = (*destination)[i->first];
202 [ + - ]: 1028 : impls.insert(impls.end(), i->second.begin(), i->second.end());
203 : : }
204 : 2056 : }
205 : :
206 : 28 : void removeFromImplementationMap(
207 : : ImplementationMap * map, std::vector< rtl::OUString > const & elements,
208 : : boost::shared_ptr< Implementation > const & implementation)
209 : : {
210 : : // The underlying data structures make this function somewhat inefficient,
211 : : // but the assumption is that it is rarely called:
212 : : assert(map != 0);
213 [ + - ][ + + ]: 84 : for (std::vector< rtl::OUString >::const_iterator i(elements.begin());
214 : 42 : i != elements.end(); ++i)
215 : : {
216 [ + - ]: 14 : ImplementationMap::iterator j(map->find(*i));
217 : : assert(j != map->end());
218 : : std::vector< boost::shared_ptr< Implementation > >::iterator k(
219 [ + - ]: 14 : std::find(j->second.begin(), j->second.end(), implementation));
220 : : assert(k != j->second.end());
221 [ + - ]: 14 : j->second.erase(k);
222 [ + - ]: 14 : if (j->second.empty()) {
223 [ + - ]: 14 : map->erase(j);
224 : : }
225 : : }
226 : 28 : }
227 : :
228 [ + - ][ + - ]: 3207 : struct Data: private boost::noncopyable {
[ + - ][ + - ]
229 : : NamedImplementations namedImplementations;
230 : : DynamicImplementations dynamicImplementations;
231 : : ImplementationMap services;
232 : : ImplementationMap singletons;
233 : : };
234 : :
235 : : // This is largely a copy from stoc/source/simpleregistry/textualservices.cxx
236 : : // (which it obsoletes); cppuhelper's published interface concept makes it
237 : : // difficult to make both places use a shared Parser implementation, so I
238 : : // created a copy for now (until the whole stoc/source/simpleregistry stuff can
239 : : // be removed in an incompatible LibreOffice version). For simplicity, this
240 : : // code keeps throwing css::registry::InvalidRegistryException for invalid XML
241 : : // rdbs (even though that does not fit the exception's name):
242 [ + - ][ + - ]: 3947 : class Parser: private boost::noncopyable {
243 : : public:
244 : : Parser(
245 : : rtl::OUString const & uri,
246 : : css::uno::Reference< css::uno::XComponentContext > const & alienContext,
247 : : Data * data);
248 : :
249 : : private:
250 : : void handleComponent();
251 : :
252 : : void handleImplementation();
253 : :
254 : : void handleService();
255 : :
256 : : void handleSingleton();
257 : :
258 : : rtl::OUString getNameAttribute();
259 : :
260 : : xmlreader::XmlReader reader_;
261 : : css::uno::Reference< css::uno::XComponentContext > alienContext_;
262 : : Data * data_;
263 : : rtl::OUString attrLoader_;
264 : : rtl::OUString attrUri_;
265 : : rtl::OUString attrPrefix_;
266 : : rtl::OUString attrImplementation_;
267 : : boost::shared_ptr< Implementation > implementation_;
268 : : };
269 : :
270 : 4467 : Parser::Parser(
271 : : rtl::OUString const & uri,
272 : : css::uno::Reference< css::uno::XComponentContext > const & alienContext,
273 : : Data * data):
274 [ + + ][ + - ]: 4663 : reader_(uri), alienContext_(alienContext), data_(data)
275 : : {
276 : : assert(data != 0);
277 : : int ucNsId = reader_.registerNamespaceIri(
278 : : xmlreader::Span(
279 : : RTL_CONSTASCII_STRINGPARAM(
280 [ + - ]: 4143 : "http://openoffice.org/2010/uno-components")));
281 : : enum State {
282 : : STATE_BEGIN, STATE_END, STATE_COMPONENTS, STATE_COMPONENT_INITIAL,
283 : : STATE_COMPONENT, STATE_IMPLEMENTATION, STATE_SERVICE, STATE_SINGLETON };
284 : 1102046 : for (State state = STATE_BEGIN;;) {
285 : 1098099 : xmlreader::Span name;
286 : : int nsId;
287 : : xmlreader::XmlReader::Result res = reader_.nextItem(
288 [ + + ]: 1098099 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
289 [ + + + + : 1097903 : switch (state) {
+ + + +
- ]
290 : : case STATE_BEGIN:
291 [ + - ]: 7894 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
[ + - + - ]
[ + - ]
292 : 3947 : && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
293 : : {
294 : 3947 : state = STATE_COMPONENTS;
295 : 3947 : break;
296 : : }
297 : : throw css::registry::InvalidRegistryException(
298 : : reader_.getUrl() + ": unexpected item in outer level",
299 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
300 : : case STATE_END:
301 [ - + ]: 3947 : if (res == xmlreader::XmlReader::RESULT_DONE) {
302 : 3947 : return;
303 : : }
304 : : throw css::registry::InvalidRegistryException(
305 : : reader_.getUrl() + ": unexpected item in outer level",
306 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
307 : : case STATE_COMPONENTS:
308 [ + + ]: 41803 : if (res == xmlreader::XmlReader::RESULT_END) {
309 : 3947 : state = STATE_END;
310 : 3947 : break;
311 : : }
312 [ + - ]: 75712 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
[ + - + - ]
[ + - ]
313 : 37856 : && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
314 : : {
315 [ + - ]: 37856 : handleComponent();
316 : 37856 : state = STATE_COMPONENT_INITIAL;
317 : 37856 : break;
318 : : }
319 : : throw css::registry::InvalidRegistryException(
320 : : reader_.getUrl() + ": unexpected item in <components>",
321 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
322 : : case STATE_COMPONENT:
323 [ + + ]: 223022 : if (res == xmlreader::XmlReader::RESULT_END) {
324 : 37856 : state = STATE_COMPONENTS;
325 : 37856 : break;
326 : : }
327 : : // fall through
328 : : case STATE_COMPONENT_INITIAL:
329 [ + - ]: 446044 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
[ + - + - ]
[ + - ]
330 : 223022 : && name.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
331 : : {
332 [ + - ]: 223022 : handleImplementation();
333 : 223022 : state = STATE_IMPLEMENTATION;
334 : 223022 : break;
335 : : }
336 : : throw css::registry::InvalidRegistryException(
337 : : reader_.getUrl() + ": unexpected item in <component>",
338 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
339 : : case STATE_IMPLEMENTATION:
340 [ + + ]: 505175 : if (res == xmlreader::XmlReader::RESULT_END) {
341 : 223022 : state = STATE_COMPONENT;
342 : 223022 : break;
343 : : }
344 [ + - ]: 564306 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
[ + - + + ]
[ + + ]
345 : 282153 : && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
346 : : {
347 [ + - ]: 278562 : handleService();
348 : 278562 : state = STATE_SERVICE;
349 : 278562 : break;
350 : : }
351 [ + - ]: 7182 : if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
[ + - + - ]
[ + - ]
352 : 3591 : && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
353 : : {
354 [ + - ]: 3591 : handleSingleton();
355 : 3591 : state = STATE_SINGLETON;
356 : 3591 : break;
357 : : }
358 : : throw css::registry::InvalidRegistryException(
359 : : reader_.getUrl() + ": unexpected item in <implementation>",
360 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
361 : : case STATE_SERVICE:
362 [ + - ]: 278562 : if (res == xmlreader::XmlReader::RESULT_END) {
363 : 278562 : state = STATE_IMPLEMENTATION;
364 : 278562 : break;
365 : : }
366 : : throw css::registry::InvalidRegistryException(
367 : : reader_.getUrl() + ": unexpected item in <service>",
368 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
369 : : case STATE_SINGLETON:
370 [ + - ]: 3591 : if (res == xmlreader::XmlReader::RESULT_END) {
371 : 3591 : state = STATE_IMPLEMENTATION;
372 : 3591 : break;
373 : : }
374 : : throw css::registry::InvalidRegistryException(
375 : : reader_.getUrl() + ": unexpected item in <service>",
376 [ # # ][ # # ]: 196 : css::uno::Reference< css::uno::XInterface >());
377 : : }
378 : : }
379 : : }
380 : :
381 : 37856 : void Parser::handleComponent() {
382 : 37856 : attrLoader_ = rtl::OUString();
383 : 37856 : attrUri_ = rtl::OUString();
384 : 37856 : attrPrefix_ = rtl::OUString();
385 : 37856 : xmlreader::Span name;
386 : : int nsId;
387 [ + - ][ + + ]: 129288 : while (reader_.nextAttribute(&nsId, &name)) {
388 [ + - + + ]: 182864 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
[ + + ]
389 : 91432 : && name.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
390 : : {
391 [ - + ]: 37856 : if (!attrLoader_.isEmpty()) {
392 : : throw css::registry::InvalidRegistryException(
393 : : (reader_.getUrl()
394 : : + ": <component> has multiple \"loader\" attributes"),
395 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
396 : : }
397 [ + - ][ + - ]: 37856 : attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8();
398 [ - + ]: 37856 : if (attrLoader_.isEmpty()) {
399 : : throw css::registry::InvalidRegistryException(
400 : : (reader_.getUrl()
401 : : + ": <component> has empty \"loader\" attribute"),
402 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
403 : : }
404 [ + - + + ]: 107152 : } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
[ + + ]
405 : 53576 : && name.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
406 : : {
407 [ - + ]: 37856 : if (!attrUri_.isEmpty()) {
408 : : throw css::registry::InvalidRegistryException(
409 : : (reader_.getUrl()
410 : : + ": <component> has multiple \"uri\" attributes"),
411 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
412 : : }
413 [ + - ][ + - ]: 37856 : attrUri_ = reader_.getAttributeValue(false).convertFromUtf8();
414 [ - + ]: 37856 : if (attrUri_.isEmpty()) {
415 : : throw css::registry::InvalidRegistryException(
416 : : (reader_.getUrl()
417 : : + ": <component> has empty \"uri\" attribute"),
418 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
419 : : }
420 [ + - + - ]: 31440 : } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
[ + - ]
421 : 15720 : && name.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
422 : : {
423 [ - + ]: 15720 : if (!attrPrefix_.isEmpty()) {
424 : : throw css::registry::InvalidRegistryException(
425 : : (reader_.getUrl() +
426 : : ": <component> has multiple \"prefix\" attributes"),
427 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
428 : : }
429 [ + - ][ + - ]: 15720 : attrPrefix_ = reader_.getAttributeValue(false).convertFromUtf8();
430 [ - + ]: 15720 : if (attrPrefix_.isEmpty()) {
431 : : throw css::registry::InvalidRegistryException(
432 : : (reader_.getUrl() +
433 : : ": <component> has empty \"prefix\" attribute"),
434 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
435 : : }
436 : : } else {
437 : : throw css::registry::InvalidRegistryException(
438 : : (reader_.getUrl() + ": unexpected attribute \""
439 : : + name.convertFromUtf8() + "\" in <component>"),
440 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
441 : : }
442 : : }
443 [ - + ]: 37856 : if (attrLoader_.isEmpty()) {
444 : : throw css::registry::InvalidRegistryException(
445 : : reader_.getUrl() + ": <component> is missing \"loader\" attribute",
446 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
447 : : }
448 [ - + ]: 37856 : if (attrUri_.isEmpty()) {
449 : : throw css::registry::InvalidRegistryException(
450 : : reader_.getUrl() + ": <component> is missing \"uri\" attribute",
451 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
452 : : }
453 : : #ifndef DISABLE_DYNLOADING
454 : : try {
455 [ + - ][ + - ]: 37856 : attrUri_ = rtl::Uri::convertRelToAbs(reader_.getUrl(), attrUri_);
456 [ # # ]: 0 : } catch (const rtl::MalformedUriException & e) {
457 : : throw css::registry::InvalidRegistryException(
458 : 0 : reader_.getUrl() + ": bad \"uri\" attribute: " + e.getMessage(),
459 [ # # # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
460 : : }
461 : : #endif
462 : 37856 : }
463 : :
464 : 223022 : void Parser::handleImplementation() {
465 : 223022 : attrImplementation_ = getNameAttribute();
466 : : implementation_.reset(
467 : : new Implementation(
468 : : attrImplementation_, attrLoader_, attrUri_, attrPrefix_,
469 [ + - ]: 223022 : alienContext_));
470 [ - + ]: 223022 : if (!data_->namedImplementations.insert(
471 : : NamedImplementations::value_type(
472 : : attrImplementation_, implementation_)).
473 [ + - ]: 223022 : second)
474 : : {
475 : : throw css::registry::InvalidRegistryException(
476 : : (reader_.getUrl() + ": duplicate <implementation name=\""
477 : : + attrImplementation_ + "\">"),
478 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
479 : : }
480 : 223022 : }
481 : :
482 : 278562 : void Parser::handleService() {
483 [ + - ]: 278562 : rtl::OUString name(getNameAttribute());
484 [ + - ]: 278562 : implementation_->info->services.push_back(name);
485 [ + - ][ + - ]: 278562 : data_->services[name].push_back(implementation_);
486 : 278562 : }
487 : :
488 : 3591 : void Parser::handleSingleton() {
489 [ + - ]: 3591 : rtl::OUString name(getNameAttribute());
490 [ + - ]: 3591 : implementation_->info->singletons.push_back(name);
491 [ + - ][ + - ]: 3591 : data_->singletons[name].push_back(implementation_);
492 : 3591 : }
493 : :
494 : 505175 : rtl::OUString Parser::getNameAttribute() {
495 : 505175 : rtl::OUString attrName;
496 : 505175 : xmlreader::Span name;
497 : : int nsId;
498 [ + - ][ + + ]: 1010350 : while (reader_.nextAttribute(&nsId, &name)) {
499 [ + - + - ]: 1010350 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
[ + - ]
500 : 505175 : && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
501 : : {
502 [ - + ]: 505175 : if (!attrName.isEmpty()) {
503 : : throw css::registry::InvalidRegistryException(
504 : : (reader_.getUrl()
505 : : + ": element has multiple \"name\" attributes"),
506 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
507 : : }
508 [ + - ][ + - ]: 505175 : attrName = reader_.getAttributeValue(false).convertFromUtf8();
509 [ - + ]: 505175 : if (attrName.isEmpty()) {
510 : : throw css::registry::InvalidRegistryException(
511 : : reader_.getUrl() + ": element has empty \"name\" attribute",
512 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
513 : : }
514 : : } else {
515 : : throw css::registry::InvalidRegistryException(
516 : : reader_.getUrl() + ": expected element attribute \"name\"",
517 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
518 : : }
519 : : }
520 [ - + ]: 505175 : if (attrName.isEmpty()) {
521 : : throw css::registry::InvalidRegistryException(
522 : : reader_.getUrl() + ": element is missing \"name\" attribute",
523 [ # # ][ # # ]: 505175 : css::uno::Reference< css::uno::XInterface >());
524 : : }
525 : 505175 : return attrName;
526 : : }
527 : :
528 : : class ContentEnumeration:
529 : : public cppu::WeakImplHelper1< css::container::XEnumeration >,
530 : : private boost::noncopyable
531 : : {
532 : : public:
533 : 1106 : explicit ContentEnumeration(std::vector< css::uno::Any > const & factories):
534 [ + - ][ + - ]: 1106 : factories_(factories), iterator_(factories_.begin()) {}
[ + - ]
535 : :
536 : : private:
537 [ + - ][ - + ]: 2212 : virtual ~ContentEnumeration() {}
538 : :
539 : : virtual sal_Bool SAL_CALL hasMoreElements()
540 : : throw (css::uno::RuntimeException);
541 : :
542 : : virtual css::uno::Any SAL_CALL nextElement()
543 : : throw (
544 : : css::container::NoSuchElementException,
545 : : css::lang::WrappedTargetException, css::uno::RuntimeException);
546 : :
547 : : osl::Mutex mutex_;
548 : : std::vector< css::uno::Any > factories_;
549 : : std::vector< css::uno::Any >::const_iterator iterator_;
550 : : };
551 : :
552 : 3707 : sal_Bool ContentEnumeration::hasMoreElements()
553 : : throw (css::uno::RuntimeException)
554 : : {
555 [ + - ]: 3707 : osl::MutexGuard g(mutex_);
556 [ + - ][ + - ]: 3707 : return iterator_ != factories_.end();
557 : : }
558 : :
559 : 2601 : css::uno::Any ContentEnumeration::nextElement()
560 : : throw (
561 : : css::container::NoSuchElementException,
562 : : css::lang::WrappedTargetException, css::uno::RuntimeException)
563 : : {
564 [ + - ]: 2601 : osl::MutexGuard g(mutex_);
565 [ + - ][ - + ]: 2601 : if (iterator_ == factories_.end()) {
566 : : throw css::container::NoSuchElementException(
567 : : "Bootstrap service manager service enumerator has no more elements",
568 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
569 : : }
570 [ + - ][ + - ]: 2601 : return *iterator_++;
571 : : }
572 : :
573 : 112 : css::beans::Property getDefaultContextProperty() {
574 : : return css::beans::Property(
575 : : "DefaultContext", -1,
576 : 112 : cppu::UnoType< css::uno::XComponentContext >::get(),
577 : 112 : css::beans::PropertyAttribute::READONLY);
578 : : }
579 : :
580 : : typedef cppu::WeakComponentImplHelper8<
581 : : css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
582 : : css::lang::XMultiComponentFactory, css::container::XSet,
583 : : css::container::XContentEnumerationAccess, css::beans::XPropertySet,
584 : : css::beans::XPropertySetInfo, css::lang::XEventListener >
585 : : ServiceManagerBase;
586 : :
587 : : class ServiceManager:
588 : : private osl::Mutex, public ServiceManagerBase, private boost::noncopyable
589 : : {
590 : : public:
591 : 357 : explicit ServiceManager(rtl::OUString const & rdbUris):
592 [ + - ]: 357 : ServiceManagerBase(*static_cast< osl::Mutex * >(this))
593 [ + - ]: 357 : { readRdbs(rdbUris); }
594 : :
595 : : using ServiceManagerBase::acquire;
596 : : using ServiceManagerBase::release;
597 : :
598 : 357 : void setContext(
599 : : css::uno::Reference< css::uno::XComponentContext > const & context)
600 : : {
601 : : assert(context.is());
602 : : assert(!context_.is());
603 : 357 : context_ = context;
604 : 357 : }
605 : :
606 : 18 : css::uno::Reference< css::uno::XComponentContext > getContext() const {
607 : : assert(context_.is());
608 : 18 : return context_;
609 : : }
610 : :
611 : 357 : Data const & getData() const { return data_; }
612 : :
613 : : void loadImplementation(
614 : : css::uno::Reference< css::uno::XComponentContext > const & context,
615 : : boost::shared_ptr< ImplementationInfo > const & info,
616 : : css::uno::Reference< css::lang::XSingleComponentFactory > * factory1,
617 : : css::uno::Reference< css::lang::XSingleServiceFactory > * factory2);
618 : :
619 : : virtual rtl::OUString SAL_CALL getImplementationName()
620 : : throw (css::uno::RuntimeException);
621 : :
622 : : virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
623 : : throw (css::uno::RuntimeException);
624 : :
625 : : virtual css::uno::Sequence< rtl::OUString > SAL_CALL
626 : : getSupportedServiceNames() throw (css::uno::RuntimeException);
627 : :
628 : : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
629 : : rtl::OUString const & aServiceSpecifier)
630 : : throw (css::uno::Exception, css::uno::RuntimeException);
631 : :
632 : : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
633 : : createInstanceWithArguments(
634 : : rtl::OUString const & ServiceSpecifier,
635 : : css::uno::Sequence< css::uno::Any > const & Arguments)
636 : : throw (css::uno::Exception, css::uno::RuntimeException);
637 : :
638 : : virtual css::uno::Sequence< rtl::OUString > SAL_CALL
639 : : getAvailableServiceNames() throw (css::uno::RuntimeException);
640 : :
641 : : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
642 : : createInstanceWithContext(
643 : : rtl::OUString const & aServiceSpecifier,
644 : : css::uno::Reference< css::uno::XComponentContext > const & Context)
645 : : throw (css::uno::Exception, css::uno::RuntimeException);
646 : :
647 : : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
648 : : createInstanceWithArgumentsAndContext(
649 : : rtl::OUString const & ServiceSpecifier,
650 : : css::uno::Sequence< css::uno::Any > const & Arguments,
651 : : css::uno::Reference< css::uno::XComponentContext > const & Context)
652 : : throw (css::uno::Exception, css::uno::RuntimeException);
653 : :
654 : : virtual css::uno::Type SAL_CALL getElementType()
655 : : throw (css::uno::RuntimeException);
656 : :
657 : : virtual sal_Bool SAL_CALL hasElements() throw (css::uno::RuntimeException);
658 : :
659 : : virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL
660 : : createEnumeration() throw (css::uno::RuntimeException);
661 : :
662 : : virtual sal_Bool SAL_CALL has(css::uno::Any const & aElement)
663 : : throw (css::uno::RuntimeException);
664 : :
665 : : virtual void SAL_CALL insert(css::uno::Any const & aElement)
666 : : throw (
667 : : css::lang::IllegalArgumentException,
668 : : css::container::ElementExistException, css::uno::RuntimeException);
669 : :
670 : : virtual void SAL_CALL remove(css::uno::Any const & aElement)
671 : : throw (
672 : : css::lang::IllegalArgumentException,
673 : : css::container::NoSuchElementException, css::uno::RuntimeException);
674 : :
675 : : virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL
676 : : createContentEnumeration(rtl::OUString const & aServiceName)
677 : : throw (css::uno::RuntimeException);
678 : :
679 : : virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
680 : : getPropertySetInfo() throw (css::uno::RuntimeException);
681 : :
682 : : virtual void SAL_CALL setPropertyValue(
683 : : rtl::OUString const & aPropertyName, css::uno::Any const & aValue)
684 : : throw (
685 : : css::beans::UnknownPropertyException,
686 : : css::beans::PropertyVetoException,
687 : : css::lang::IllegalArgumentException,
688 : : css::lang::WrappedTargetException, css::uno::RuntimeException);
689 : :
690 : : virtual css::uno::Any SAL_CALL getPropertyValue(
691 : : rtl::OUString const & PropertyName)
692 : : throw (
693 : : css::beans::UnknownPropertyException,
694 : : css::lang::WrappedTargetException, css::uno::RuntimeException);
695 : :
696 : : virtual void SAL_CALL addPropertyChangeListener(
697 : : rtl::OUString const & aPropertyName,
698 : : css::uno::Reference< css::beans::XPropertyChangeListener > const &
699 : : xListener)
700 : : throw (
701 : : css::beans::UnknownPropertyException,
702 : : css::lang::WrappedTargetException, css::uno::RuntimeException);
703 : :
704 : : virtual void SAL_CALL removePropertyChangeListener(
705 : : rtl::OUString const & aPropertyName,
706 : : css::uno::Reference< css::beans::XPropertyChangeListener > const &
707 : : aListener)
708 : : throw (
709 : : css::beans::UnknownPropertyException,
710 : : css::lang::WrappedTargetException, css::uno::RuntimeException);
711 : :
712 : : virtual void SAL_CALL addVetoableChangeListener(
713 : : rtl::OUString const & PropertyName,
714 : : css::uno::Reference< css::beans::XVetoableChangeListener > const &
715 : : aListener)
716 : : throw (
717 : : css::beans::UnknownPropertyException,
718 : : css::lang::WrappedTargetException, css::uno::RuntimeException);
719 : :
720 : : virtual void SAL_CALL removeVetoableChangeListener(
721 : : rtl::OUString const & PropertyName,
722 : : css::uno::Reference< css::beans::XVetoableChangeListener > const &
723 : : aListener)
724 : : throw (
725 : : css::beans::UnknownPropertyException,
726 : : css::lang::WrappedTargetException, css::uno::RuntimeException);
727 : :
728 : : virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties()
729 : : throw (css::uno::RuntimeException);
730 : :
731 : : virtual css::beans::Property SAL_CALL getPropertyByName(
732 : : rtl::OUString const & aName)
733 : : throw (
734 : : css::beans::UnknownPropertyException, css::uno::RuntimeException);
735 : :
736 : : virtual sal_Bool SAL_CALL hasPropertyByName(rtl::OUString const & Name)
737 : : throw (css::uno::RuntimeException);
738 : :
739 : : virtual void SAL_CALL disposing(css::lang::EventObject const & Source)
740 : : throw (css::uno::RuntimeException);
741 : :
742 : : private:
743 [ + - ][ - + ]: 168 : virtual ~ServiceManager() {}
744 : :
745 : : virtual void SAL_CALL disposing();
746 : :
747 : : // needs to be called with rBHelper.rMutex locked:
748 [ + - ][ - + ]: 23073 : bool isDisposed() { return rBHelper.bDisposed || rBHelper.bInDispose; }
749 : :
750 : : void removeEventListenerFromComponent(
751 : : css::uno::Reference< css::lang::XComponent > const & component);
752 : :
753 : : void readRdbs(rtl::OUString const & uris);
754 : :
755 : : void readRdbDirectory(rtl::OUString const & uri, bool optional);
756 : :
757 : : void readRdbFile(rtl::OUString const & uri, bool optional);
758 : :
759 : : bool readLegacyRdbFile(rtl::OUString const & uri);
760 : :
761 : : rtl::OUString readLegacyRdbString(
762 : : rtl::OUString const & uri, RegistryKey & key,
763 : : rtl::OUString const & path);
764 : :
765 : : void readLegacyRdbStrings(
766 : : rtl::OUString const & uri, RegistryKey & key,
767 : : rtl::OUString const & path, std::vector< rtl::OUString > * strings);
768 : :
769 : : void insertRdbFiles(
770 : : std::vector< rtl::OUString > const & uris,
771 : : css::uno::Reference< css::uno::XComponentContext > const &
772 : : alientContext);
773 : :
774 : : void insertLegacyFactory(
775 : : css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo);
776 : :
777 : : bool insertExtraData(Data const & extra);
778 : :
779 : : void removeRdbFiles(std::vector< rtl::OUString > const & uris);
780 : :
781 : : bool removeLegacyFactory(
782 : : css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
783 : : bool removeListener);
784 : :
785 : : void removeImplementation(rtl::OUString name);
786 : :
787 : : boost::shared_ptr< Implementation > findServiceImplementation(
788 : : css::uno::Reference< css::uno::XComponentContext > const & context,
789 : : rtl::OUString const & specifier);
790 : :
791 : : css::uno::Reference< css::uno::XComponentContext > context_;
792 : : Data data_;
793 : : };
794 : :
795 : : class FactoryWrapper:
796 : : public cppu::WeakImplHelper3<
797 : : css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
798 : : css::lang::XServiceInfo >,
799 : : private boost::noncopyable
800 : : {
801 : : public:
802 : 1035 : FactoryWrapper(
803 : : rtl::Reference< ServiceManager > const & manager,
804 : : boost::shared_ptr< ImplementationInfo > const & info):
805 [ + - ][ + - ]: 1035 : manager_(manager), info_(info), loaded_(false)
806 : 1035 : { assert(manager.is() && info.get() != 0); }
807 : :
808 : : private:
809 [ + - ][ + - ]: 1926 : virtual ~FactoryWrapper() {}
[ - + ]
810 : :
811 : : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
812 : : createInstanceWithContext(
813 : : css::uno::Reference< css::uno::XComponentContext > const & Context)
814 : : throw (css::uno::Exception, css::uno::RuntimeException);
815 : :
816 : : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
817 : : createInstanceWithArgumentsAndContext(
818 : : css::uno::Sequence< css::uno::Any > const & Arguments,
819 : : css::uno::Reference< css::uno::XComponentContext > const & Context)
820 : : throw (css::uno::Exception, css::uno::RuntimeException);
821 : :
822 : : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
823 : : createInstance() throw (css::uno::Exception, css::uno::RuntimeException);
824 : :
825 : : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
826 : : createInstanceWithArguments(
827 : : css::uno::Sequence< css::uno::Any > const & Arguments)
828 : : throw (css::uno::Exception, css::uno::RuntimeException);
829 : :
830 : : virtual rtl::OUString SAL_CALL getImplementationName()
831 : : throw (css::uno::RuntimeException);
832 : :
833 : : virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
834 : : throw (css::uno::RuntimeException);
835 : :
836 : : virtual css::uno::Sequence< rtl::OUString > SAL_CALL
837 : : getSupportedServiceNames() throw (css::uno::RuntimeException);
838 : :
839 : : void loadImplementation(
840 : : css::uno::Reference< css::uno::XComponentContext > const & context);
841 : :
842 : : rtl::Reference< ServiceManager > manager_;
843 : : boost::shared_ptr< ImplementationInfo > info_;
844 : :
845 : : osl::Mutex mutex_;
846 : : bool loaded_;
847 : : css::uno::Reference< css::lang::XSingleComponentFactory > factory1_;
848 : : css::uno::Reference< css::lang::XSingleServiceFactory > factory2_;
849 : : };
850 : :
851 : 20406 : void ServiceManager::loadImplementation(
852 : : css::uno::Reference< css::uno::XComponentContext > const & context,
853 : : boost::shared_ptr< ImplementationInfo > const & info,
854 : : css::uno::Reference< css::lang::XSingleComponentFactory > * factory1,
855 : : css::uno::Reference< css::lang::XSingleServiceFactory > * factory2)
856 : : {
857 : : assert(
858 : : info.get() != 0 && factory1 != 0 && !factory1->is() && factory2 != 0
859 : : && !factory2->is());
860 : 20406 : rtl::OUString uri;
861 : : try {
862 [ + - ]: 20406 : uri = cppu::bootstrap_expandUri(info->uri);
863 [ # # ]: 0 : } catch (css::lang::IllegalArgumentException & e) {
864 : : throw css::uno::DeploymentException(
865 : 0 : "Cannot expand URI" + info->uri + ": " + e.Message,
866 [ # # # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
867 : : }
868 : 20406 : css::uno::Reference< css::uno::XInterface > f0;
869 : : // Shortcut loading via SharedLibrary loader, to pass in prefix argument
870 : : // (which the loader's activate implementation would normally obtain through
871 : : // the legacy xKey argument):
872 [ + + ]: 40812 : if (!info->alienContext.is()
[ + - + + ]
873 : 20406 : && info->loader == "com.sun.star.loader.SharedLibrary")
874 : : {
875 : 20353 : rtl::OUString prefix(info->prefix);
876 [ + + ]: 20353 : if (!prefix.isEmpty()) {
877 : 16375 : prefix += "_";
878 : : }
879 : : f0 = cppu::loadSharedLibComponentFactory(
880 : 20353 : uri, rtl::OUString(), info->name, this,
881 [ + - + - ]: 40706 : css::uno::Reference< css::registry::XRegistryKey >(), prefix);
[ + - ]
882 : : } else {
883 : : SAL_INFO_IF(
884 : : !info->prefix.isEmpty(), "cppuhelper",
885 : : "Loader " << info->loader << " and non-empty prefix "
886 : : << info->prefix);
887 : 53 : css::uno::Reference< css::uno::XComponentContext > ctxt;
888 : 53 : css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
889 [ - + ]: 53 : if (info->alienContext.is()) {
890 [ # # ]: 0 : ctxt = info->alienContext;
891 : : smgr = css::uno::Reference< css::lang::XMultiComponentFactory >(
892 [ # # ][ # # ]: 0 : ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
[ # # ][ # # ]
893 : : } else {
894 : : assert(context.is());
895 [ + - ]: 53 : ctxt = context;
896 [ + - ]: 53 : smgr = this;
897 : : }
898 : : css::uno::Reference< css::loader::XImplementationLoader > loader(
899 [ + - ]: 53 : smgr->createInstanceWithContext(info->loader, ctxt),
900 [ + - ][ + - ]: 53 : css::uno::UNO_QUERY_THROW);
901 [ + - ]: 53 : f0 = loader->activate(
902 : 53 : info->name, rtl::OUString(), uri,
903 [ + - ][ + - ]: 106 : css::uno::Reference< css::registry::XRegistryKey >());
904 : : }
905 [ + - ]: 20406 : factory1->set(f0, css::uno::UNO_QUERY);
906 [ + + ]: 20406 : if (!factory1->is()) {
907 [ + - ]: 252 : factory2->set(f0, css::uno::UNO_QUERY);
908 : 20406 : }
909 : 20406 : }
910 : :
911 : 27 : rtl::OUString ServiceManager::getImplementationName()
912 : : throw (css::uno::RuntimeException)
913 : : {
914 : : return rtl::OUString(
915 : 27 : "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager");
916 : : }
917 : :
918 : 0 : sal_Bool ServiceManager::supportsService(rtl::OUString const & ServiceName)
919 : : throw (css::uno::RuntimeException)
920 : : {
921 [ # # ]: 0 : css::uno::Sequence< rtl::OUString > names(getSupportedServiceNames());
922 [ # # ]: 0 : for (sal_Int32 i = 0; i != names.getLength(); ++i) {
923 [ # # ][ # # ]: 0 : if (ServiceName == names[i]) {
924 : 0 : return true;
925 : : }
926 : : }
927 [ # # ]: 0 : return false;
928 : : }
929 : :
930 : 0 : css::uno::Sequence< rtl::OUString > ServiceManager::getSupportedServiceNames()
931 : : throw (css::uno::RuntimeException)
932 : : {
933 : 0 : css::uno::Sequence< rtl::OUString > names(2);
934 [ # # ]: 0 : names[0] = "com.sun.star.lang.MultiServiceFactory";
935 [ # # ]: 0 : names[1] = "com.sun.star.lang.ServiceManager";
936 : 0 : return names;
937 : : }
938 : :
939 : 940973 : css::uno::Reference< css::uno::XInterface > ServiceManager::createInstance(
940 : : rtl::OUString const & aServiceSpecifier)
941 : : throw (css::uno::Exception, css::uno::RuntimeException)
942 : : {
943 : : assert(context_.is());
944 : 940973 : return createInstanceWithContext(aServiceSpecifier, context_);
945 : : }
946 : :
947 : : css::uno::Reference< css::uno::XInterface >
948 : 30736 : ServiceManager::createInstanceWithArguments(
949 : : rtl::OUString const & ServiceSpecifier,
950 : : css::uno::Sequence< css::uno::Any > const & Arguments)
951 : : throw (css::uno::Exception, css::uno::RuntimeException)
952 : : {
953 : : assert(context_.is());
954 : : return createInstanceWithArgumentsAndContext(
955 : 30736 : ServiceSpecifier, Arguments, context_);
956 : : }
957 : :
958 : 0 : css::uno::Sequence< rtl::OUString > ServiceManager::getAvailableServiceNames()
959 : : throw (css::uno::RuntimeException)
960 : : {
961 [ # # ]: 0 : osl::MutexGuard g(rBHelper.rMutex);
962 [ # # ]: 0 : if (isDisposed()) {
963 [ # # ]: 0 : return css::uno::Sequence< rtl::OUString >();
964 : : }
965 : 0 : ImplementationMap::size_type n = data_.services.size();
966 [ # # ]: 0 : if (n > static_cast< sal_uInt32 >(SAL_MAX_INT32)) {
967 : : throw css::uno::RuntimeException(
968 : : "getAvailableServiceNames: too many services",
969 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
970 : : }
971 [ # # ]: 0 : css::uno::Sequence< rtl::OUString > names(static_cast< sal_Int32 >(n));
972 : 0 : sal_Int32 i = 0;
973 [ # # ]: 0 : for (ImplementationMap::const_iterator j(data_.services.begin());
974 : 0 : j != data_.services.end(); ++j)
975 : : {
976 [ # # ]: 0 : names[i++] = j->first;
977 : : }
978 : : assert(i == names.getLength());
979 [ # # ][ # # ]: 0 : return names;
[ # # ]
980 : : }
981 : :
982 : : css::uno::Reference< css::uno::XInterface >
983 : 1282255 : ServiceManager::createInstanceWithContext(
984 : : rtl::OUString const & aServiceSpecifier,
985 : : css::uno::Reference< css::uno::XComponentContext > const & Context)
986 : : throw (css::uno::Exception, css::uno::RuntimeException)
987 : : {
988 : : boost::shared_ptr< Implementation > impl(
989 [ + - ]: 1282255 : findServiceImplementation(Context, aServiceSpecifier));
990 [ + + ]: 1282255 : if (impl.get() == 0) {
991 : 113465 : return css::uno::Reference< css::uno::XInterface >();
992 : : }
993 [ + + ]: 1168790 : if (impl->factory1.is()) {
994 [ + - ][ + - ]: 1165222 : return impl->factory1->createInstanceWithContext(Context);
995 : : }
996 [ + - ]: 3568 : if (impl->factory2.is()) {
997 [ + - ][ + - ]: 3568 : return impl->factory2->createInstance();
998 : : }
999 : : throw css::uno::DeploymentException(
1000 : 0 : "Implementation " + impl->info->name + " does not provide a factory",
1001 [ # # ][ # # ]: 1282255 : static_cast< cppu::OWeakObject * >(this));
[ + - ]
1002 : : }
1003 : :
1004 : : css::uno::Reference< css::uno::XInterface >
1005 : 47016 : ServiceManager::createInstanceWithArgumentsAndContext(
1006 : : rtl::OUString const & ServiceSpecifier,
1007 : : css::uno::Sequence< css::uno::Any > const & Arguments,
1008 : : css::uno::Reference< css::uno::XComponentContext > const & Context)
1009 : : throw (css::uno::Exception, css::uno::RuntimeException)
1010 : : {
1011 : : boost::shared_ptr< Implementation > impl(
1012 [ + - ]: 47016 : findServiceImplementation(Context, ServiceSpecifier));
1013 [ + + ]: 47016 : if (impl.get() == 0) {
1014 : 15292 : return css::uno::Reference< css::uno::XInterface >();
1015 : : }
1016 [ + + ]: 31724 : if (impl->factory1.is()) {
1017 [ + - ]: 31169 : return impl->factory1->createInstanceWithArgumentsAndContext(
1018 [ + + ]: 31169 : Arguments, Context);
1019 : : }
1020 [ + - ]: 555 : if (impl->factory2.is()) {
1021 [ + - ][ + - ]: 555 : return impl->factory2->createInstanceWithArguments(Arguments);
1022 : : }
1023 : : throw css::uno::DeploymentException(
1024 : 0 : "Implementation " + impl->info->name + " does not provide a factory",
1025 [ # # ][ # # ]: 47016 : static_cast< cppu::OWeakObject * >(this));
[ + - ]
1026 : : }
1027 : :
1028 : 0 : css::uno::Type ServiceManager::getElementType()
1029 : : throw (css::uno::RuntimeException)
1030 : : {
1031 : 0 : return css::uno::Type();
1032 : : }
1033 : :
1034 : 0 : sal_Bool ServiceManager::hasElements() throw (css::uno::RuntimeException) {
1035 [ # # ]: 0 : osl::MutexGuard g(rBHelper.rMutex);
1036 : : return
1037 : 0 : !(data_.namedImplementations.empty()
1038 [ # # ][ # # ]: 0 : && data_.dynamicImplementations.empty());
[ # # ]
1039 : : }
1040 : :
1041 : : css::uno::Reference< css::container::XEnumeration >
1042 : 0 : ServiceManager::createEnumeration() throw (css::uno::RuntimeException) {
1043 : : throw css::uno::RuntimeException(
1044 : : "ServiceManager createEnumeration: method not supported",
1045 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1046 : : }
1047 : :
1048 : 0 : sal_Bool ServiceManager::has(css::uno::Any const &)
1049 : : throw (css::uno::RuntimeException)
1050 : : {
1051 : : throw css::uno::RuntimeException(
1052 : : "ServiceManager has: method not supported",
1053 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1054 : : }
1055 : :
1056 : 1028 : void ServiceManager::insert(css::uno::Any const & aElement)
1057 : : throw (
1058 : : css::lang::IllegalArgumentException,
1059 : : css::container::ElementExistException, css::uno::RuntimeException)
1060 : : {
1061 [ + - ]: 1028 : css::uno::Sequence< css::beans::NamedValue > args;
1062 [ + - ][ - + ]: 1028 : if (aElement >>= args) {
1063 [ # # ]: 0 : std::vector< rtl::OUString > uris;
1064 : 0 : css::uno::Reference< css::uno::XComponentContext > alienContext;
1065 [ # # ]: 0 : for (sal_Int32 i = 0; i < args.getLength(); ++i) {
1066 [ # # ][ # # ]: 0 : if (args[i].Name == "uri") {
1067 : 0 : rtl::OUString uri;
1068 [ # # ][ # # ]: 0 : if (!(args[i].Value >>= uri)) {
1069 : : throw css::lang::IllegalArgumentException(
1070 : : "Bad uri argument",
1071 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this), 0);
1072 : : }
1073 [ # # ]: 0 : uris.push_back(uri);
1074 [ # # ][ # # ]: 0 : } else if (args[i].Name == "component-context") {
1075 [ # # ]: 0 : if (alienContext.is()) {
1076 : : throw css::lang::IllegalArgumentException(
1077 : : "Multiple component-context arguments",
1078 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this), 0);
1079 : : }
1080 [ # # ][ # # ]: 0 : if (!(args[i].Value >>= alienContext) || !alienContext.is()) {
[ # # ][ # # ]
[ # # ]
1081 : : throw css::lang::IllegalArgumentException(
1082 : : "Bad component-context argument",
1083 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this), 0);
1084 : : }
1085 : : } else {
1086 : : throw css::lang::IllegalArgumentException(
1087 [ # # ]: 0 : "Bad argument " + args[i].Name,
1088 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this), 0);
1089 : : }
1090 : : }
1091 [ # # ]: 0 : insertRdbFiles(uris, alienContext);
1092 : 0 : return;
1093 : : }
1094 : 1028 : css::uno::Reference< css::lang::XServiceInfo > info;
1095 [ + - ][ + - ]: 1028 : if ((aElement >>= info) && info.is()) {
[ + - ][ + - ]
1096 [ + - ]: 1028 : insertLegacyFactory(info);
1097 : : return;
1098 : : }
1099 : : // At least revisions up to 1.7 of LanguageTool.oxt (incl. the bundled 1.4.0 in
1100 : : // module languagetool) contain an (actively registered) factory that does not
1101 : : // implement XServiceInfo (see <http://sourceforge.net/tracker/?
1102 : : // func=detail&aid=3526635&group_id=110216&atid=655717> "SingletonFactory should
1103 : : // implement XServiceInfo"); the old OServiceManager::insert
1104 : : // (stoc/source/servicemanager/servicemanager.cxx) silently did not add such
1105 : : // broken factories to its m_ImplementationNameMap, so ignore them here for
1106 : : // backwards compatibility of live-insertion of extensions, too (can go again
1107 : : // for incompatible LO 4):
1108 : : #if SUPD < 400
1109 : 0 : css::uno::Reference< css::lang::XSingleComponentFactory > legacy;
1110 [ # # ][ # # ]: 0 : if ((aElement >>= legacy) && legacy.is()) {
[ # # ][ # # ]
1111 : : SAL_WARN(
1112 : : "cppuhelper",
1113 : : "Ignored XSingleComponentFactory not implementing XServiceInfo");
1114 : : return;
1115 : : }
1116 : : #endif
1117 : : throw css::lang::IllegalArgumentException(
1118 [ # # ][ # # ]: 1028 : "Bad insert element", static_cast< cppu::OWeakObject * >(this), 0);
[ + - ]
1119 : : }
1120 : :
1121 : 2 : void ServiceManager::remove(css::uno::Any const & aElement)
1122 : : throw (
1123 : : css::lang::IllegalArgumentException,
1124 : : css::container::NoSuchElementException, css::uno::RuntimeException)
1125 : : {
1126 [ + - ]: 2 : css::uno::Sequence< css::beans::NamedValue > args;
1127 [ + - ][ - + ]: 2 : if (aElement >>= args) {
1128 [ # # ]: 0 : std::vector< rtl::OUString > uris;
1129 [ # # ]: 0 : for (sal_Int32 i = 0; i < args.getLength(); ++i) {
1130 [ # # ][ # # ]: 0 : if (args[i].Name == "uri") {
1131 : 0 : rtl::OUString uri;
1132 [ # # ][ # # ]: 0 : if (!(args[i].Value >>= uri)) {
1133 : : throw css::lang::IllegalArgumentException(
1134 : : "Bad uri argument",
1135 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this), 0);
1136 : : }
1137 [ # # ]: 0 : uris.push_back(uri);
1138 : : } else {
1139 : : throw css::lang::IllegalArgumentException(
1140 [ # # ]: 0 : "Bad argument " + args[i].Name,
1141 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this), 0);
1142 : : }
1143 : : }
1144 [ # # ]: 0 : removeRdbFiles(uris);
1145 : 0 : return;
1146 : : }
1147 : 2 : css::uno::Reference< css::lang::XServiceInfo > info;
1148 [ - + ][ # # ]: 2 : if ((aElement >>= info) && info.is()) {
[ - + ][ + - ]
1149 [ # # ][ # # ]: 0 : if (!removeLegacyFactory(info, true)) {
1150 : : throw css::container::NoSuchElementException(
1151 : : "Remove non-inserted factory object",
1152 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1153 : : }
1154 : : return;
1155 : : }
1156 : 2 : rtl::OUString impl;
1157 [ + - ]: 2 : if (aElement >>= impl) {
1158 : : // For live-removal of extensions:
1159 [ + - ]: 2 : removeImplementation(impl);
1160 : : return;
1161 : : }
1162 : : throw css::lang::IllegalArgumentException(
1163 [ # # ][ # # ]: 2 : "Bad remove element", static_cast< cppu::OWeakObject * >(this), 0);
[ + - ]
1164 : : }
1165 : :
1166 : : css::uno::Reference< css::container::XEnumeration >
1167 : 1106 : ServiceManager::createContentEnumeration(rtl::OUString const & aServiceName)
1168 : : throw (css::uno::RuntimeException)
1169 : : {
1170 [ + - ]: 1106 : std::vector< boost::shared_ptr< Implementation > > impls;
1171 : : {
1172 [ + - ]: 1106 : osl::MutexGuard g(rBHelper.rMutex);
1173 [ + - ]: 1106 : ImplementationMap::const_iterator i(data_.services.find(aServiceName));
1174 [ + + ]: 1106 : if (i != data_.services.end()) {
1175 [ + - ]: 613 : impls = i->second;
1176 [ + - ]: 1106 : }
1177 : : }
1178 [ + - ]: 1106 : std::vector< css::uno::Any > factories;
1179 [ + - ][ + + ]: 7414 : for (std::vector< boost::shared_ptr< Implementation > >::const_iterator i(
1180 [ + - ]: 1106 : impls.begin());
1181 : 3707 : i != impls.end(); ++i)
1182 : : {
1183 : 2601 : Implementation * impl = i->get();
1184 : : assert(impl != 0);
1185 : : {
1186 [ + - ]: 2601 : osl::MutexGuard g(rBHelper.rMutex);
1187 [ - + ]: 2601 : if (isDisposed()) {
1188 : 0 : factories.clear();
1189 : : break;
1190 : : }
1191 [ + + ]: 2601 : if (!impl->loaded) {
1192 : : // Postpone actual factory instantiation as long as possible (so
1193 : : // that e.g. opening LO's "Tools - Macros" menu does not try to
1194 : : // instantiate a JVM, which can lead to a synchronous error
1195 : : // dialog when no JVM is specified, and showing the dialog while
1196 : : // hovering over a menu can cause trouble):
1197 [ + - ][ + - ]: 1035 : impl->factory1 = new FactoryWrapper(this, impl->info);
[ + - ]
1198 : 2601 : impl->loaded = true;
1199 [ + - ][ + - ]: 2601 : }
1200 : : }
1201 [ + - ]: 2601 : if (impl->factory1.is()) {
1202 [ + - ][ + - ]: 2601 : factories.push_back(css::uno::makeAny(impl->factory1));
1203 [ # # ]: 0 : } else if (impl->factory2.is()) {
1204 [ # # ][ # # ]: 0 : factories.push_back(css::uno::makeAny(impl->factory2));
1205 : : } else {
1206 : : throw css::uno::DeploymentException(
1207 : 0 : ("Implementation " + impl->info->name
1208 : : + " does not provide a factory"),
1209 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1210 : : }
1211 : : }
1212 [ + - ][ + - ]: 1106 : return new ContentEnumeration(factories);
[ + - ]
1213 : : }
1214 : :
1215 : : css::uno::Reference< css::beans::XPropertySetInfo >
1216 : 435 : ServiceManager::getPropertySetInfo() throw (css::uno::RuntimeException) {
1217 : 435 : return this;
1218 : : }
1219 : :
1220 : 0 : void ServiceManager::setPropertyValue(
1221 : : rtl::OUString const & aPropertyName, css::uno::Any const &)
1222 : : throw (
1223 : : css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
1224 : : css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
1225 : : css::uno::RuntimeException)
1226 : : {
1227 [ # # ]: 0 : if (aPropertyName == "DefaultContext") {
1228 : : throw css::beans::PropertyVetoException(
1229 [ # # ][ # # ]: 0 : aPropertyName, static_cast< cppu::OWeakObject * >(this));
1230 : : } else {
1231 : : throw css::beans::UnknownPropertyException(
1232 [ # # ][ # # ]: 0 : aPropertyName, static_cast< cppu::OWeakObject * >(this));
1233 : : }
1234 : : }
1235 : :
1236 : 384950 : css::uno::Any ServiceManager::getPropertyValue(
1237 : : rtl::OUString const & PropertyName)
1238 : : throw (
1239 : : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1240 : : css::uno::RuntimeException)
1241 : : {
1242 [ - + ]: 384950 : if (PropertyName != "DefaultContext") {
1243 : : throw css::beans::UnknownPropertyException(
1244 [ # # ][ # # ]: 0 : PropertyName, static_cast< cppu::OWeakObject * >(this));
1245 : : }
1246 : : assert(context_.is());
1247 : 384950 : return css::uno::makeAny(context_);
1248 : : }
1249 : :
1250 : 0 : void ServiceManager::addPropertyChangeListener(
1251 : : rtl::OUString const & aPropertyName,
1252 : : css::uno::Reference< css::beans::XPropertyChangeListener > const &
1253 : : xListener)
1254 : : throw (
1255 : : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1256 : : css::uno::RuntimeException)
1257 : : {
1258 [ # # ][ # # ]: 0 : if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
[ # # ]
1259 : : throw css::beans::UnknownPropertyException(
1260 [ # # ][ # # ]: 0 : aPropertyName, static_cast< cppu::OWeakObject * >(this));
1261 : : }
1262 : : // DefaultContext does not change, so just treat it as an event listener:
1263 [ # # ]: 0 : return addEventListener(xListener.get());
1264 : : }
1265 : :
1266 : 0 : void ServiceManager::removePropertyChangeListener(
1267 : : rtl::OUString const & aPropertyName,
1268 : : css::uno::Reference< css::beans::XPropertyChangeListener > const &
1269 : : aListener)
1270 : : throw (
1271 : : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1272 : : css::uno::RuntimeException)
1273 : : {
1274 [ # # ][ # # ]: 0 : if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
[ # # ]
1275 : : throw css::beans::UnknownPropertyException(
1276 [ # # ][ # # ]: 0 : aPropertyName, static_cast< cppu::OWeakObject * >(this));
1277 : : }
1278 : : // DefaultContext does not change, so just treat it as an event listener:
1279 [ # # ]: 0 : return removeEventListener(aListener.get());
1280 : : }
1281 : :
1282 : 0 : void ServiceManager::addVetoableChangeListener(
1283 : : rtl::OUString const & PropertyName,
1284 : : css::uno::Reference< css::beans::XVetoableChangeListener > const &
1285 : : aListener)
1286 : : throw (
1287 : : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1288 : : css::uno::RuntimeException)
1289 : : {
1290 [ # # ][ # # ]: 0 : if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
[ # # ]
1291 : : throw css::beans::UnknownPropertyException(
1292 [ # # ][ # # ]: 0 : PropertyName, static_cast< cppu::OWeakObject * >(this));
1293 : : }
1294 : : // DefaultContext does not change, so just treat it as an event listener:
1295 [ # # ]: 0 : return addEventListener(aListener.get());
1296 : : }
1297 : :
1298 : 0 : void ServiceManager::removeVetoableChangeListener(
1299 : : rtl::OUString const & PropertyName,
1300 : : css::uno::Reference< css::beans::XVetoableChangeListener > const &
1301 : : aListener)
1302 : : throw (
1303 : : css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
1304 : : css::uno::RuntimeException)
1305 : : {
1306 [ # # ][ # # ]: 0 : if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
[ # # ]
1307 : : throw css::beans::UnknownPropertyException(
1308 [ # # ][ # # ]: 0 : PropertyName, static_cast< cppu::OWeakObject * >(this));
1309 : : }
1310 : : // DefaultContext does not change, so just treat it as an event listener:
1311 [ # # ]: 0 : return removeEventListener(aListener.get());
1312 : : }
1313 : :
1314 : 112 : css::uno::Sequence< css::beans::Property > ServiceManager::getProperties()
1315 : : throw (css::uno::RuntimeException)
1316 : : {
1317 : 112 : css::uno::Sequence< css::beans::Property > props(1);
1318 [ + - ][ + - ]: 112 : props[0] = getDefaultContextProperty();
1319 : 112 : return props;
1320 : : }
1321 : :
1322 : 0 : css::beans::Property ServiceManager::getPropertyByName(
1323 : : rtl::OUString const & aName)
1324 : : throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
1325 : : {
1326 [ # # ]: 0 : if (aName != "DefaultContext") {
1327 : : throw css::beans::UnknownPropertyException(
1328 [ # # ][ # # ]: 0 : aName, static_cast< cppu::OWeakObject * >(this));
1329 : : }
1330 : 0 : return getDefaultContextProperty();
1331 : : }
1332 : :
1333 : 0 : sal_Bool ServiceManager::hasPropertyByName(rtl::OUString const & Name)
1334 : : throw (css::uno::RuntimeException)
1335 : : {
1336 : 0 : return Name == "DefaultContext";
1337 : : }
1338 : :
1339 : 12 : void ServiceManager::disposing(css::lang::EventObject const & Source)
1340 : : throw (css::uno::RuntimeException)
1341 : : {
1342 : : removeLegacyFactory(
1343 : : css::uno::Reference< css::lang::XServiceInfo >(
1344 : : Source.Source, css::uno::UNO_QUERY_THROW),
1345 [ + - ]: 12 : false);
1346 : 12 : }
1347 : :
1348 : 355 : void ServiceManager::disposing() {
1349 [ + - ]: 355 : std::vector< css::uno::Reference< css::lang::XComponent > > comps;
1350 [ + - ]: 355 : Data clear;
1351 : : {
1352 [ + - ]: 355 : osl::MutexGuard g(rBHelper.rMutex);
1353 [ + + ]: 2738 : for (DynamicImplementations::const_iterator i(
1354 : 355 : data_.dynamicImplementations.begin());
1355 : 1369 : i != data_.dynamicImplementations.end(); ++i)
1356 : : {
1357 : : assert(i->second.get() != 0);
1358 [ + - ]: 1014 : if (i->second->component.is()) {
1359 [ + - ]: 1014 : comps.push_back(i->second->component);
1360 : : }
1361 : : }
1362 [ + - ]: 355 : data_.namedImplementations.swap(clear.namedImplementations);
1363 [ + - ]: 355 : data_.dynamicImplementations.swap(clear.dynamicImplementations);
1364 [ + - ]: 355 : data_.services.swap(clear.services);
1365 [ + - ][ + - ]: 355 : data_.singletons.swap(clear.singletons);
1366 : : }
1367 [ + - ][ + + ]: 2738 : for (std::vector<
1368 : : css::uno::Reference< css::lang::XComponent > >::const_iterator i(
1369 [ + - ]: 355 : comps.begin());
1370 : 1369 : i != comps.end(); ++i)
1371 : : {
1372 [ + - ]: 1014 : removeEventListenerFromComponent(*i);
1373 : 355 : }
1374 : 355 : }
1375 : :
1376 : 1014 : void ServiceManager::removeEventListenerFromComponent(
1377 : : css::uno::Reference< css::lang::XComponent > const & component)
1378 : : {
1379 : : assert(component.is());
1380 : : try {
1381 [ + - ][ + - ]: 1014 : component->removeEventListener(this);
[ + - ][ # # ]
1382 : 0 : } catch (css::uno::RuntimeException & e) {
1383 : : SAL_INFO(
1384 : : "cppuhelper",
1385 : : "Ignored removeEventListener RuntimeException " + e.Message);
1386 : : }
1387 : 1014 : }
1388 : :
1389 : 357 : void ServiceManager::readRdbs(rtl::OUString const & uris) {
1390 [ + + ]: 5044 : for (sal_Int32 i = 0; i != -1;) {
1391 : 4687 : rtl::OUString uri(uris.getToken(0, ' ', i));
1392 [ + + ]: 4687 : if (uri.isEmpty()) {
1393 : 380 : continue;
1394 : : }
1395 : : bool optional;
1396 : : bool directory;
1397 : 4307 : decodeRdbUri(&uri, &optional, &directory);
1398 [ + + ]: 4307 : if (directory) {
1399 [ + - ]: 160 : readRdbDirectory(uri, optional);
1400 : : } else {
1401 [ + - ]: 4307 : readRdbFile(uri, optional);
1402 : : }
1403 [ + + ]: 4687 : }
1404 : 357 : }
1405 : :
1406 : 160 : void ServiceManager::readRdbDirectory(rtl::OUString const & uri, bool optional)
1407 : : {
1408 : 160 : osl::Directory dir(uri);
1409 [ + - - ]: 160 : switch (dir.open()) {
[ + - ]
1410 : : case osl::FileBase::E_None:
1411 : 160 : break;
1412 : : case osl::FileBase::E_NOENT:
1413 [ # # ]: 0 : if (optional) {
1414 : : SAL_INFO("cppuhelper", "Ignored optional " << uri);
1415 : 160 : return;
1416 : : }
1417 : : // fall through
1418 : : default:
1419 : : throw css::uno::DeploymentException(
1420 : : "Cannot open directory " + uri,
1421 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1422 : : }
1423 : 480 : for (;;) {
1424 : 480 : rtl::OUString url;
1425 [ + + ][ + - ]: 480 : if (!nextDirectoryItem(dir, &url)) {
1426 : : break;
1427 : : }
1428 [ + - ][ + + ]: 800 : readRdbFile(url, false);
1429 [ + - ][ + - ]: 640 : }
1430 : : }
1431 : :
1432 : 4467 : void ServiceManager::readRdbFile(rtl::OUString const & uri, bool optional) {
1433 : : try {
1434 : : Parser(
1435 [ + + ][ + - ]: 4467 : uri, css::uno::Reference< css::uno::XComponentContext >(), &data_);
1436 : 640 : } catch (css::container::NoSuchElementException &) {
1437 [ - + ]: 320 : if (!optional) {
1438 : : throw css::uno::DeploymentException(
1439 : : uri + ": no such file",
1440 [ # # # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1441 : : }
1442 : : SAL_INFO("cppuhelper", "Ignored optional " << uri);
1443 : 0 : } catch (css::registry::InvalidRegistryException & e) {
1444 [ # # # # ]: 0 : if (!readLegacyRdbFile(uri)) {
1445 : : throw css::uno::DeploymentException(
1446 : : "InvalidRegistryException: " + e.Message,
1447 [ # # # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1448 : : }
1449 [ - + - + ]: 720 : } catch (css::uno::RuntimeException &) {
1450 [ - + ][ - + ]: 200 : if (!readLegacyRdbFile(uri)) {
1451 : 0 : throw;
1452 : : }
1453 : : }
1454 : 4467 : }
1455 : :
1456 : 200 : bool ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) {
1457 [ + - ]: 200 : Registry reg;
1458 [ + - ]: 200 : switch (reg.open(uri, REG_READONLY)) {
[ + + - ]
1459 : : case REG_NO_ERROR:
1460 : 196 : break;
1461 : : case REG_REGISTRY_NOT_EXISTS:
1462 : : case REG_INVALID_REGISTRY:
1463 : : {
1464 : : // Ignore empty rdb files (which are at least seen by subordinate
1465 : : // uno processes during extension registration; Registry::open can
1466 : : // fail on them if mmap(2) returns EINVAL for a zero length):
1467 : 4 : osl::DirectoryItem item;
1468 [ + - ][ + - ]: 4 : if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
1469 : 4 : osl::FileStatus status(osl_FileStatus_Mask_FileSize);
1470 [ + - ][ + - ]: 8 : if (item.getFileStatus(status) == osl::FileBase::E_None
[ + - ][ + - ]
1471 [ + - ]: 4 : && status.getFileSize() == 0)
1472 : : {
1473 : 4 : return true;
1474 [ - + ]: 4 : }
1475 [ + - ][ - + ]: 4 : }
1476 : : }
1477 : : // fall through
1478 : : default:
1479 : 0 : return false;
1480 : : }
1481 [ + - ]: 196 : RegistryKey rootKey;
1482 [ + - ][ - + ]: 196 : if (reg.openRootKey(rootKey) != REG_NO_ERROR) {
1483 : : throw css::uno::DeploymentException(
1484 : : "Failure reading legacy rdb file " + uri,
1485 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1486 : : }
1487 [ + - ]: 196 : RegistryKeyArray impls;
1488 [ + - ]: 196 : switch (rootKey.openSubKeys("IMPLEMENTATIONS", impls)) {
[ + + - ]
1489 : : case REG_NO_ERROR:
1490 : 98 : break;
1491 : : case REG_KEY_NOT_EXISTS:
1492 : 98 : return true;
1493 : : default:
1494 : : throw css::uno::DeploymentException(
1495 : : "Failure reading legacy rdb file " + uri,
1496 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1497 : : }
1498 [ + + ]: 294 : for (sal_uInt32 i = 0; i != impls.getLength(); ++i) {
1499 [ + - ]: 196 : RegistryKey implKey(impls.getElement(i));
1500 : : assert(implKey.getName().match("/IMPLEMENTATIONS/"));
1501 : : rtl::OUString name(
1502 [ + - ]: 196 : implKey.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
1503 : : boost::shared_ptr< Implementation > impl(
1504 : : new Implementation(
1505 : : name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"),
1506 [ + - ][ + - ]: 196 : readLegacyRdbString(uri, implKey, "UNO/LOCATION")));
[ + - ][ + - ]
[ + - ]
1507 [ - + ]: 196 : if (!data_.namedImplementations.insert(
1508 : : NamedImplementations::value_type(name, impl)).
1509 [ + - ][ + - ]: 196 : second)
[ + - ]
1510 : : {
1511 : : throw css::registry::InvalidRegistryException(
1512 : : uri + ": duplicate <implementation name=\"" + name + "\">",
1513 [ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
1514 : : }
1515 : : readLegacyRdbStrings(
1516 [ + - ]: 196 : uri, implKey, "UNO/SERVICES", &impl->info->services);
1517 [ + - ][ + + ]: 784 : for (std::vector< rtl::OUString >::const_iterator j(
1518 [ + - ]: 196 : impl->info->services.begin());
1519 : 392 : j != impl->info->services.end(); ++j)
1520 : : {
1521 [ + - ][ + - ]: 196 : data_.services[*j].push_back(impl);
1522 : : }
1523 : : readLegacyRdbStrings(
1524 [ + - ]: 196 : uri, implKey, "UNO/SINGLETONS", &impl->info->singletons);
1525 [ + - ][ - + ]: 392 : for (std::vector< rtl::OUString >::const_iterator j(
1526 [ + - ]: 196 : impl->info->singletons.begin());
1527 : 196 : j != impl->info->singletons.end(); ++j)
1528 : : {
1529 [ # # ][ # # ]: 0 : data_.singletons[*j].push_back(impl);
1530 : : }
1531 [ + - ][ + - ]: 196 : }
1532 [ + - ][ + - ]: 200 : return true;
[ + - ]
1533 : : }
1534 : :
1535 : 392 : rtl::OUString ServiceManager::readLegacyRdbString(
1536 : : rtl::OUString const & uri, RegistryKey & key, rtl::OUString const & path)
1537 : : {
1538 [ + - ]: 392 : RegistryKey subkey;
1539 : : RegValueType t;
1540 : 392 : sal_uInt32 s(0);
1541 [ + - ][ + - ]: 1176 : if (key.openKey(path, subkey) != REG_NO_ERROR
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
1542 [ + - ][ + - ]: 784 : || subkey.getValueInfo(rtl::OUString(), &t, &s) != REG_NO_ERROR
[ # # ]
1543 : : || t != RG_VALUETYPE_STRING
1544 : : || s == 0 || s > static_cast< sal_uInt32 >(SAL_MAX_INT32))
1545 : : {
1546 : : throw css::uno::DeploymentException(
1547 : : "Failure reading legacy rdb file " + uri,
1548 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1549 : : }
1550 : 392 : rtl::OUString val;
1551 [ + - ]: 392 : std::vector< char > v(s); // assuming sal_uInt32 fits into vector::size_type
1552 [ + - ][ + - ]: 1176 : if (subkey.getValue(rtl::OUString(), &v[0]) != REG_NO_ERROR
[ + - ]
[ + - - + ]
[ + - ]
[ - + # # ]
1553 [ + - ]: 392 : || v.back() != '\0'
1554 : : || !rtl_convertStringToUString(
1555 [ + - ]: 392 : &val.pData, &v[0], static_cast< sal_Int32 >(s - 1),
1556 : : RTL_TEXTENCODING_UTF8,
1557 : : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1558 : : | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1559 : 392 : | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
1560 : : {
1561 : : throw css::uno::DeploymentException(
1562 : : "Failure reading legacy rdb file " + uri,
1563 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1564 : : }
1565 [ + - ]: 392 : return val;
1566 : : }
1567 : :
1568 : 392 : void ServiceManager::readLegacyRdbStrings(
1569 : : rtl::OUString const & uri, RegistryKey & key, rtl::OUString const & path,
1570 : : std::vector< rtl::OUString > * strings)
1571 : : {
1572 : : assert(strings != 0);
1573 [ + - ]: 392 : RegistryKey subkey;
1574 [ + - ]: 392 : switch (key.openKey(path, subkey)) {
[ + + - ]
1575 : : case REG_NO_ERROR:
1576 : 392 : break;
1577 : : case REG_KEY_NOT_EXISTS:
1578 : 392 : return;
1579 : : default:
1580 : : throw css::uno::DeploymentException(
1581 : : "Failure reading legacy rdb file " + uri,
1582 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1583 : : }
1584 [ + - ]: 196 : rtl::OUString prefix(subkey.getName() + "/");
1585 [ + - ]: 196 : RegistryKeyNames names;
1586 [ + - ][ - + ]: 196 : if (subkey.getKeyNames(rtl::OUString(), names) != REG_NO_ERROR) {
1587 : : throw css::uno::DeploymentException(
1588 : : "Failure reading legacy rdb file " + uri,
1589 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1590 : : }
1591 [ + + ]: 392 : for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
1592 : : assert(names.getElement(i).match(prefix));
1593 [ + - ]: 196 : strings->push_back(names.getElement(i).copy(prefix.getLength()));
1594 [ + - ][ + - ]: 392 : }
[ + + ]
1595 : : }
1596 : :
1597 : 0 : void ServiceManager::insertRdbFiles(
1598 : : std::vector< rtl::OUString > const & uris,
1599 : : css::uno::Reference< css::uno::XComponentContext > const & alienContext)
1600 : : {
1601 [ # # ]: 0 : Data extra;
1602 [ # # ][ # # ]: 0 : for (std::vector< rtl::OUString >::const_iterator i(uris.begin());
1603 : 0 : i != uris.end(); ++i)
1604 : : {
1605 : : try {
1606 [ # # ][ # # ]: 0 : Parser(*i, alienContext, &extra);
1607 : 0 : } catch (css::container::NoSuchElementException &) {
1608 : : throw css::lang::IllegalArgumentException(
1609 : 0 : *i + ": no such file", static_cast< cppu::OWeakObject * >(this),
1610 [ # # # # ]: 0 : 0);
1611 [ # # # ]: 0 : } catch (css::registry::InvalidRegistryException & e) {
1612 : : throw css::lang::IllegalArgumentException(
1613 : : "InvalidRegistryException: " + e.Message,
1614 [ # # # # ]: 0 : static_cast< cppu::OWeakObject * >(this), 0);
1615 : : }
1616 : : }
1617 [ # # ]: 0 : insertExtraData(extra);
1618 : 0 : }
1619 : :
1620 : 1028 : void ServiceManager::insertLegacyFactory(
1621 : : css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo)
1622 : : {
1623 : : assert(factoryInfo.is());
1624 [ + - ][ + - ]: 1028 : rtl::OUString name(factoryInfo->getImplementationName());
1625 : : css::uno::Reference< css::lang::XSingleComponentFactory > f1(
1626 [ + - ]: 1028 : factoryInfo, css::uno::UNO_QUERY);
1627 : 1028 : css::uno::Reference< css::lang::XSingleServiceFactory > f2;
1628 [ - + ]: 1028 : if (!f1.is()) {
1629 : : f2 = css::uno::Reference< css::lang::XSingleServiceFactory >(
1630 [ # # ][ # # ]: 0 : factoryInfo, css::uno::UNO_QUERY);
1631 : : }
1632 : : css::uno::Reference< css::lang::XComponent > comp(
1633 [ + - ]: 1028 : factoryInfo, css::uno::UNO_QUERY);
1634 : : boost::shared_ptr< Implementation > impl(
1635 [ + - ][ + - ]: 1028 : new Implementation(name, f1, f2, comp));
[ + - ]
1636 [ + - ]: 1028 : Data extra;
1637 [ + + ]: 1028 : if (!name.isEmpty()) {
1638 : : extra.namedImplementations.insert(
1639 [ + - ][ + - ]: 183 : NamedImplementations::value_type(name, impl));
[ + - ]
1640 : : }
1641 : : extra.dynamicImplementations.insert(
1642 [ + - ][ + - ]: 1028 : DynamicImplementations::value_type(factoryInfo, impl));
[ + - ]
1643 : : css::uno::Sequence< rtl::OUString > services(
1644 [ + - ][ + - ]: 1028 : factoryInfo->getSupportedServiceNames());
1645 [ + + ]: 2056 : for (sal_Int32 i = 0; i != services.getLength(); ++i) {
1646 [ + - ][ + - ]: 1028 : impl->info->services.push_back(services[i]);
1647 [ + - ][ + - ]: 1028 : extra.services[services[i]].push_back(impl);
[ + - ]
1648 : : }
1649 [ + - ][ + - ]: 1028 : if (insertExtraData(extra) && comp.is()) {
[ + - ][ + - ]
1650 [ + - ][ + - ]: 1028 : comp->addEventListener(this);
[ + - ]
1651 [ + - ][ + - ]: 1028 : }
1652 : 1028 : }
1653 : :
1654 : 1028 : bool ServiceManager::insertExtraData(Data const & extra) {
1655 : : {
1656 [ + - ]: 1028 : osl::MutexGuard g(rBHelper.rMutex);
1657 [ - + ]: 1028 : if (isDisposed()) {
1658 : 0 : return false;
1659 : : }
1660 [ + + ]: 2422 : for (NamedImplementations::const_iterator i(
1661 : 1028 : extra.namedImplementations.begin());
1662 : 1211 : i != extra.namedImplementations.end(); ++i)
1663 : : {
1664 [ - + ]: 366 : if (data_.namedImplementations.find(i->first)
1665 [ + - ]: 366 : != data_.namedImplementations.end())
1666 : : {
1667 : : throw css::lang::IllegalArgumentException(
1668 : 0 : "Insert duplicate implementation name " + i->first,
1669 [ # # # # ]: 0 : static_cast< cppu::OWeakObject * >(this), 0);
1670 : : }
1671 : : }
1672 [ + + ]: 4112 : for (DynamicImplementations::const_iterator i(
1673 : 1028 : extra.dynamicImplementations.begin());
1674 : 2056 : i != extra.dynamicImplementations.end(); ++i)
1675 : : {
1676 [ - + ]: 2056 : if (data_.dynamicImplementations.find(i->first)
1677 [ + - ]: 2056 : != data_.dynamicImplementations.end())
1678 : : {
1679 : : throw css::lang::IllegalArgumentException(
1680 : : "Insert duplicate factory object",
1681 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this), 0);
1682 : : }
1683 : : }
1684 : : //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1685 : : data_.namedImplementations.insert(
1686 : : extra.namedImplementations.begin(),
1687 [ + - ]: 1028 : extra.namedImplementations.end());
1688 : : data_.dynamicImplementations.insert(
1689 : : extra.dynamicImplementations.begin(),
1690 [ + - ]: 1028 : extra.dynamicImplementations.end());
1691 [ + - ]: 1028 : insertImplementationMap(&data_.services, extra.services);
1692 [ + - ][ + - ]: 1028 : insertImplementationMap(&data_.singletons, extra.singletons);
[ + - ]
1693 : : }
1694 : : //TODO: Updating the component context singleton data should be part of the
1695 : : // atomic service manager update:
1696 [ - + ]: 1028 : if (!extra.singletons.empty()) {
1697 : : assert(context_.is());
1698 : : css::uno::Reference< css::container::XNameContainer > cont(
1699 [ # # ]: 0 : context_, css::uno::UNO_QUERY_THROW);
1700 [ # # ]: 0 : for (ImplementationMap::const_iterator i(extra.singletons.begin());
1701 : 0 : i != extra.singletons.end(); ++i)
1702 : : {
1703 : 0 : rtl::OUString name("/singletons/" + i->first);
1704 : : //TODO: Update should be atomic:
1705 : : try {
1706 [ # # ][ # # ]: 0 : cont->removeByName(name + "/arguments");
[ # # ]
1707 [ # # ]: 0 : } catch (const css::container::NoSuchElementException &) {}
1708 : : assert(!i->second.empty());
1709 : : assert(i->second[0].get() != 0);
1710 : : SAL_INFO_IF(
1711 : : i->second.size() > 1, "cppuhelper",
1712 : : "Arbitrarily chosing " << i->second[0]->info->name
1713 : : << " among multiple implementations for singleton "
1714 : : << i->first);
1715 : : try {
1716 [ # # ]: 0 : cont->insertByName(
1717 [ # # ][ # # ]: 0 : name + "/service", css::uno::Any(i->second[0]->info->name));
1718 [ # # # # ]: 0 : } catch (css::container::ElementExistException &) {
1719 [ # # ]: 0 : cont->replaceByName(
1720 [ # # # # ]: 0 : name + "/service", css::uno::Any(i->second[0]->info->name));
1721 : : }
1722 : : try {
1723 [ # # ][ # # ]: 0 : cont->insertByName(name, css::uno::Any());
1724 [ # # # # ]: 0 : } catch (css::container::ElementExistException &) {
1725 : : SAL_INFO("cppuhelper", "Overwriting singleton " << i->first);
1726 [ # # # # ]: 0 : cont->replaceByName(name, css::uno::Any());
1727 : : }
1728 : 0 : }
1729 : : }
1730 : 1028 : return true;
1731 : : }
1732 : :
1733 : 0 : void ServiceManager::removeRdbFiles(std::vector< rtl::OUString > const & uris) {
1734 : : // The underlying data structures make this function somewhat inefficient,
1735 : : // but the assumption is that it is rarely called (and that if it is called,
1736 : : // it is called with a uris vector of size one):
1737 [ # # ]: 0 : std::vector< boost::shared_ptr< Implementation > > clear;
1738 : : {
1739 [ # # ]: 0 : osl::MutexGuard g(rBHelper.rMutex);
1740 [ # # ][ # # ]: 0 : for (std::vector< rtl::OUString >::const_iterator i(uris.begin());
1741 : 0 : i != uris.end(); ++i)
1742 : : {
1743 [ # # ]: 0 : for (NamedImplementations::iterator j(
1744 : 0 : data_.namedImplementations.begin());
1745 : 0 : j != data_.namedImplementations.end();)
1746 : : {
1747 : : assert(j->second.get() != 0);
1748 [ # # ]: 0 : if (j->second->info->uri == *i) {
1749 [ # # ]: 0 : clear.push_back(j->second);
1750 : : //TODO: The below leaves data_ in an inconsistent state upon
1751 : : // exceptions:
1752 : : removeFromImplementationMap(
1753 [ # # ]: 0 : &data_.services, j->second->info->services, j->second);
1754 : : removeFromImplementationMap(
1755 : 0 : &data_.singletons, j->second->info->singletons,
1756 [ # # ]: 0 : j->second);
1757 [ # # ]: 0 : data_.namedImplementations.erase(j++);
1758 : : } else {
1759 : 0 : ++j;
1760 : : }
1761 : : }
1762 [ # # ]: 0 : }
1763 : 0 : }
1764 : : //TODO: Update the component context singleton data
1765 : 0 : }
1766 : :
1767 : 12 : bool ServiceManager::removeLegacyFactory(
1768 : : css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
1769 : : bool removeListener)
1770 : : {
1771 : : assert(factoryInfo.is());
1772 [ + - ]: 12 : boost::shared_ptr< Implementation > clear;
1773 : 12 : css::uno::Reference< css::lang::XComponent > comp;
1774 : : {
1775 [ + - ]: 12 : osl::MutexGuard g(rBHelper.rMutex);
1776 : : DynamicImplementations::iterator i(
1777 [ + - ]: 12 : data_.dynamicImplementations.find(factoryInfo));
1778 [ - + ]: 12 : if (i == data_.dynamicImplementations.end()) {
1779 : 0 : return isDisposed();
1780 : : }
1781 : : assert(i->second.get() != 0);
1782 [ + - ]: 12 : clear = i->second;
1783 : : //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1784 : : removeFromImplementationMap(
1785 [ + - ]: 12 : &data_.services, i->second->info->services, i->second);
1786 : : removeFromImplementationMap(
1787 [ + - ]: 12 : &data_.singletons, i->second->info->singletons, i->second);
1788 [ + - ]: 12 : if (!i->second->info->name.isEmpty()) {
1789 [ + - ]: 12 : data_.namedImplementations.erase(i->second->info->name);
1790 : : }
1791 [ + - ]: 12 : data_.dynamicImplementations.erase(i);
1792 [ - + ]: 12 : if (removeListener) {
1793 [ # # ]: 12 : comp = i->second->component;
1794 [ + - ][ + - ]: 12 : }
1795 : : }
1796 [ - + ]: 12 : if (comp.is()) {
1797 [ # # ]: 0 : removeEventListenerFromComponent(comp);
1798 : : }
1799 [ + - ]: 12 : return true;
1800 : : }
1801 : :
1802 : 2 : void ServiceManager::removeImplementation(rtl::OUString name) {
1803 : : // The underlying data structures make this function somewhat inefficient,
1804 : : // but the assumption is that it is rarely called:
1805 [ + - ]: 2 : boost::shared_ptr< Implementation > clear;
1806 : : {
1807 [ + - ]: 2 : osl::MutexGuard g(rBHelper.rMutex);
1808 [ - + ]: 2 : if (isDisposed()) {
1809 : 2 : return;
1810 : : }
1811 [ + - ]: 2 : NamedImplementations::iterator i(data_.namedImplementations.find(name));
1812 [ - + ]: 2 : if (i == data_.namedImplementations.end()) {
1813 : : throw css::container::NoSuchElementException(
1814 : : "Remove non-inserted implementation " + name,
1815 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1816 : : }
1817 : : assert(i->second.get() != 0);
1818 [ + - ]: 2 : clear = i->second;
1819 : : //TODO: The below leaves data_ in an inconsistent state upon exceptions:
1820 : : removeFromImplementationMap(
1821 [ + - ]: 2 : &data_.services, i->second->info->services, i->second);
1822 : : removeFromImplementationMap(
1823 [ + - ]: 2 : &data_.singletons, i->second->info->singletons, i->second);
1824 [ + - ]: 28 : for (DynamicImplementations::iterator j(
1825 : 2 : data_.dynamicImplementations.begin());
1826 : 14 : j != data_.dynamicImplementations.end(); ++j)
1827 : : {
1828 [ + + ]: 14 : if (j->second == i->second) {
1829 [ + - ]: 2 : data_.dynamicImplementations.erase(j);
1830 : 2 : break;
1831 : : }
1832 : : }
1833 [ + - ][ + - ]: 2 : data_.namedImplementations.erase(i);
[ + - ]
1834 [ + - ][ + - ]: 2 : }
1835 : : }
1836 : :
1837 : 1329271 : boost::shared_ptr< Implementation > ServiceManager::findServiceImplementation(
1838 : : css::uno::Reference< css::uno::XComponentContext > const & context,
1839 : : rtl::OUString const & specifier)
1840 : : {
1841 [ + - ]: 1329271 : boost::shared_ptr< Implementation > impl;
1842 : : bool loaded;
1843 : : {
1844 [ + - ]: 1329271 : osl::MutexGuard g(rBHelper.rMutex);
1845 [ + - ]: 1329271 : ImplementationMap::const_iterator i(data_.services.find(specifier));
1846 [ + + ]: 1329271 : if (i == data_.services.end()) {
1847 : : NamedImplementations::const_iterator j(
1848 [ + - ]: 162823 : data_.namedImplementations.find(specifier));
1849 [ + + ]: 162823 : if (j == data_.namedImplementations.end()) {
1850 : : SAL_INFO("cppuhelper", "No implementation for " << specifier);
1851 [ + - ]: 128757 : return boost::shared_ptr< Implementation >();
1852 : : }
1853 [ + - ]: 162823 : impl = j->second;
1854 : : } else {
1855 : : assert(!i->second.empty());
1856 : : SAL_INFO_IF(
1857 : : i->second.size() > 1, "cppuhelper",
1858 : : "Arbitrarily chosing " << i->second[0]->info->name
1859 : : << " among multiple implementations for " << i->first);
1860 [ + - ]: 1166448 : impl = i->second[0];
1861 : : }
1862 : : assert(impl.get() != 0);
1863 [ + - ][ + + ]: 1329271 : loaded = impl->loaded;
1864 : : }
1865 : : //TODO: There is a race here, as the relevant service factory can be removed
1866 : : // while the mutex is unlocked and loading can thus fail, as the entity from
1867 : : // which to load can disappear once the service factory is removed.
1868 [ + + ]: 1329271 : if (!loaded) {
1869 : 19442 : css::uno::Reference< css::lang::XSingleComponentFactory > f1;
1870 : 19442 : css::uno::Reference< css::lang::XSingleServiceFactory > f2;
1871 [ + - ]: 19442 : loadImplementation(context, impl->info, &f1, &f2);
1872 [ + - ]: 19442 : osl::MutexGuard g(rBHelper.rMutex);
1873 [ + - ][ + + ]: 19442 : if (!(isDisposed() || impl->loaded)) {
[ + + ]
1874 : 19441 : impl->loaded = true;
1875 [ + - ]: 19441 : impl->factory1 = f1;
1876 [ + - ]: 19441 : impl->factory2 = f2;
1877 [ + - ]: 19442 : }
1878 : : }
1879 [ + - ][ + - ]: 1329271 : return impl;
1880 : : }
1881 : :
1882 : : css::uno::Reference< css::uno::XInterface >
1883 : 328 : FactoryWrapper::createInstanceWithContext(
1884 : : css::uno::Reference< css::uno::XComponentContext > const & Context)
1885 : : throw (css::uno::Exception, css::uno::RuntimeException)
1886 : : {
1887 : 328 : loadImplementation(Context);
1888 : 328 : return factory1_.is()
1889 : 328 : ? factory1_->createInstanceWithContext(Context)
1890 [ + - ]: 656 : : factory2_->createInstance();
1891 : : }
1892 : :
1893 : : css::uno::Reference< css::uno::XInterface >
1894 : 2513 : FactoryWrapper::createInstanceWithArgumentsAndContext(
1895 : : css::uno::Sequence< css::uno::Any > const & Arguments,
1896 : : css::uno::Reference< css::uno::XComponentContext > const & Context)
1897 : : throw (css::uno::Exception, css::uno::RuntimeException)
1898 : : {
1899 : 2513 : loadImplementation(Context);
1900 : 2513 : return factory1_.is()
1901 : 2513 : ? factory1_->createInstanceWithArgumentsAndContext(Arguments, Context)
1902 [ + - ]: 5026 : : factory2_->createInstanceWithArguments(Arguments);
1903 : : }
1904 : :
1905 : 9 : css::uno::Reference< css::uno::XInterface > FactoryWrapper::createInstance()
1906 : : throw (css::uno::Exception, css::uno::RuntimeException)
1907 : : {
1908 [ + - ]: 9 : loadImplementation(manager_->getContext());
1909 : 9 : return factory1_.is()
1910 [ + - ]: 9 : ? factory1_->createInstanceWithContext(manager_->getContext())
1911 [ + - ][ + - ]: 18 : : factory2_->createInstance();
[ # # ][ # # ]
[ + - ][ # # ]
[ + - ]
1912 : : }
1913 : :
1914 : : css::uno::Reference< css::uno::XInterface >
1915 : 0 : FactoryWrapper::createInstanceWithArguments(
1916 : : css::uno::Sequence< css::uno::Any > const & Arguments)
1917 : : throw (css::uno::Exception, css::uno::RuntimeException)
1918 : : {
1919 [ # # ]: 0 : loadImplementation(manager_->getContext());
1920 : 0 : return factory1_.is()
1921 [ # # ]: 0 : ? factory1_->createInstanceWithArgumentsAndContext(
1922 : 0 : Arguments, manager_->getContext())
1923 [ # # ][ # # ]: 0 : : factory2_->createInstanceWithArguments(Arguments);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1924 : : }
1925 : :
1926 : 2352 : rtl::OUString FactoryWrapper::getImplementationName()
1927 : : throw (css::uno::RuntimeException)
1928 : : {
1929 : 2352 : return info_->name;
1930 : : }
1931 : :
1932 : 0 : sal_Bool FactoryWrapper::supportsService(rtl::OUString const & ServiceName)
1933 : : throw (css::uno::RuntimeException)
1934 : : {
1935 [ # # ]: 0 : css::uno::Sequence< rtl::OUString > names(getSupportedServiceNames());
1936 [ # # ]: 0 : for (sal_Int32 i = 0; i != names.getLength(); ++i) {
1937 [ # # ][ # # ]: 0 : if (ServiceName == names[i]) {
1938 : 0 : return true;
1939 : : }
1940 : : }
1941 [ # # ]: 0 : return false;
1942 : : }
1943 : :
1944 : 23 : css::uno::Sequence< rtl::OUString > FactoryWrapper::getSupportedServiceNames()
1945 : : throw (css::uno::RuntimeException)
1946 : : {
1947 [ - + ]: 23 : if (info_->services.size() > static_cast< sal_uInt32 >(SAL_MAX_INT32)) {
1948 : : throw css::uno::RuntimeException(
1949 : 0 : "Implementation " + info_->name + " supports too many services",
1950 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1951 : : }
1952 : : css::uno::Sequence< rtl::OUString > names(
1953 : 23 : static_cast< sal_Int32 >(info_->services.size()));
1954 : 23 : sal_Int32 i = 0;
1955 [ + - ][ + + ]: 214 : for (std::vector< rtl::OUString >::const_iterator j(
1956 [ + - ]: 23 : info_->services.begin());
1957 : 107 : j != info_->services.end(); ++j)
1958 : : {
1959 [ + - ]: 84 : names[i++] = *j;
1960 : : }
1961 : 23 : return names;
1962 : : }
1963 : :
1964 : 2850 : void FactoryWrapper::loadImplementation(
1965 : : css::uno::Reference< css::uno::XComponentContext > const & context)
1966 : : {
1967 : : {
1968 [ + - ]: 2850 : osl::MutexGuard g(mutex_);
1969 [ + + ]: 2850 : if (loaded_) {
1970 : 2850 : return;
1971 [ + - ][ + + ]: 2850 : }
1972 : : }
1973 : 964 : css::uno::Reference< css::lang::XSingleComponentFactory > f1;
1974 : 964 : css::uno::Reference< css::lang::XSingleServiceFactory > f2;
1975 : : //TODO: There is a race here, as the relevant service factory can already
1976 : : // have been removed and loading can thus fail, as the entity from which to
1977 : : // load can disappear once the service factory is removed:
1978 [ + - ]: 2850 : manager_->loadImplementation(context, info_, &f1, &f2);
1979 [ - + ][ # # ]: 964 : if (!(f1.is() || f2.is())) {
[ - + ]
1980 : : throw css::uno::DeploymentException(
1981 : 0 : "Implementation " + info_->name + " does not provide a factory",
1982 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
1983 : : }
1984 [ + - ]: 964 : osl::MutexGuard g(mutex_);
1985 [ + - ]: 964 : if (!loaded_) {
1986 : 964 : loaded_ = true;
1987 [ + - ]: 964 : factory1_ = f1;
1988 [ + - ]: 964 : factory2_ = f2;
1989 [ + - ]: 964 : }
1990 : : }
1991 : :
1992 : 357 : css::uno::Reference< css::uno::XComponentContext > bootstrapComponentContext(
1993 : : css::uno::Reference< css::registry::XSimpleRegistry > const & typeRegistry,
1994 : : rtl::OUString const & serviceUris, rtl::Bootstrap const & bootstrap)
1995 : : {
1996 [ + - ]: 357 : rtl::Reference< ServiceManager > smgr(new ServiceManager(serviceUris));
1997 : 357 : cppu::ContextEntry_Init entry;
1998 [ + - ]: 357 : std::vector< cppu::ContextEntry_Init > context_values;
1999 : : context_values.push_back(
2000 : : cppu::ContextEntry_Init(
2001 : : "/singletons/com.sun.star.lang.theServiceManager",
2002 : : css::uno::makeAny(
2003 : : css::uno::Reference< css::uno::XInterface >(
2004 : 357 : static_cast< cppu::OWeakObject * >(smgr.get()))),
2005 [ + - ][ + - ]: 357 : false));
[ + - ]
2006 : : context_values.push_back( //TODO: from services.rdb?
2007 : : cppu::ContextEntry_Init(
2008 : : "/singletons/com.sun.star.reflection.theTypeDescriptionManager",
2009 : : css::uno::makeAny(
2010 : : rtl::OUString("com.sun.star.comp.stoc.TypeDescriptionManager")),
2011 [ + - ][ + - ]: 357 : true /*TODO: false?*/));
2012 : : context_values.push_back( //TODO: from services.rdb?
2013 : : cppu::ContextEntry_Init(
2014 : : "/singletons/com.sun.star.util.theMacroExpander",
2015 : : css::uno::makeAny(
2016 : : cppuhelper::detail::create_bootstrap_macro_expander_factory()),
2017 [ + - ][ + - ]: 357 : true));
[ + - ]
2018 : 357 : Data const & data = smgr->getData();
2019 [ + + ]: 7896 : for (ImplementationMap::const_iterator i(data.singletons.begin());
2020 : 3948 : i != data.singletons.end(); ++i)
2021 : : {
2022 : : assert(!i->second.empty());
2023 : : assert(i->second[0].get() != 0);
2024 : : SAL_INFO_IF(
2025 : : i->second.size() > 1, "cppuhelper",
2026 : : "Arbitrarily chosing " << i->second[0]->info->name
2027 : : << " among multiple implementations for " << i->first);
2028 : : context_values.push_back(
2029 : : cppu::ContextEntry_Init(
2030 : 3591 : "/singletons/" + i->first,
2031 [ + - + - ]: 7182 : css::uno::makeAny(i->second[0]->info->name), true));
2032 : : }
2033 [ + - ]: 357 : cppu::add_access_control_entries(&context_values, bootstrap);
2034 : : assert(!context_values.empty());
2035 : : css::uno::Reference< css::uno::XComponentContext > context(
2036 : : createComponentContext(
2037 : 357 : &context_values[0], context_values.size(),
2038 [ + - ]: 714 : css::uno::Reference< css::uno::XComponentContext >()));
2039 [ + - ]: 357 : smgr->setContext(context);
2040 : : css::uno::Reference< css::container::XHierarchicalNameAccess > tdmgr(
2041 [ + - ]: 357 : context->getValueByName(
2042 : 357 : "/singletons/com.sun.star.reflection.theTypeDescriptionManager"),
2043 [ + - ][ + - ]: 357 : css::uno::UNO_QUERY_THROW);
2044 [ + - ]: 357 : if (typeRegistry.is()) {
2045 [ + - ]: 357 : css::uno::Sequence< css::uno::Any > arg(1);
2046 [ + - ][ + - ]: 357 : arg[0] <<= typeRegistry;
2047 : : css::uno::Reference< css::container::XSet >(
2048 [ + - ][ + - ]: 714 : tdmgr, css::uno::UNO_QUERY_THROW)->
2049 : : insert(
2050 : : css::uno::makeAny(
2051 : 357 : smgr->createInstanceWithArgumentsAndContext(
2052 : : ("com.sun.star.comp.stoc"
2053 : : ".RegistryTypeDescriptionProvider"),
2054 [ + - ][ + - ]: 714 : arg, context)));
[ + - ][ + - ]
2055 : : }
2056 [ + - ]: 357 : cppu::installTypeDescriptionManager(tdmgr);
2057 : 357 : return context;
2058 : : }
2059 : :
2060 : 1071 : rtl::OUString getBootstrapVariable(
2061 : : rtl::Bootstrap const & bootstrap, rtl::OUString const & name)
2062 : : {
2063 : 1071 : rtl::OUString v;
2064 [ - + ]: 1071 : if (!bootstrap.getFrom(name, v)) {
2065 : : throw css::uno::DeploymentException(
2066 : : "Cannot obtain " + name + " from uno ini",
2067 [ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
2068 : : }
2069 : 1071 : return v;
2070 : : }
2071 : :
2072 : 1201 : css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbFile(
2073 : : rtl::OUString const & uri, bool optional,
2074 : : css::uno::Reference< css::registry::XSimpleRegistry > const & lastRegistry,
2075 : : css::uno::Reference< css::lang::XSingleServiceFactory > const &
2076 : : simpleRegistryFactory,
2077 : : css::uno::Reference< css::lang::XSingleServiceFactory > const &
2078 : : nestedRegistryFactory)
2079 : : {
2080 : : assert(simpleRegistryFactory.is() && nestedRegistryFactory.is());
2081 : : try {
2082 : : css::uno::Reference< css::registry::XSimpleRegistry > simple(
2083 [ + - ][ + - ]: 1201 : simpleRegistryFactory->createInstance(), css::uno::UNO_QUERY_THROW);
[ + - ]
2084 [ + + ][ + - ]: 1201 : simple->open(uri, true, false);
2085 [ + + ]: 881 : if (lastRegistry.is()) {
2086 : : css::uno::Reference< css::registry::XSimpleRegistry > nested(
2087 [ + - ]: 524 : nestedRegistryFactory->createInstance(),
2088 [ + - ][ + - ]: 524 : css::uno::UNO_QUERY_THROW);
2089 [ + - ]: 524 : css::uno::Sequence< css::uno::Any > args(2);
2090 [ + - ][ + - ]: 524 : args[0] <<= lastRegistry;
2091 [ + - ][ + - ]: 524 : args[1] <<= simple;
2092 : : css::uno::Reference< css::lang::XInitialization >(
2093 [ + - ][ + - ]: 1048 : nested, css::uno::UNO_QUERY_THROW)->
2094 [ + - ]: 524 : initialize(args);
2095 [ + - ]: 524 : return nested;
2096 : : } else {
2097 : 357 : return simple;
2098 : 1521 : }
2099 [ - + ]: 640 : } catch (css::registry::InvalidRegistryException & e) {
2100 [ - + ]: 320 : if (!optional) {
2101 : : throw css::uno::DeploymentException(
2102 : : "Invalid registry " + uri + ":" + e.Message,
2103 [ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
2104 : : }
2105 : : SAL_INFO("cppuhelper", "Ignored optional " << uri);
2106 : 320 : return lastRegistry;
2107 : : }
2108 : : }
2109 : :
2110 : 160 : css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbDirectory(
2111 : : rtl::OUString const & uri, bool optional,
2112 : : css::uno::Reference< css::registry::XSimpleRegistry > const & lastRegistry,
2113 : : css::uno::Reference< css::lang::XSingleServiceFactory > const &
2114 : : simpleRegistryFactory,
2115 : : css::uno::Reference< css::lang::XSingleServiceFactory > const &
2116 : : nestedRegistryFactory)
2117 : : {
2118 : : assert(simpleRegistryFactory.is() && nestedRegistryFactory.is());
2119 : 160 : osl::Directory dir(uri);
2120 [ + - - ]: 160 : switch (dir.open()) {
[ + - ]
2121 : : case osl::FileBase::E_None:
2122 : 160 : break;
2123 : : case osl::FileBase::E_NOENT:
2124 [ # # ]: 0 : if (optional) {
2125 : : SAL_INFO("cppuhelper", "Ignored optional " << uri);
2126 : 0 : return lastRegistry;
2127 : : }
2128 : : // fall through
2129 : : default:
2130 : : throw css::uno::DeploymentException(
2131 : : "Cannot open directory " + uri,
2132 [ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
2133 : : }
2134 : 160 : css::uno::Reference< css::registry::XSimpleRegistry > last(lastRegistry);
2135 : 320 : for (;;) {
2136 : 480 : rtl::OUString fileUri;
2137 [ + + ][ + - ]: 480 : if (!nextDirectoryItem(dir, &fileUri)) {
2138 : : break;
2139 : : }
2140 : : last = readTypeRdbFile(
2141 : : fileUri, optional, last, simpleRegistryFactory,
2142 [ + - ][ + - ]: 800 : nestedRegistryFactory);
[ + + ]
2143 : 480 : }
2144 [ + - ]: 160 : return last;
2145 : : }
2146 : :
2147 : 357 : css::uno::Reference< css::registry::XSimpleRegistry > createTypeRegistry(
2148 : : rtl::OUString const & uris, rtl::OUString const & libraryDirectoryUri)
2149 : : {
2150 : : css::uno::Reference< css::lang::XMultiComponentFactory > factory(
2151 [ + - ]: 357 : cppu::bootstrapInitialSF(libraryDirectoryUri));
2152 : : css::uno::Reference< css::lang::XSingleServiceFactory > simpleRegs(
2153 : : cppu::loadSharedLibComponentFactory(
2154 : : "bootstrap.uno" SAL_DLLEXTENSION, libraryDirectoryUri,
2155 : : "com.sun.star.comp.stoc.SimpleRegistry",
2156 : : css::uno::Reference< css::lang::XMultiServiceFactory >(
2157 : : factory, css::uno::UNO_QUERY_THROW),
2158 : : css::uno::Reference< css::registry::XRegistryKey >()),
2159 [ + - ][ + - ]: 357 : css::uno::UNO_QUERY_THROW);
[ + - ]
2160 : : css::uno::Reference< css::lang::XSingleServiceFactory > nestedRegs(
2161 : : cppu::loadSharedLibComponentFactory(
2162 : : "bootstrap.uno" SAL_DLLEXTENSION, libraryDirectoryUri,
2163 : : "com.sun.star.comp.stoc.NestedRegistry",
2164 : : css::uno::Reference< css::lang::XMultiServiceFactory >(
2165 : : factory, css::uno::UNO_QUERY_THROW),
2166 : : css::uno::Reference< css::registry::XRegistryKey >()),
2167 [ + - ][ + - ]: 357 : css::uno::UNO_QUERY_THROW);
[ + - ]
2168 : 357 : css::uno::Reference< css::registry::XSimpleRegistry > reg;
2169 [ + + ]: 1878 : for (sal_Int32 i = 0; i != -1;) {
2170 : 1521 : rtl::OUString uri(uris.getToken(0, ' ', i));
2171 [ + + ]: 1521 : if (uri.isEmpty()) {
2172 : 480 : continue;
2173 : : }
2174 : : bool optional;
2175 : : bool directory;
2176 : 1041 : decodeRdbUri(&uri, &optional, &directory);
2177 : : reg = directory
2178 : : ? readTypeRdbDirectory(uri, optional, reg, simpleRegs, nestedRegs)
2179 [ + - ][ + - ]: 2562 : : readTypeRdbFile(uri, optional, reg, simpleRegs, nestedRegs);
[ + - ][ + + ]
[ + + ]
2180 : 1521 : }
2181 : 357 : return reg;
2182 : : }
2183 : :
2184 : : }
2185 : :
2186 : : css::uno::Reference< css::uno::XComponentContext >
2187 : 357 : cppu::defaultBootstrap_InitialComponentContext(rtl::OUString const & iniUri)
2188 : : SAL_THROW((css::uno::Exception))
2189 : : {
2190 : 357 : rtl::Bootstrap bs(iniUri);
2191 [ - + ]: 357 : if (bs.getHandle() == 0) {
2192 : : throw css::uno::DeploymentException(
2193 : : "Cannot open uno ini " + iniUri,
2194 [ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
2195 : : }
2196 : : return bootstrapComponentContext(
2197 : : createTypeRegistry(
2198 : : getBootstrapVariable(bs, "UNO_TYPES"),
2199 : : getBootstrapVariable(bs, "URE_INTERNAL_LIB_DIR")),
2200 [ + - ][ + - ]: 357 : getBootstrapVariable(bs, "UNO_SERVICES"), bs);
[ + - ][ + - ]
[ + - ]
2201 : : }
2202 : :
2203 : : css::uno::Reference< css::uno::XComponentContext >
2204 : 357 : cppu::defaultBootstrap_InitialComponentContext()
2205 : : SAL_THROW((css::uno::Exception))
2206 : : {
2207 [ + - ]: 357 : return defaultBootstrap_InitialComponentContext(getUnoIniUri());
2208 : : }
2209 : :
2210 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|