LCOV - code coverage report
Current view: top level - cppuhelper/source - servicemanager.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 511 818 62.5 %
Date: 2015-06-13 12:38:46 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        1382 : void insertImplementationMap(
      61             :     cppuhelper::ServiceManager::Data::ImplementationMap * destination,
      62             :     cppuhelper::ServiceManager::Data::ImplementationMap const & source)
      63             : {
      64             :     assert(destination != 0);
      65        6219 :     for (cppuhelper::ServiceManager::Data::ImplementationMap::const_iterator i(
      66        1382 :              source.begin());
      67        4146 :          i != source.end(); ++i)
      68             :     {
      69             :         std::vector<
      70             :             boost::shared_ptr<
      71             :                 cppuhelper::ServiceManager::Data::Implementation > > & impls
      72         691 :             = (*destination)[i->first];
      73         691 :         impls.insert(impls.end(), i->second.begin(), i->second.end());
      74             :     }
      75        1382 : }
      76             : 
      77          14 : 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          63 :     for (std::vector< rtl::OUString >::const_iterator i(elements.begin());
      87          42 :          i != elements.end(); ++i)
      88             :     {
      89             :         cppuhelper::ServiceManager::Data::ImplementationMap::iterator j(
      90           7 :             map->find(*i));
      91             :         assert(j != map->end());
      92             :         std::vector<
      93             :             boost::shared_ptr<
      94             :                 cppuhelper::ServiceManager::Data::Implementation > >::iterator
      95           7 :             k(std::find(j->second.begin(), j->second.end(), implementation));
      96             :         assert(k != j->second.end());
      97           7 :         j->second.erase(k);
      98           7 :         if (j->second.empty()) {
      99           7 :             map->erase(j);
     100             :         }
     101             :     }
     102          14 : }
     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        3757 : 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        3759 : Parser::Parser(
     137             :     rtl::OUString const & uri,
     138             :     css::uno::Reference< css::uno::XComponentContext > const & alienContext,
     139             :     cppuhelper::ServiceManager::Data * data):
     140        3759 :     reader_(uri), alienContext_(alienContext), data_(data)
     141             : {
     142             :     assert(data != 0);
     143             :     int ucNsId = reader_.registerNamespaceIri(
     144             :         xmlreader::Span(
     145             :             RTL_CONSTASCII_STRINGPARAM(
     146        3757 :                 "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        3757 :     for (State state = STATE_BEGIN;;) {
     151      996081 :         xmlreader::Span name;
     152             :         int nsId;
     153             :         xmlreader::XmlReader::Result res = reader_.nextItem(
     154      996081 :             xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
     155      996081 :         switch (state) {
     156             :         case STATE_BEGIN:
     157        7514 :             if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
     158        7514 :                 && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
     159             :             {
     160        3757 :                 state = STATE_COMPONENTS;
     161        3757 :                 break;
     162             :             }
     163             :             throw css::registry::InvalidRegistryException(
     164           0 :                 reader_.getUrl() + ": unexpected item in outer level");
     165             :         case STATE_END:
     166        3757 :             if (res == xmlreader::XmlReader::RESULT_DONE) {
     167        7514 :                 return;
     168             :             }
     169             :             throw css::registry::InvalidRegistryException(
     170           0 :                 reader_.getUrl() + ": unexpected item in outer level");
     171             :         case STATE_COMPONENTS:
     172       37951 :             if (res == xmlreader::XmlReader::RESULT_END) {
     173        3757 :                 state = STATE_END;
     174        3757 :                 break;
     175             :             }
     176       68388 :             if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
     177       68388 :                 && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
     178             :             {
     179       34194 :                 handleComponent();
     180       34194 :                 state = STATE_COMPONENT_INITIAL;
     181       34194 :                 break;
     182             :             }
     183             :             throw css::registry::InvalidRegistryException(
     184           0 :                 reader_.getUrl() + ": unexpected item in <components>");
     185             :         case STATE_COMPONENT:
     186      201185 :             if (res == xmlreader::XmlReader::RESULT_END) {
     187       34194 :                 state = STATE_COMPONENTS;
     188       34194 :                 break;
     189             :             }
     190             :             // fall through
     191             :         case STATE_COMPONENT_INITIAL:
     192      402370 :             if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
     193      402370 :                 && name.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
     194             :             {
     195      201185 :                 handleImplementation();
     196      201185 :                 state = STATE_IMPLEMENTATION;
     197      201185 :                 break;
     198             :             }
     199             :             throw css::registry::InvalidRegistryException(
     200           0 :                 reader_.getUrl() + ": unexpected item in <component>");
     201             :         case STATE_IMPLEMENTATION:
     202      458211 :             if (res == xmlreader::XmlReader::RESULT_END) {
     203      201185 :                 state = STATE_COMPONENT;
     204      201185 :                 break;
     205             :             }
     206      514052 :             if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
     207      514052 :                 && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
     208             :             {
     209      249636 :                 handleService();
     210      249636 :                 state = STATE_SERVICE;
     211      249636 :                 break;
     212             :             }
     213       14780 :             if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
     214       14780 :                 && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
     215             :             {
     216        7390 :                 handleSingleton();
     217        7390 :                 state = STATE_SINGLETON;
     218        7390 :                 break;
     219             :             }
     220             :             throw css::registry::InvalidRegistryException(
     221           0 :                 reader_.getUrl() + ": unexpected item in <implementation>");
     222             :         case STATE_SERVICE:
     223      249636 :             if (res == xmlreader::XmlReader::RESULT_END) {
     224      249636 :                 state = STATE_IMPLEMENTATION;
     225      249636 :                 break;
     226             :             }
     227             :             throw css::registry::InvalidRegistryException(
     228           0 :                 reader_.getUrl() + ": unexpected item in <service>");
     229             :         case STATE_SINGLETON:
     230        7390 :             if (res == xmlreader::XmlReader::RESULT_END) {
     231        7390 :                 state = STATE_IMPLEMENTATION;
     232        7390 :                 break;
     233             :             }
     234             :             throw css::registry::InvalidRegistryException(
     235           0 :                 reader_.getUrl() + ": unexpected item in <service>");
     236             :         }
     237      992324 :     }
     238             : }
     239             : 
     240       34194 : void Parser::handleComponent() {
     241       34194 :     attrLoader_ = rtl::OUString();
     242       34194 :     attrUri_ = rtl::OUString();
     243       34194 :     attrEnvironment_ = rtl::OUString();
     244       34194 :     attrPrefix_ = rtl::OUString();
     245       34194 :     xmlreader::Span name;
     246             :     int nsId;
     247       34194 :     while (reader_.nextAttribute(&nsId, &name)) {
     248      254916 :         if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
     249      127458 :             && name.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
     250             :         {
     251       34194 :             if (!attrLoader_.isEmpty()) {
     252             :                 throw css::registry::InvalidRegistryException(
     253           0 :                     reader_.getUrl()
     254           0 :                      + ": <component> has multiple \"loader\" attributes");
     255             :             }
     256       34194 :             attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8();
     257       34194 :             if (attrLoader_.isEmpty()) {
     258             :                 throw css::registry::InvalidRegistryException(
     259           0 :                     reader_.getUrl()
     260           0 :                      + ": <component> has empty \"loader\" attribute");
     261             :             }
     262      186528 :         } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
     263       93264 :                    && name.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
     264             :         {
     265       34194 :             if (!attrUri_.isEmpty()) {
     266             :                 throw css::registry::InvalidRegistryException(
     267           0 :                     reader_.getUrl()
     268           0 :                      + ": <component> has multiple \"uri\" attributes");
     269             :             }
     270       34194 :             attrUri_ = reader_.getAttributeValue(false).convertFromUtf8();
     271       34194 :             if (attrUri_.isEmpty()) {
     272             :                 throw css::registry::InvalidRegistryException(
     273           0 :                     reader_.getUrl()
     274           0 :                      + ": <component> has empty \"uri\" attribute");
     275             :             }
     276      118140 :         } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
     277       59070 :                    && name.equals(RTL_CONSTASCII_STRINGPARAM("environment")))
     278             :         {
     279       32224 :             if (!attrEnvironment_.isEmpty()) {
     280             :                 throw css::registry::InvalidRegistryException(
     281           0 :                     reader_.getUrl() +
     282           0 :                      ": <component> has multiple \"environment\" attributes");
     283             :             }
     284       64448 :             attrEnvironment_ = reader_.getAttributeValue(false)
     285       32224 :                 .convertFromUtf8();
     286       32224 :             if (attrEnvironment_.isEmpty()) {
     287             :                 throw css::registry::InvalidRegistryException(
     288           0 :                     reader_.getUrl() +
     289           0 :                      ": <component> has empty \"environment\" attribute");
     290             :             }
     291       53692 :         } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
     292       26846 :                    && name.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
     293             :         {
     294       26846 :             if (!attrPrefix_.isEmpty()) {
     295             :                 throw css::registry::InvalidRegistryException(
     296           0 :                     reader_.getUrl() +
     297           0 :                      ": <component> has multiple \"prefix\" attributes");
     298             :             }
     299       26846 :             attrPrefix_ = reader_.getAttributeValue(false).convertFromUtf8();
     300       26846 :             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       34194 :     if (attrLoader_.isEmpty()) {
     312             :         throw css::registry::InvalidRegistryException(
     313           0 :             reader_.getUrl() + ": <component> is missing \"loader\" attribute");
     314             :     }
     315       34194 :     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       34194 :         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       34194 : }
     328             : 
     329      201185 : void Parser::handleImplementation() {
     330      201185 :     rtl::OUString attrName;
     331      402370 :     rtl::OUString attrConstructor;
     332      201185 :     xmlreader::Span name;
     333             :     int nsId;
     334      201185 :     while (reader_.nextAttribute(&nsId, &name)) {
     335      561744 :         if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
     336      280872 :             && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
     337             :         {
     338      201185 :             if (!attrName.isEmpty()) {
     339             :                 throw css::registry::InvalidRegistryException(
     340           0 :                     reader_.getUrl()
     341           0 :                      + ": <implementation> has multiple \"name\" attributes");
     342             :             }
     343      201185 :             attrName = reader_.getAttributeValue(false).convertFromUtf8();
     344      201185 :             if (attrName.isEmpty()) {
     345             :                 throw css::registry::InvalidRegistryException(
     346           0 :                     reader_.getUrl()
     347           0 :                     + ": <implementation> has empty \"name\" attribute");
     348             :             }
     349      159374 :         } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
     350       79687 :                    && name.equals(RTL_CONSTASCII_STRINGPARAM("constructor")))
     351             :         {
     352       79687 :             if (!attrConstructor.isEmpty()) {
     353             :                 throw css::registry::InvalidRegistryException(
     354           0 :                     reader_.getUrl()
     355           0 :                      + ": <implementation> has multiple \"constructor\""
     356           0 :                         " attributes");
     357             :             }
     358      159374 :             attrConstructor = reader_.getAttributeValue(false)
     359       79687 :                 .convertFromUtf8();
     360       79687 :             if (attrConstructor.isEmpty()) {
     361             :                 throw css::registry::InvalidRegistryException(
     362           0 :                     reader_.getUrl()
     363           0 :                      + ": element has empty \"constructor\" attribute");
     364             :             }
     365       79687 :             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      201185 :     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      201185 :             attrPrefix_, alienContext_, reader_.getUrl()));
     386      402370 :     if (!data_->namedImplementations.insert(
     387             :             cppuhelper::ServiceManager::Data::NamedImplementations::value_type(
     388      402370 :                 attrName, implementation_)).
     389      201185 :         second)
     390             :     {
     391             :         throw css::registry::InvalidRegistryException(
     392           0 :             reader_.getUrl() + ": duplicate <implementation name=\"" + attrName
     393           0 :              + "\">");
     394      201185 :     }
     395      201185 : }
     396             : 
     397      249636 : void Parser::handleService() {
     398      249636 :     rtl::OUString name(getNameAttribute());
     399      249636 :     implementation_->info->services.push_back(name);
     400      249636 :     data_->services[name].push_back(implementation_);
     401      249636 : }
     402             : 
     403        7390 : void Parser::handleSingleton() {
     404        7390 :     rtl::OUString name(getNameAttribute());
     405        7390 :     implementation_->info->singletons.push_back(name);
     406        7390 :     data_->singletons[name].push_back(implementation_);
     407        7390 : }
     408             : 
     409      257026 : rtl::OUString Parser::getNameAttribute() {
     410      257026 :     rtl::OUString attrName;
     411      257026 :     xmlreader::Span name;
     412             :     int nsId;
     413      257026 :     while (reader_.nextAttribute(&nsId, &name)) {
     414      514052 :         if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
     415      257026 :             && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
     416             :         {
     417      257026 :             if (!attrName.isEmpty()) {
     418             :                 throw css::registry::InvalidRegistryException(
     419           0 :                     reader_.getUrl()
     420           0 :                      + ": element has multiple \"name\" attributes");
     421             :             }
     422      257026 :             attrName = reader_.getAttributeValue(false).convertFromUtf8();
     423      257026 :             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      257026 :     if (attrName.isEmpty()) {
     433             :         throw css::registry::InvalidRegistryException(
     434           0 :             reader_.getUrl() + ": element is missing \"name\" attribute");
     435             :     }
     436      257026 :     return attrName;
     437             : }
     438             : 
     439             : class ContentEnumeration:
     440             :     public cppu::WeakImplHelper1< css::container::XEnumeration >,
     441             :     private boost::noncopyable
     442             : {
     443             : public:
     444        4896 :     explicit ContentEnumeration(std::vector< css::uno::Any > const & factories):
     445        4896 :         factories_(factories), iterator_(factories_.begin()) {}
     446             : 
     447             : private:
     448        9792 :     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        8910 : sal_Bool ContentEnumeration::hasMoreElements()
     464             :     throw (css::uno::RuntimeException, std::exception)
     465             : {
     466        8910 :     osl::MutexGuard g(mutex_);
     467        8910 :     return iterator_ != factories_.end();
     468             : }
     469             : 
     470        4040 : css::uno::Any ContentEnumeration::nextElement()
     471             :     throw (
     472             :         css::container::NoSuchElementException,
     473             :         css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception)
     474             : {
     475        4040 :     osl::MutexGuard g(mutex_);
     476        4040 :     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        4040 :     return *iterator_++;
     482             : }
     483             : 
     484           3 : css::beans::Property getDefaultContextProperty() {
     485             :     return css::beans::Property(
     486             :         "DefaultContext", -1,
     487           3 :         cppu::UnoType< css::uno::XComponentContext >::get(),
     488           3 :         css::beans::PropertyAttribute::READONLY);
     489             : }
     490             : 
     491             : class SingletonFactory:
     492             :     public cppu::WeakImplHelper1<css::lang::XSingleComponentFactory>,
     493             :     private boost::noncopyable
     494             : {
     495             : public:
     496        7390 :     SingletonFactory(
     497             :         rtl::Reference< cppuhelper::ServiceManager > const & manager,
     498             :         boost::shared_ptr<
     499             :             cppuhelper::ServiceManager::Data::Implementation > const &
     500             :             implementation):
     501        7390 :         manager_(manager), implementation_(implementation)
     502        7390 :     { assert(manager.is()); assert(implementation.get() != 0); }
     503             : 
     504             : private:
     505       14582 :     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        2440 : SingletonFactory::createInstanceWithContext(
     525             :     css::uno::Reference< css::uno::XComponentContext > const & Context)
     526             :     throw (css::uno::Exception, css::uno::RuntimeException, std::exception)
     527             : {
     528        2440 :     manager_->loadImplementation(Context, implementation_);
     529        2440 :     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        1982 :     ImplementationWrapper(
     551             :         rtl::Reference< cppuhelper::ServiceManager > const & manager,
     552             :         boost::shared_ptr<
     553             :             cppuhelper::ServiceManager::Data::Implementation > const &
     554             :             implementation):
     555        1982 :         manager_(manager), implementation_(implementation)
     556        1982 :     { assert(manager.is()); assert(implementation.get() != 0); }
     557             : 
     558             : private:
     559        3744 :     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         198 : ImplementationWrapper::createInstanceWithContext(
     596             :     css::uno::Reference< css::uno::XComponentContext > const & Context)
     597             :     throw (css::uno::Exception, css::uno::RuntimeException, std::exception)
     598             : {
     599         198 :     boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
     600             :     assert(impl);
     601         198 :     manager_->loadImplementation(Context, impl);
     602         198 :     return impl->createInstance(Context, false);
     603             : }
     604             : 
     605             : css::uno::Reference< css::uno::XInterface >
     606         574 : 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         574 :     boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
     612             :     assert(impl);
     613         574 :     manager_->loadImplementation(Context, impl);
     614             :     return impl->createInstanceWithArguments(
     615         574 :         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        2035 : rtl::OUString ImplementationWrapper::getImplementationName()
     635             :     throw (css::uno::RuntimeException, std::exception)
     636             : {
     637        2035 :     boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
     638             :     assert(impl);
     639        2035 :     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        1055 : ImplementationWrapper::getSupportedServiceNames()
     650             :     throw (css::uno::RuntimeException, std::exception)
     651             : {
     652        1055 :     boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
     653             :     assert(impl);
     654        1055 :     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        1055 :         static_cast< sal_Int32 >(impl->info->services.size()));
     664        1055 :     sal_Int32 i = 0;
     665        7272 :     for (std::vector< rtl::OUString >::const_iterator j(
     666        1055 :              impl->info->services.begin());
     667        4848 :          j != impl->info->services.end(); ++j)
     668             :     {
     669        1369 :         names[i++] = *j;
     670             :     }
     671        1055 :     return names;
     672             : }
     673             : 
     674             : }
     675             : 
     676             : css::uno::Reference<css::uno::XInterface>
     677   196263394 : cppuhelper::ServiceManager::Data::Implementation::createInstance(
     678             :     css::uno::Reference<css::uno::XComponentContext> const & context,
     679             :     bool singletonRequest)
     680             : {
     681   196263394 :     css::uno::Reference<css::uno::XInterface> inst;
     682   196263394 :     if (constructor != 0) {
     683             :         inst.set(
     684             :             (*constructor)(context.get(), css::uno::Sequence<css::uno::Any>()),
     685     1384020 :             SAL_NO_ACQUIRE);
     686   194879382 :     } else if (factory1.is()) {
     687   194874494 :             inst = factory1->createInstanceWithContext(context);
     688             :     } else {
     689             :         assert(factory2.is());
     690        4888 :         inst = factory2->createInstance();
     691             :     }
     692   196263385 :     updateDisposeSingleton(singletonRequest, inst);
     693   196263385 :     return inst;
     694             : }
     695             : 
     696             : css::uno::Reference<css::uno::XInterface>
     697      370721 : 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      370721 :     css::uno::Reference<css::uno::XInterface> inst;
     702      370721 :     if (constructor != 0) {
     703       28964 :         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       28955 :             inst, css::uno::UNO_QUERY);
     711       28955 :         if (init.is()) {
     712       27545 :             init->initialize(arguments);
     713       28955 :         }
     714      341757 :     } else if (factory1.is()) {
     715     1017214 :         inst = factory1->createInstanceWithArgumentsAndContext(
     716      675778 :             arguments, context);
     717             :     } else {
     718             :         assert(factory2.is());
     719         321 :         inst = factory2->createInstanceWithArguments(arguments);
     720             :     }
     721      363502 :     updateDisposeSingleton(singletonRequest, inst);
     722      363502 :     return inst;
     723             : }
     724             : 
     725   196626887 : 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   196626887 :     if (singletonRequest) {
     736        2440 :         osl::MutexGuard g(mutex);
     737        2440 :         disposeSingleton.clear();
     738        2440 :         dispose = false;
     739   196624447 :     } else if (!info->singletons.empty()) {
     740             :         css::uno::Reference<css::lang::XComponent> comp(
     741       21080 :             instance, css::uno::UNO_QUERY);
     742       21080 :         if (comp.is()) {
     743       21075 :             osl::MutexGuard g(mutex);
     744       21075 :             if (dispose) {
     745       20407 :                 disposeSingleton = comp;
     746       21075 :             }
     747       21080 :         }
     748             :     }
     749   196626887 : }
     750             : 
     751         519 : void cppuhelper::ServiceManager::addSingletonContextEntries(
     752             :     std::vector< cppu::ContextEntry_Init > * entries)
     753             : {
     754             :     assert(entries != 0);
     755       23727 :     for (Data::ImplementationMap::const_iterator i(data_.singletons.begin());
     756       15818 :          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       14780 :                 "/singletons/" + i->first,
     767             :                 css::uno::makeAny<
     768             :                     css::uno::Reference<css::lang::XSingleComponentFactory> >(
     769       14780 :                         new SingletonFactory(this, i->second[0])),
     770       22170 :                 true));
     771             :     }
     772         519 : }
     773             : 
     774       16573 : 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       16573 :         osl::MutexGuard g(rBHelper.rMutex);
     781       16573 :         if (implementation->status == Data::Implementation::STATUS_LOADED) {
     782       16578 :             return;
     783       16567 :         }
     784             :     }
     785       16567 :     rtl::OUString uri;
     786             :     try {
     787       16567 :         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       16567 :     cppuhelper::ImplementationConstructorFn * ctor = 0;
     794       33134 :     css::uno::Reference< css::uno::XInterface > f0;
     795             :     // Special handling of SharedLibrary loader, with support for environment,
     796             :     // constructor, and prefix arguments:
     797       33134 :     if (!implementation->info->alienContext.is()
     798       16567 :         && implementation->info->loader == "com.sun.star.loader.SharedLibrary")
     799             :     {
     800             :         cppuhelper::detail::loadSharedLibComponentFactory(
     801       16559 :             uri, implementation->info->environment,
     802       33118 :             implementation->info->prefix, implementation->info->name,
     803       66237 :             implementation->info->constructor, this, &ctor, &f0);
     804       16558 :         if (ctor != 0) {
     805             :             assert(!implementation->info->environment.isEmpty());
     806        8465 :             css::uno::Environment curEnv(css::uno::Environment::getCurrent());
     807             :             css::uno::Environment env(
     808             :                 cppuhelper::detail::getEnvironment(
     809        8465 :                     implementation->info->environment,
     810       25395 :                     implementation->info->name));
     811        8465 :             if (!(curEnv.is() && env.is())) {
     812             :                 throw css::uno::DeploymentException(
     813             :                     "cannot get environments",
     814           0 :                     css::uno::Reference<css::uno::XInterface>());
     815             :             }
     816        8465 :             if (curEnv.get() != env.get()) {
     817           0 :                 std::abort();//TODO
     818        8465 :             }
     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           8 :         css::uno::Reference< css::uno::XComponentContext > ctxt;
     836          16 :         css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
     837           8 :         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           8 :             ctxt = context;
     844           8 :             smgr = this;
     845             :         }
     846             :         css::uno::Reference< css::loader::XImplementationLoader > loader(
     847           8 :             smgr->createInstanceWithContext(implementation->info->loader, ctxt),
     848          16 :             css::uno::UNO_QUERY_THROW);
     849          32 :         f0 = loader->activate(
     850           8 :             implementation->info->name, rtl::OUString(), uri,
     851          24 :             css::uno::Reference< css::registry::XRegistryKey >());
     852             :     }
     853       33132 :     css::uno::Reference<css::lang::XSingleComponentFactory> f1;
     854       33132 :     css::uno::Reference<css::lang::XSingleServiceFactory> f2;
     855       16566 :     if (ctor == 0) {
     856        8101 :         f1.set(f0, css::uno::UNO_QUERY);
     857        8101 :         if (!f1.is()) {
     858         204 :             f2.set(f0, css::uno::UNO_QUERY);
     859         204 :             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       33132 :     osl::MutexGuard g(rBHelper.rMutex);
     871       33132 :     if (!(isDisposed()
     872       16566 :           || implementation->status == Data::Implementation::STATUS_LOADED))
     873             :     {
     874       16566 :         implementation->status = Data::Implementation::STATUS_LOADED;
     875       16566 :         implementation->constructor = ctor;
     876       16566 :         implementation->factory1 = f1;
     877       16566 :         implementation->factory2 = f2;
     878       16567 :     }
     879             : }
     880             : 
     881         515 : void cppuhelper::ServiceManager::disposing() {
     882         515 :     std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
     883        1030 :     std::vector< css::uno::Reference< css::lang::XComponent > > comps;
     884        1030 :     Data clear;
     885             :     {
     886         515 :         osl::MutexGuard g(rBHelper.rMutex);
     887      595779 :         for (Data::NamedImplementations::const_iterator i(
     888         515 :                  data_.namedImplementations.begin());
     889      397186 :              i != data_.namedImplementations.end(); ++i)
     890             :         {
     891             :             assert(i->second.get() != 0);
     892      198078 :             if (!i->second->info->singletons.empty()) {
     893        7291 :                 osl::MutexGuard g2(i->second->mutex);
     894        7291 :                 if (i->second->disposeSingleton.is()) {
     895         218 :                     sngls.push_back(i->second->disposeSingleton);
     896        7291 :                 }
     897             :             }
     898             :         }
     899        3579 :         for (Data::DynamicImplementations::const_iterator i(
     900         515 :                  data_.dynamicImplementations.begin());
     901        2386 :              i != data_.dynamicImplementations.end(); ++i)
     902             :         {
     903             :             assert(i->second.get() != 0);
     904         678 :             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         678 :             if (i->second->component.is()) {
     911         678 :                 comps.push_back(i->second->component);
     912             :             }
     913             :         }
     914         515 :         data_.namedImplementations.swap(clear.namedImplementations);
     915         515 :         data_.dynamicImplementations.swap(clear.dynamicImplementations);
     916         515 :         data_.services.swap(clear.services);
     917         515 :         data_.singletons.swap(clear.singletons);
     918             :     }
     919        2199 :     for (std::vector<
     920             :              css::uno::Reference<css::lang::XComponent> >::const_iterator i(
     921         515 :                  sngls.begin());
     922        1466 :          i != sngls.end(); ++i)
     923             :     {
     924             :         try {
     925         218 :             (*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        3579 :     for (std::vector<
     934             :              css::uno::Reference< css::lang::XComponent > >::const_iterator i(
     935         515 :                  comps.begin());
     936        2386 :          i != comps.end(); ++i)
     937             :     {
     938         678 :         removeEventListenerFromComponent(*i);
     939         515 :     }
     940         515 : }
     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      157820 : cppuhelper::ServiceManager::createInstance(
     968             :     rtl::OUString const & aServiceSpecifier)
     969             :     throw (css::uno::Exception, css::uno::RuntimeException, std::exception)
     970             : {
     971             :     assert(context_.is());
     972      157820 :     return createInstanceWithContext(aServiceSpecifier, context_);
     973             : }
     974             : 
     975             : css::uno::Reference< css::uno::XInterface >
     976        4579 : 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        4579 :         ServiceSpecifier, Arguments, context_);
     984             : }
     985             : 
     986             : css::uno::Sequence< rtl::OUString >
     987           1 : cppuhelper::ServiceManager::getAvailableServiceNames()
     988             :     throw (css::uno::RuntimeException, std::exception)
     989             : {
     990           1 :     osl::MutexGuard g(rBHelper.rMutex);
     991           1 :     if (isDisposed()) {
     992           0 :         return css::uno::Sequence< rtl::OUString >();
     993             :     }
     994           1 :     Data::ImplementationMap::size_type n = data_.services.size();
     995           1 :     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           2 :     css::uno::Sequence< rtl::OUString > names(static_cast< sal_Int32 >(n));
    1001           1 :     sal_Int32 i = 0;
    1002        2967 :     for (Data::ImplementationMap::const_iterator j(data_.services.begin());
    1003        1978 :          j != data_.services.end(); ++j)
    1004             :     {
    1005         988 :         names[i++] = j->first;
    1006             :     }
    1007             :     assert(i == names.getLength());
    1008           2 :     return names;
    1009             : }
    1010             : 
    1011             : css::uno::Reference< css::uno::XInterface >
    1012   196532146 : 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   196532146 :         findServiceImplementation(Context, aServiceSpecifier));
    1019   196532145 :     return impl.get() == 0
    1020             :         ? css::uno::Reference< css::uno::XInterface >()
    1021   196532145 :         : impl->createInstance(Context, false);
    1022             : }
    1023             : 
    1024             : css::uno::Reference< css::uno::XInterface >
    1025      392603 : 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      392603 :         findServiceImplementation(Context, ServiceSpecifier));
    1033      392603 :     return impl.get() == 0
    1034             :         ? css::uno::Reference< css::uno::XInterface >()
    1035      392603 :         : 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         691 : 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         691 :     css::uno::Sequence< css::beans::NamedValue > args;
    1076         691 :     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        1382 :     css::uno::Reference< css::lang::XServiceInfo > info;
    1109         691 :     if ((aElement >>= info) && info.is()) {
    1110         691 :         insertLegacyFactory(info);
    1111         691 :         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         691 :         "Bad insert element", static_cast< cppu::OWeakObject * >(this), 0);
    1134             : }
    1135             : 
    1136           1 : 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           1 :     css::uno::Sequence< css::beans::NamedValue > args;
    1142           1 :     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           2 :     css::uno::Reference< css::lang::XServiceInfo > info;
    1163           1 :     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           2 :     rtl::OUString impl;
    1172           1 :     if (aElement >>= impl) {
    1173             :         // For live-removal of extensions:
    1174           1 :         removeImplementation(impl);
    1175           1 :         return;
    1176             :     }
    1177             :     throw css::lang::IllegalArgumentException(
    1178           1 :         "Bad remove element", static_cast< cppu::OWeakObject * >(this), 0);
    1179             : }
    1180             : 
    1181             : css::uno::Reference< css::container::XEnumeration >
    1182        4896 : cppuhelper::ServiceManager::createContentEnumeration(
    1183             :     rtl::OUString const & aServiceName)
    1184             :     throw (css::uno::RuntimeException, std::exception)
    1185             : {
    1186        4896 :     std::vector< boost::shared_ptr< Data::Implementation > > impls;
    1187             :     {
    1188        4896 :         osl::MutexGuard g(rBHelper.rMutex);
    1189             :         Data::ImplementationMap::const_iterator i(
    1190        4896 :             data_.services.find(aServiceName));
    1191        4896 :         if (i != data_.services.end()) {
    1192        1601 :             impls = i->second;
    1193        4896 :         }
    1194             :     }
    1195        9792 :     std::vector< css::uno::Any > factories;
    1196       27186 :     for (std::vector<
    1197             :              boost::shared_ptr< Data::Implementation > >::const_iterator i(
    1198        4896 :                  impls.begin());
    1199       18124 :          i != impls.end(); ++i)
    1200             :     {
    1201        4166 :         Data::Implementation * impl = i->get();
    1202             :         assert(impl != 0);
    1203             :         {
    1204        4166 :             osl::MutexGuard g(rBHelper.rMutex);
    1205        4166 :             if (isDisposed()) {
    1206           0 :                 factories.clear();
    1207           0 :                 break;
    1208             :             }
    1209        4166 :             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        1978 :                 impl->factory1 = new ImplementationWrapper(this, *i);
    1217        1978 :                 impl->status = Data::Implementation::STATUS_WRAPPER;
    1218        4166 :             }
    1219             :         }
    1220        4166 :         if (impl->factory1.is()) {
    1221        4162 :             factories.push_back(css::uno::makeAny(impl->factory1));
    1222           4 :         } 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           4 :                     new ImplementationWrapper(this, *i));
    1227           4 :             factories.push_back(css::uno::makeAny(factory));
    1228             :         }
    1229             :     }
    1230        9792 :     return new ContentEnumeration(factories);
    1231             : }
    1232             : 
    1233             : css::uno::Reference< css::beans::XPropertySetInfo >
    1234          16 : cppuhelper::ServiceManager::getPropertySetInfo()
    1235             :     throw (css::uno::RuntimeException, std::exception)
    1236             : {
    1237          16 :     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   222937247 : 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   222937247 :     if (PropertyName != "DefaultContext") {
    1263             :         throw css::beans::UnknownPropertyException(
    1264           0 :             PropertyName, static_cast< cppu::OWeakObject * >(this));
    1265             :     }
    1266             :     assert(context_.is());
    1267   222937247 :     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           3 : cppuhelper::ServiceManager::getProperties() throw (css::uno::RuntimeException, std::exception) {
    1336           3 :     css::uno::Sequence< css::beans::Property > props(1);
    1337           3 :     props[0] = getDefaultContextProperty();
    1338           3 :     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           6 : 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           6 :         false);
    1367           6 : }
    1368             : 
    1369         678 : void cppuhelper::ServiceManager::removeEventListenerFromComponent(
    1370             :     css::uno::Reference< css::lang::XComponent > const & component)
    1371             : {
    1372             :     assert(component.is());
    1373             :     try {
    1374         678 :         component->removeEventListener(this);
    1375           0 :     } catch (css::uno::RuntimeException & e) {
    1376             :         SAL_INFO(
    1377             :             "cppuhelper",
    1378             :             "Ignored removeEventListener RuntimeException " + e.Message);
    1379             :     }
    1380         678 : }
    1381             : 
    1382         519 : void cppuhelper::ServiceManager::readRdbs(rtl::OUString const & uris) {
    1383        4961 :     for (sal_Int32 i = 0; i != -1;) {
    1384        3923 :         rtl::OUString uri(uris.getToken(0, ' ', i));
    1385        3923 :         if (uri.isEmpty()) {
    1386         524 :             continue;
    1387             :         }
    1388             :         bool optional;
    1389             :         bool directory;
    1390        3399 :         cppu::decodeRdbUri(&uri, &optional, &directory);
    1391        3399 :         if (directory) {
    1392         120 :             readRdbDirectory(uri, optional);
    1393             :         } else {
    1394        3279 :             readRdbFile(uri, optional);
    1395             :         }
    1396        3399 :     }
    1397         519 : }
    1398             : 
    1399         120 : void cppuhelper::ServiceManager::readRdbDirectory(
    1400             :     rtl::OUString const & uri, bool optional)
    1401             : {
    1402         120 :     osl::Directory dir(uri);
    1403         120 :     switch (dir.open()) {
    1404             :     case osl::FileBase::E_None:
    1405         120 :         break;
    1406             :     case osl::FileBase::E_NOENT:
    1407           0 :         if (optional) {
    1408             :             SAL_INFO("cppuhelper", "Ignored optional " << uri);
    1409         120 :             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         600 :         rtl::OUString url;
    1419         600 :         if (!cppu::nextDirectoryItem(dir, &url)) {
    1420         120 :             break;
    1421             :         }
    1422         480 :         readRdbFile(url, false);
    1423         480 :     }
    1424             : }
    1425             : 
    1426        3759 : void cppuhelper::ServiceManager::readRdbFile(
    1427             :     rtl::OUString const & uri, bool optional)
    1428             : {
    1429             :     try {
    1430             :         Parser(
    1431        3761 :             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           4 :     } catch (css::uno::RuntimeException &) {
    1446           2 :         if (!readLegacyRdbFile(uri)) {
    1447           0 :             throw;
    1448             :         }
    1449             :     }
    1450        3759 : }
    1451             : 
    1452           2 : bool cppuhelper::ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) {
    1453           2 :     Registry reg;
    1454           2 :     switch (reg.open(uri, RegAccessMode::READONLY)) {
    1455             :     case RegError::NO_ERROR:
    1456           0 :         break;
    1457             :     case RegError::REGISTRY_NOT_EXISTS:
    1458             :     case RegError::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           2 :             osl::DirectoryItem item;
    1464           2 :             if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
    1465           2 :                 osl::FileStatus status(osl_FileStatus_Mask_FileSize);
    1466           4 :                 if (item.getFileStatus(status) == osl::FileBase::E_None
    1467           2 :                     && status.getFileSize() == 0)
    1468             :                 {
    1469           2 :                     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) != RegError::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 RegError::NO_ERROR:
    1486           0 :         break;
    1487             :     case RegError::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) != RegError::NO_ERROR
    1538           0 :         || subkey.getValueInfo(rtl::OUString(), &t, &s) != RegError::NO_ERROR
    1539           0 :         || t != RegValueType::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]) != RegError::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 RegError::NO_ERROR:
    1572           0 :         break;
    1573             :     case RegError::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) != RegError::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         691 : void cppuhelper::ServiceManager::insertLegacyFactory(
    1617             :     css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo)
    1618             : {
    1619             :     assert(factoryInfo.is());
    1620         691 :     rtl::OUString name(factoryInfo->getImplementationName());
    1621             :     css::uno::Reference< css::lang::XSingleComponentFactory > f1(
    1622        1382 :         factoryInfo, css::uno::UNO_QUERY);
    1623        1382 :     css::uno::Reference< css::lang::XSingleServiceFactory > f2;
    1624         691 :     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        1382 :         factoryInfo, css::uno::UNO_QUERY);
    1636             :     boost::shared_ptr< Data::Implementation > impl(
    1637        1382 :         new Data::Implementation(name, f1, f2, comp));
    1638        1382 :     Data extra;
    1639         691 :     if (!name.isEmpty()) {
    1640             :         extra.namedImplementations.insert(
    1641         121 :             Data::NamedImplementations::value_type(name, impl));
    1642             :     }
    1643             :     extra.dynamicImplementations.insert(
    1644         691 :         Data::DynamicImplementations::value_type(factoryInfo, impl));
    1645             :     css::uno::Sequence< rtl::OUString > services(
    1646        1382 :         factoryInfo->getSupportedServiceNames());
    1647        1382 :     for (sal_Int32 i = 0; i != services.getLength(); ++i) {
    1648         691 :         impl->info->services.push_back(services[i]);
    1649         691 :         extra.services[services[i]].push_back(impl);
    1650             :     }
    1651         691 :     if (insertExtraData(extra) && comp.is()) {
    1652         691 :         comp->addEventListener(this);
    1653         691 :     }
    1654         691 : }
    1655             : 
    1656         691 : bool cppuhelper::ServiceManager::insertExtraData(Data const & extra) {
    1657             :     {
    1658         691 :         osl::MutexGuard g(rBHelper.rMutex);
    1659         691 :         if (isDisposed()) {
    1660           0 :             return false;
    1661             :         }
    1662        2436 :         for (Data::NamedImplementations::const_iterator i(
    1663         691 :                  extra.namedImplementations.begin());
    1664        1624 :              i != extra.namedImplementations.end(); ++i)
    1665             :         {
    1666         363 :             if (data_.namedImplementations.find(i->first)
    1667         363 :                 != 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        4146 :         for (Data::DynamicImplementations::const_iterator i(
    1675         691 :                  extra.dynamicImplementations.begin());
    1676        2764 :              i != extra.dynamicImplementations.end(); ++i)
    1677             :         {
    1678        2073 :             if (data_.dynamicImplementations.find(i->first)
    1679        2073 :                 != 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         691 :             extra.namedImplementations.end());
    1690             :         data_.dynamicImplementations.insert(
    1691             :             extra.dynamicImplementations.begin(),
    1692         691 :             extra.dynamicImplementations.end());
    1693         691 :         insertImplementationMap(&data_.services, extra.services);
    1694         691 :         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         691 :     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         691 :     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           6 : bool cppuhelper::ServiceManager::removeLegacyFactory(
    1773             :     css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
    1774             :     bool removeListener)
    1775             : {
    1776             :     assert(factoryInfo.is());
    1777           6 :     boost::shared_ptr< Data::Implementation > clear;
    1778          12 :     css::uno::Reference< css::lang::XComponent > comp;
    1779             :     {
    1780           6 :         osl::MutexGuard g(rBHelper.rMutex);
    1781             :         Data::DynamicImplementations::iterator i(
    1782           6 :             data_.dynamicImplementations.find(factoryInfo));
    1783           6 :         if (i == data_.dynamicImplementations.end()) {
    1784           0 :             return isDisposed();
    1785             :         }
    1786             :         assert(i->second.get() != 0);
    1787           6 :         clear = i->second;
    1788           6 :         if (removeListener) {
    1789           0 :             comp = i->second->component;
    1790             :         }
    1791             :         //TODO: The below leaves data_ in an inconsistent state upon exceptions:
    1792             :         removeFromImplementationMap(
    1793           6 :             &data_.services, i->second->info->services, i->second);
    1794             :         removeFromImplementationMap(
    1795           6 :             &data_.singletons, i->second->info->singletons, i->second);
    1796           6 :         if (!i->second->info->name.isEmpty()) {
    1797           6 :             data_.namedImplementations.erase(i->second->info->name);
    1798             :         }
    1799           6 :         data_.dynamicImplementations.erase(i);
    1800             :     }
    1801           6 :     if (comp.is()) {
    1802           0 :         removeEventListenerFromComponent(comp);
    1803             :     }
    1804          12 :     return true;
    1805             : }
    1806             : 
    1807           1 : 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           1 :     boost::shared_ptr< Data::Implementation > clear;
    1811             :     {
    1812           1 :         osl::MutexGuard g(rBHelper.rMutex);
    1813           1 :         if (isDisposed()) {
    1814           1 :             return;
    1815             :         }
    1816             :         Data::NamedImplementations::iterator i(
    1817           1 :             data_.namedImplementations.find(name));
    1818           1 :         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           1 :         clear = i->second;
    1825             :         //TODO: The below leaves data_ in an inconsistent state upon exceptions:
    1826             :         removeFromImplementationMap(
    1827           1 :             &data_.services, i->second->info->services, i->second);
    1828             :         removeFromImplementationMap(
    1829           1 :             &data_.singletons, i->second->info->singletons, i->second);
    1830          21 :         for (Data::DynamicImplementations::iterator j(
    1831           1 :                  data_.dynamicImplementations.begin());
    1832          14 :              j != data_.dynamicImplementations.end(); ++j)
    1833             :         {
    1834           7 :             if (j->second == i->second) {
    1835           1 :                 data_.dynamicImplementations.erase(j);
    1836           1 :                 break;
    1837             :             }
    1838             :         }
    1839           1 :         data_.namedImplementations.erase(i);
    1840           1 :     }
    1841             : }
    1842             : 
    1843             : boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
    1844   196924749 : cppuhelper::ServiceManager::findServiceImplementation(
    1845             :     css::uno::Reference< css::uno::XComponentContext > const & context,
    1846             :     rtl::OUString const & specifier)
    1847             : {
    1848   196924749 :     boost::shared_ptr< Data::Implementation > impl;
    1849             :     bool loaded;
    1850             :     {
    1851   196924749 :         osl::MutexGuard g(rBHelper.rMutex);
    1852             :         Data::ImplementationMap::const_iterator i(
    1853   196924749 :             data_.services.find(specifier));
    1854   196924749 :         if (i == data_.services.end()) {
    1855             :             Data::NamedImplementations::const_iterator j(
    1856      385492 :                 data_.namedImplementations.find(specifier));
    1857      385492 :             if (j == data_.namedImplementations.end()) {
    1858             :                 SAL_INFO("cppuhelper", "No implementation for " << specifier);
    1859      293845 :                 return boost::shared_ptr< Data::Implementation >();
    1860             :             }
    1861       91647 :             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   196539257 :             impl = i->second[0];
    1869             :         }
    1870             :         assert(impl.get() != 0);
    1871   196630904 :         loaded = impl->status == Data::Implementation::STATUS_LOADED;
    1872             :     }
    1873   196630904 :     if (!loaded) {
    1874       13361 :         loadImplementation(context, impl);
    1875             :     }
    1876   196630904 :     return impl;
    1877             : }
    1878             : 
    1879             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11