LCOV - code coverage report
Current view: top level - cppuhelper/source - servicemanager.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 263 836 31.5 %
Date: 2014-04-14 Functions: 24 76 31.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10