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

Generated by: LCOV version 1.10