fdo#49291 Postpone actual factory instantiation as long as possible
...see comment in ServiceManager::createContentEnumeration for a rationale. Splitting ImplementationInfo out of Implementation has become necessary to avoid circular references. Change-Id: I29aef81ce78b9ab71e18663f8c7e6ca913c6a650
This commit is contained in:
@@ -60,6 +60,7 @@
|
|||||||
#include "cppuhelper/compbase8.hxx"
|
#include "cppuhelper/compbase8.hxx"
|
||||||
#include "cppuhelper/component_context.hxx"
|
#include "cppuhelper/component_context.hxx"
|
||||||
#include "cppuhelper/implbase1.hxx"
|
#include "cppuhelper/implbase1.hxx"
|
||||||
|
#include "cppuhelper/implbase3.hxx"
|
||||||
#include "cppuhelper/shlib.hxx"
|
#include "cppuhelper/shlib.hxx"
|
||||||
#include "osl/file.hxx"
|
#include "osl/file.hxx"
|
||||||
#include "registry/registry.hxx"
|
#include "registry/registry.hxx"
|
||||||
@@ -124,28 +125,17 @@ void decodeRdbUri(rtl::OUString * uri, bool * optional, bool * directory) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Implementation: private boost::noncopyable {
|
struct ImplementationInfo: private boost::noncopyable {
|
||||||
Implementation(
|
ImplementationInfo(
|
||||||
rtl::OUString const & theName, rtl::OUString const & theLoader,
|
rtl::OUString const & theName, rtl::OUString const & theLoader,
|
||||||
rtl::OUString const & theUri,
|
rtl::OUString const & theUri, rtl::OUString const & thePrefix,
|
||||||
rtl::OUString const & thePrefix = rtl::OUString(),
|
|
||||||
css::uno::Reference< css::uno::XComponentContext > const &
|
css::uno::Reference< css::uno::XComponentContext > const &
|
||||||
theAlienContext
|
theAlienContext):
|
||||||
= css::uno::Reference< css::uno::XComponentContext >()):
|
|
||||||
name(theName), loader(theLoader), uri(theUri), prefix(thePrefix),
|
name(theName), loader(theLoader), uri(theUri), prefix(thePrefix),
|
||||||
alienContext(theAlienContext), loaded(false)
|
alienContext(theAlienContext)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Implementation(
|
explicit ImplementationInfo(rtl::OUString const & theName): name(theName) {}
|
||||||
rtl::OUString const & theName,
|
|
||||||
css::uno::Reference< css::lang::XSingleComponentFactory > const &
|
|
||||||
theFactory1,
|
|
||||||
css::uno::Reference< css::lang::XSingleServiceFactory > const &
|
|
||||||
theFactory2,
|
|
||||||
css::uno::Reference< css::lang::XComponent > const & theComponent):
|
|
||||||
name(theName), factory1(theFactory1), factory2(theFactory2),
|
|
||||||
component(theComponent), loaded(true)
|
|
||||||
{}
|
|
||||||
|
|
||||||
rtl::OUString const name;
|
rtl::OUString const name;
|
||||||
rtl::OUString const loader;
|
rtl::OUString const loader;
|
||||||
@@ -154,6 +144,32 @@ struct Implementation: private boost::noncopyable {
|
|||||||
css::uno::Reference< css::uno::XComponentContext > const alienContext;
|
css::uno::Reference< css::uno::XComponentContext > const alienContext;
|
||||||
std::vector< rtl::OUString > services;
|
std::vector< rtl::OUString > services;
|
||||||
std::vector< rtl::OUString > singletons;
|
std::vector< rtl::OUString > singletons;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Implementation: private boost::noncopyable {
|
||||||
|
Implementation(
|
||||||
|
rtl::OUString const & name, rtl::OUString const & loader,
|
||||||
|
rtl::OUString const & uri,
|
||||||
|
rtl::OUString const & prefix = rtl::OUString(),
|
||||||
|
css::uno::Reference< css::uno::XComponentContext > const &
|
||||||
|
alienContext
|
||||||
|
= css::uno::Reference< css::uno::XComponentContext >()):
|
||||||
|
info(new ImplementationInfo(name, loader, uri, prefix, alienContext)),
|
||||||
|
loaded(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Implementation(
|
||||||
|
rtl::OUString const & name,
|
||||||
|
css::uno::Reference< css::lang::XSingleComponentFactory > const &
|
||||||
|
theFactory1,
|
||||||
|
css::uno::Reference< css::lang::XSingleServiceFactory > const &
|
||||||
|
theFactory2,
|
||||||
|
css::uno::Reference< css::lang::XComponent > const & theComponent):
|
||||||
|
info(new ImplementationInfo(name)), factory1(theFactory1),
|
||||||
|
factory2(theFactory2), component(theComponent), loaded(true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
boost::shared_ptr< ImplementationInfo > info;
|
||||||
css::uno::Reference< css::lang::XSingleComponentFactory > factory1;
|
css::uno::Reference< css::lang::XSingleComponentFactory > factory1;
|
||||||
css::uno::Reference< css::lang::XSingleServiceFactory > factory2;
|
css::uno::Reference< css::lang::XSingleServiceFactory > factory2;
|
||||||
css::uno::Reference< css::lang::XComponent > component;
|
css::uno::Reference< css::lang::XComponent > component;
|
||||||
@@ -463,13 +479,13 @@ void Parser::handleImplementation() {
|
|||||||
|
|
||||||
void Parser::handleService() {
|
void Parser::handleService() {
|
||||||
rtl::OUString name(getNameAttribute());
|
rtl::OUString name(getNameAttribute());
|
||||||
implementation_->services.push_back(name);
|
implementation_->info->services.push_back(name);
|
||||||
data_->services[name].push_back(implementation_);
|
data_->services[name].push_back(implementation_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::handleSingleton() {
|
void Parser::handleSingleton() {
|
||||||
rtl::OUString name(getNameAttribute());
|
rtl::OUString name(getNameAttribute());
|
||||||
implementation_->singletons.push_back(name);
|
implementation_->info->singletons.push_back(name);
|
||||||
data_->singletons[name].push_back(implementation_);
|
data_->singletons[name].push_back(implementation_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,8 +601,18 @@ public:
|
|||||||
context_ = context;
|
context_ = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
css::uno::Reference< css::uno::XComponentContext > getContext() const {
|
||||||
|
assert(context_.is());
|
||||||
|
return context_;
|
||||||
|
}
|
||||||
|
|
||||||
Data const & getData() const { return data_; }
|
Data const & getData() const { return data_; }
|
||||||
|
|
||||||
|
void loadImplementation(
|
||||||
|
boost::shared_ptr< ImplementationInfo > const & info,
|
||||||
|
css::uno::Reference< css::lang::XSingleComponentFactory > * factory1,
|
||||||
|
css::uno::Reference< css::lang::XSingleServiceFactory > * factory2);
|
||||||
|
|
||||||
virtual rtl::OUString SAL_CALL getImplementationName()
|
virtual rtl::OUString SAL_CALL getImplementationName()
|
||||||
throw (css::uno::RuntimeException);
|
throw (css::uno::RuntimeException);
|
||||||
|
|
||||||
@@ -757,12 +783,136 @@ private:
|
|||||||
boost::shared_ptr< Implementation > findServiceImplementation(
|
boost::shared_ptr< Implementation > findServiceImplementation(
|
||||||
rtl::OUString const & specifier);
|
rtl::OUString const & specifier);
|
||||||
|
|
||||||
void loadImplementation(Implementation * implementation);
|
|
||||||
|
|
||||||
css::uno::Reference< css::uno::XComponentContext > context_;
|
css::uno::Reference< css::uno::XComponentContext > context_;
|
||||||
Data data_;
|
Data data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FactoryWrapper:
|
||||||
|
public cppu::WeakImplHelper3<
|
||||||
|
css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
|
||||||
|
css::lang::XServiceInfo >,
|
||||||
|
private boost::noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FactoryWrapper(
|
||||||
|
rtl::Reference< ServiceManager > const & manager,
|
||||||
|
boost::shared_ptr< ImplementationInfo > const & info):
|
||||||
|
manager_(manager), info_(info), loaded_(false)
|
||||||
|
{ assert(manager.is() && info.get() != 0); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual ~FactoryWrapper() {}
|
||||||
|
|
||||||
|
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
|
||||||
|
createInstanceWithContext(
|
||||||
|
css::uno::Reference< css::uno::XComponentContext > const & Context)
|
||||||
|
throw (css::uno::Exception, css::uno::RuntimeException);
|
||||||
|
|
||||||
|
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
|
||||||
|
createInstanceWithArgumentsAndContext(
|
||||||
|
css::uno::Sequence< css::uno::Any > const & Arguments,
|
||||||
|
css::uno::Reference< css::uno::XComponentContext > const & Context)
|
||||||
|
throw (css::uno::Exception, css::uno::RuntimeException);
|
||||||
|
|
||||||
|
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
|
||||||
|
createInstance() throw (css::uno::Exception, css::uno::RuntimeException);
|
||||||
|
|
||||||
|
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
|
||||||
|
createInstanceWithArguments(
|
||||||
|
css::uno::Sequence< css::uno::Any > const & Arguments)
|
||||||
|
throw (css::uno::Exception, css::uno::RuntimeException);
|
||||||
|
|
||||||
|
virtual rtl::OUString SAL_CALL getImplementationName()
|
||||||
|
throw (css::uno::RuntimeException);
|
||||||
|
|
||||||
|
virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
|
||||||
|
throw (css::uno::RuntimeException);
|
||||||
|
|
||||||
|
virtual css::uno::Sequence< rtl::OUString > SAL_CALL
|
||||||
|
getSupportedServiceNames() throw (css::uno::RuntimeException);
|
||||||
|
|
||||||
|
void loadImplementation();
|
||||||
|
|
||||||
|
rtl::Reference< ServiceManager > manager_;
|
||||||
|
boost::shared_ptr< ImplementationInfo > info_;
|
||||||
|
|
||||||
|
osl::Mutex mutex_;
|
||||||
|
bool loaded_;
|
||||||
|
css::uno::Reference< css::lang::XSingleComponentFactory > factory1_;
|
||||||
|
css::uno::Reference< css::lang::XSingleServiceFactory > factory2_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ServiceManager::loadImplementation(
|
||||||
|
boost::shared_ptr< ImplementationInfo > const & info,
|
||||||
|
css::uno::Reference< css::lang::XSingleComponentFactory > * factory1,
|
||||||
|
css::uno::Reference< css::lang::XSingleServiceFactory > * factory2)
|
||||||
|
{
|
||||||
|
assert(
|
||||||
|
info.get() != 0 && factory1 != 0 && !factory1->is() && factory2 != 0
|
||||||
|
&& !factory2->is());
|
||||||
|
rtl::OUString uri;
|
||||||
|
try {
|
||||||
|
uri = cppu::bootstrap_expandUri(info->uri);
|
||||||
|
} catch (css::lang::IllegalArgumentException & e) {
|
||||||
|
throw css::uno::DeploymentException(
|
||||||
|
"Cannot expand URI" + info->uri + ": " + e.Message,
|
||||||
|
static_cast< cppu::OWeakObject * >(this));
|
||||||
|
}
|
||||||
|
css::uno::Reference< css::uno::XInterface > f0;
|
||||||
|
// Shortcut loading via SharedLibrary loader, to pass in prefix argument
|
||||||
|
// (which the loader's activate implementation would normally obtain through
|
||||||
|
// the legacy xKey argument):
|
||||||
|
if (!info->alienContext.is()
|
||||||
|
&& info->loader == "com.sun.star.loader.SharedLibrary")
|
||||||
|
{
|
||||||
|
rtl::OUString prefix(info->prefix);
|
||||||
|
if (!prefix.isEmpty()) {
|
||||||
|
prefix += "_";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
f0 = cppu::loadSharedLibComponentFactory(
|
||||||
|
uri, rtl::OUString(), info->name, this,
|
||||||
|
css::uno::Reference< css::registry::XRegistryKey >(), prefix);
|
||||||
|
} catch (css::loader::CannotActivateFactoryException & e) {
|
||||||
|
throw css::uno::DeploymentException(
|
||||||
|
"Cannot activate implementation " + uri + ": " + e.Message,
|
||||||
|
static_cast< cppu::OWeakObject * >(this));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SAL_INFO_IF(
|
||||||
|
!info->prefix.isEmpty(), "cppuhelper",
|
||||||
|
"Loader " << info->loader << " and non-empty prefix "
|
||||||
|
<< info->prefix);
|
||||||
|
css::uno::Reference< css::uno::XComponentContext > ctxt;
|
||||||
|
css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
|
||||||
|
if (info->alienContext.is()) {
|
||||||
|
ctxt = info->alienContext;
|
||||||
|
smgr = css::uno::Reference< css::lang::XMultiComponentFactory >(
|
||||||
|
ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
|
||||||
|
} else {
|
||||||
|
assert(context_.is());
|
||||||
|
ctxt = context_;
|
||||||
|
smgr = this;
|
||||||
|
}
|
||||||
|
css::uno::Reference< css::loader::XImplementationLoader > loader(
|
||||||
|
smgr->createInstanceWithContext(info->loader, ctxt),
|
||||||
|
css::uno::UNO_QUERY_THROW);
|
||||||
|
try {
|
||||||
|
f0 = loader->activate(
|
||||||
|
info->name, rtl::OUString(), uri,
|
||||||
|
css::uno::Reference< css::registry::XRegistryKey >());
|
||||||
|
} catch (css::loader::CannotActivateFactoryException & e) {
|
||||||
|
throw css::uno::DeploymentException(
|
||||||
|
"Cannot activate implementation " + uri + ": " + e.Message,
|
||||||
|
static_cast< cppu::OWeakObject * >(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
factory1->set(f0, css::uno::UNO_QUERY);
|
||||||
|
if (!factory1->is()) {
|
||||||
|
factory2->set(f0, css::uno::UNO_QUERY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rtl::OUString ServiceManager::getImplementationName()
|
rtl::OUString ServiceManager::getImplementationName()
|
||||||
throw (css::uno::RuntimeException)
|
throw (css::uno::RuntimeException)
|
||||||
{
|
{
|
||||||
@@ -852,7 +1002,7 @@ ServiceManager::createInstanceWithContext(
|
|||||||
return impl->factory2->createInstance();
|
return impl->factory2->createInstance();
|
||||||
}
|
}
|
||||||
throw css::uno::DeploymentException(
|
throw css::uno::DeploymentException(
|
||||||
"Implementation " + impl->name + " does not provide a factory",
|
"Implementation " + impl->info->name + " does not provide a factory",
|
||||||
static_cast< cppu::OWeakObject * >(this));
|
static_cast< cppu::OWeakObject * >(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -876,7 +1026,7 @@ ServiceManager::createInstanceWithArgumentsAndContext(
|
|||||||
return impl->factory2->createInstanceWithArguments(Arguments);
|
return impl->factory2->createInstanceWithArguments(Arguments);
|
||||||
}
|
}
|
||||||
throw css::uno::DeploymentException(
|
throw css::uno::DeploymentException(
|
||||||
"Implementation " + impl->name + " does not provide a factory",
|
"Implementation " + impl->info->name + " does not provide a factory",
|
||||||
static_cast< cppu::OWeakObject * >(this));
|
static_cast< cppu::OWeakObject * >(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1036,21 +1186,21 @@ ServiceManager::createContentEnumeration(rtl::OUString const & aServiceName)
|
|||||||
{
|
{
|
||||||
Implementation * impl = i->get();
|
Implementation * impl = i->get();
|
||||||
assert(impl != 0);
|
assert(impl != 0);
|
||||||
bool loaded;
|
|
||||||
{
|
{
|
||||||
osl::MutexGuard g(rBHelper.rMutex);
|
osl::MutexGuard g(rBHelper.rMutex);
|
||||||
if (isDisposed()) {
|
if (isDisposed()) {
|
||||||
factories.clear();
|
factories.clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
loaded = impl->loaded;
|
if (!impl->loaded) {
|
||||||
}
|
// Postpone actual factory instantiation as long as possible (so
|
||||||
//TODO: There is a race here, as the relevant service factory can be
|
// that e.g. opening LO's "Tools - Macros" menu does not try to
|
||||||
// removed while the mutex is unlocked and loading can thus fail, as the
|
// instantiate a JVM, which can lead to a synchronous error
|
||||||
// entity from which to load can disappear once the service factory is
|
// dialog when no JVM is specified, and showing the dialog while
|
||||||
// removed.
|
// hovering over a menu can cause trouble):
|
||||||
if (!loaded) {
|
impl->factory1 = new FactoryWrapper(this, impl->info);
|
||||||
loadImplementation(impl);
|
impl->loaded = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (impl->factory1.is()) {
|
if (impl->factory1.is()) {
|
||||||
factories.push_back(css::uno::makeAny(impl->factory1));
|
factories.push_back(css::uno::makeAny(impl->factory1));
|
||||||
@@ -1058,7 +1208,8 @@ ServiceManager::createContentEnumeration(rtl::OUString const & aServiceName)
|
|||||||
factories.push_back(css::uno::makeAny(impl->factory2));
|
factories.push_back(css::uno::makeAny(impl->factory2));
|
||||||
} else {
|
} else {
|
||||||
throw css::uno::DeploymentException(
|
throw css::uno::DeploymentException(
|
||||||
"Implementation " + impl->name + " does not provide a factory",
|
("Implementation " + impl->info->name
|
||||||
|
+ " does not provide a factory"),
|
||||||
static_cast< cppu::OWeakObject * >(this));
|
static_cast< cppu::OWeakObject * >(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1365,17 +1516,19 @@ bool ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) {
|
|||||||
uri + ": duplicate <implementation name=\"" + name + "\">",
|
uri + ": duplicate <implementation name=\"" + name + "\">",
|
||||||
css::uno::Reference< css::uno::XInterface >());
|
css::uno::Reference< css::uno::XInterface >());
|
||||||
}
|
}
|
||||||
readLegacyRdbStrings(uri, implKey, "UNO/SERVICES", &impl->services);
|
readLegacyRdbStrings(
|
||||||
|
uri, implKey, "UNO/SERVICES", &impl->info->services);
|
||||||
for (std::vector< rtl::OUString >::const_iterator j(
|
for (std::vector< rtl::OUString >::const_iterator j(
|
||||||
impl->services.begin());
|
impl->info->services.begin());
|
||||||
j != impl->services.end(); ++j)
|
j != impl->info->services.end(); ++j)
|
||||||
{
|
{
|
||||||
data_.services[*j].push_back(impl);
|
data_.services[*j].push_back(impl);
|
||||||
}
|
}
|
||||||
readLegacyRdbStrings(uri, implKey, "UNO/SINGLETONS", &impl->singletons);
|
readLegacyRdbStrings(
|
||||||
|
uri, implKey, "UNO/SINGLETONS", &impl->info->singletons);
|
||||||
for (std::vector< rtl::OUString >::const_iterator j(
|
for (std::vector< rtl::OUString >::const_iterator j(
|
||||||
impl->singletons.begin());
|
impl->info->singletons.begin());
|
||||||
j != impl->singletons.end(); ++j)
|
j != impl->info->singletons.end(); ++j)
|
||||||
{
|
{
|
||||||
data_.singletons[*j].push_back(impl);
|
data_.singletons[*j].push_back(impl);
|
||||||
}
|
}
|
||||||
@@ -1494,7 +1647,7 @@ void ServiceManager::insertLegacyFactory(
|
|||||||
css::uno::Sequence< rtl::OUString > services(
|
css::uno::Sequence< rtl::OUString > services(
|
||||||
factoryInfo->getSupportedServiceNames());
|
factoryInfo->getSupportedServiceNames());
|
||||||
for (sal_Int32 i = 0; i != services.getLength(); ++i) {
|
for (sal_Int32 i = 0; i != services.getLength(); ++i) {
|
||||||
impl->services.push_back(services[i]);
|
impl->info->services.push_back(services[i]);
|
||||||
extra.services[services[i]].push_back(impl);
|
extra.services[services[i]].push_back(impl);
|
||||||
}
|
}
|
||||||
if (insertExtraData(extra) && comp.is()) {
|
if (insertExtraData(extra) && comp.is()) {
|
||||||
@@ -1560,15 +1713,15 @@ bool ServiceManager::insertExtraData(Data const & extra) {
|
|||||||
assert(i->second[0].get() != 0);
|
assert(i->second[0].get() != 0);
|
||||||
SAL_INFO_IF(
|
SAL_INFO_IF(
|
||||||
i->second.size() > 1, "cppuhelper",
|
i->second.size() > 1, "cppuhelper",
|
||||||
"Arbitrarily chosing " << i->second[0]->name
|
"Arbitrarily chosing " << i->second[0]->info->name
|
||||||
<< " among multiple implementations for singleton "
|
<< " among multiple implementations for singleton "
|
||||||
<< i->first);
|
<< i->first);
|
||||||
try {
|
try {
|
||||||
cont->insertByName(
|
cont->insertByName(
|
||||||
name + "/service", css::uno::Any(i->second[0]->name));
|
name + "/service", css::uno::Any(i->second[0]->info->name));
|
||||||
} catch (css::container::ElementExistException &) {
|
} catch (css::container::ElementExistException &) {
|
||||||
cont->replaceByName(
|
cont->replaceByName(
|
||||||
name + "/service", css::uno::Any(i->second[0]->name));
|
name + "/service", css::uno::Any(i->second[0]->info->name));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
cont->insertByName(name, css::uno::Any());
|
cont->insertByName(name, css::uno::Any());
|
||||||
@@ -1594,13 +1747,13 @@ void ServiceManager::removeRdbFiles(std::vector< rtl::OUString > const & uris) {
|
|||||||
j != data_.namedImplementations.end();)
|
j != data_.namedImplementations.end();)
|
||||||
{
|
{
|
||||||
assert(j->second.get() != 0);
|
assert(j->second.get() != 0);
|
||||||
if (j->second->uri == *i) {
|
if (j->second->info->uri == *i) {
|
||||||
//TODO: The below leaves data_ in an inconsistent state upon
|
//TODO: The below leaves data_ in an inconsistent state upon
|
||||||
// exceptions:
|
// exceptions:
|
||||||
removeFromImplementationMap(
|
removeFromImplementationMap(
|
||||||
&data_.services, j->second->services, j->second);
|
&data_.services, j->second->info->services, j->second);
|
||||||
removeFromImplementationMap(
|
removeFromImplementationMap(
|
||||||
&data_.singletons, j->second->singletons, j->second);
|
&data_.singletons, j->second->info->singletons, j->second);
|
||||||
data_.namedImplementations.erase(j++);
|
data_.namedImplementations.erase(j++);
|
||||||
} else {
|
} else {
|
||||||
++j;
|
++j;
|
||||||
@@ -1626,11 +1779,11 @@ bool ServiceManager::removeLegacyFactory(
|
|||||||
assert(i->second.get() != 0);
|
assert(i->second.get() != 0);
|
||||||
//TODO: The below leaves data_ in an inconsistent state upon exceptions:
|
//TODO: The below leaves data_ in an inconsistent state upon exceptions:
|
||||||
removeFromImplementationMap(
|
removeFromImplementationMap(
|
||||||
&data_.services, i->second->services, i->second);
|
&data_.services, i->second->info->services, i->second);
|
||||||
removeFromImplementationMap(
|
removeFromImplementationMap(
|
||||||
&data_.singletons, i->second->singletons, i->second);
|
&data_.singletons, i->second->info->singletons, i->second);
|
||||||
if (!i->second->name.isEmpty()) {
|
if (!i->second->info->name.isEmpty()) {
|
||||||
data_.namedImplementations.erase(i->second->name);
|
data_.namedImplementations.erase(i->second->info->name);
|
||||||
}
|
}
|
||||||
data_.dynamicImplementations.erase(i);
|
data_.dynamicImplementations.erase(i);
|
||||||
if (removeListener) {
|
if (removeListener) {
|
||||||
@@ -1659,9 +1812,9 @@ void ServiceManager::removeImplementation(rtl::OUString name) {
|
|||||||
assert(i->second.get() != 0);
|
assert(i->second.get() != 0);
|
||||||
//TODO: The below leaves data_ in an inconsistent state upon exceptions:
|
//TODO: The below leaves data_ in an inconsistent state upon exceptions:
|
||||||
removeFromImplementationMap(
|
removeFromImplementationMap(
|
||||||
&data_.services, i->second->services, i->second);
|
&data_.services, i->second->info->services, i->second);
|
||||||
removeFromImplementationMap(
|
removeFromImplementationMap(
|
||||||
&data_.singletons, i->second->singletons, i->second);
|
&data_.singletons, i->second->info->singletons, i->second);
|
||||||
for (DynamicImplementations::iterator j(
|
for (DynamicImplementations::iterator j(
|
||||||
data_.dynamicImplementations.begin());
|
data_.dynamicImplementations.begin());
|
||||||
j != data_.dynamicImplementations.end(); ++j)
|
j != data_.dynamicImplementations.end(); ++j)
|
||||||
@@ -1694,7 +1847,7 @@ boost::shared_ptr< Implementation > ServiceManager::findServiceImplementation(
|
|||||||
assert(!i->second.empty());
|
assert(!i->second.empty());
|
||||||
SAL_INFO_IF(
|
SAL_INFO_IF(
|
||||||
i->second.size() > 1, "cppuhelper",
|
i->second.size() > 1, "cppuhelper",
|
||||||
"Arbitrarily chosing " << i->second[0]->name
|
"Arbitrarily chosing " << i->second[0]->info->name
|
||||||
<< " among multiple implementations for " << i->first);
|
<< " among multiple implementations for " << i->first);
|
||||||
impl = i->second[0];
|
impl = i->second[0];
|
||||||
}
|
}
|
||||||
@@ -1705,82 +1858,124 @@ boost::shared_ptr< Implementation > ServiceManager::findServiceImplementation(
|
|||||||
// while the mutex is unlocked and loading can thus fail, as the entity from
|
// while the mutex is unlocked and loading can thus fail, as the entity from
|
||||||
// which to load can disappear once the service factory is removed.
|
// which to load can disappear once the service factory is removed.
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
loadImplementation(impl.get());
|
css::uno::Reference< css::lang::XSingleComponentFactory > f1;
|
||||||
|
css::uno::Reference< css::lang::XSingleServiceFactory > f2;
|
||||||
|
loadImplementation(impl->info, &f1, &f2);
|
||||||
|
osl::MutexGuard g(rBHelper.rMutex);
|
||||||
|
if (!(isDisposed() || impl->loaded)) {
|
||||||
|
impl->loaded = true;
|
||||||
|
impl->factory1 = f1;
|
||||||
|
impl->factory2 = f2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return impl;
|
return impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceManager::loadImplementation(Implementation * implementation) {
|
css::uno::Reference< css::uno::XInterface >
|
||||||
assert(implementation != 0);
|
FactoryWrapper::createInstanceWithContext(
|
||||||
rtl::OUString uri;
|
css::uno::Reference< css::uno::XComponentContext > const & Context)
|
||||||
try {
|
throw (css::uno::Exception, css::uno::RuntimeException)
|
||||||
uri = cppu::bootstrap_expandUri(implementation->uri);
|
{
|
||||||
} catch (css::lang::IllegalArgumentException & e) {
|
loadImplementation();
|
||||||
throw css::uno::DeploymentException(
|
return factory1_.is()
|
||||||
"Cannot expand URI" + implementation->uri + ": " + e.Message,
|
? factory1_->createInstanceWithContext(Context)
|
||||||
|
: factory2_->createInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
css::uno::Reference< css::uno::XInterface >
|
||||||
|
FactoryWrapper::createInstanceWithArgumentsAndContext(
|
||||||
|
css::uno::Sequence< css::uno::Any > const & Arguments,
|
||||||
|
css::uno::Reference< css::uno::XComponentContext > const & Context)
|
||||||
|
throw (css::uno::Exception, css::uno::RuntimeException)
|
||||||
|
{
|
||||||
|
loadImplementation();
|
||||||
|
return factory1_.is()
|
||||||
|
? factory1_->createInstanceWithArgumentsAndContext(Arguments, Context)
|
||||||
|
: factory2_->createInstanceWithArguments(Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
css::uno::Reference< css::uno::XInterface > FactoryWrapper::createInstance()
|
||||||
|
throw (css::uno::Exception, css::uno::RuntimeException)
|
||||||
|
{
|
||||||
|
loadImplementation();
|
||||||
|
return factory1_.is()
|
||||||
|
? factory1_->createInstanceWithContext(manager_->getContext())
|
||||||
|
: factory2_->createInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
css::uno::Reference< css::uno::XInterface >
|
||||||
|
FactoryWrapper::createInstanceWithArguments(
|
||||||
|
css::uno::Sequence< css::uno::Any > const & Arguments)
|
||||||
|
throw (css::uno::Exception, css::uno::RuntimeException)
|
||||||
|
{
|
||||||
|
loadImplementation();
|
||||||
|
return factory1_.is()
|
||||||
|
? factory1_->createInstanceWithArgumentsAndContext(
|
||||||
|
Arguments, manager_->getContext())
|
||||||
|
: factory2_->createInstanceWithArguments(Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtl::OUString FactoryWrapper::getImplementationName()
|
||||||
|
throw (css::uno::RuntimeException)
|
||||||
|
{
|
||||||
|
return info_->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
sal_Bool FactoryWrapper::supportsService(rtl::OUString const & ServiceName)
|
||||||
|
throw (css::uno::RuntimeException)
|
||||||
|
{
|
||||||
|
css::uno::Sequence< rtl::OUString > names(getSupportedServiceNames());
|
||||||
|
for (sal_Int32 i = 0; i != names.getLength(); ++i) {
|
||||||
|
if (ServiceName == names[i]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
css::uno::Sequence< rtl::OUString > FactoryWrapper::getSupportedServiceNames()
|
||||||
|
throw (css::uno::RuntimeException)
|
||||||
|
{
|
||||||
|
if (info_->services.size() > static_cast< sal_uInt32 >(SAL_MAX_INT32)) {
|
||||||
|
throw css::uno::RuntimeException(
|
||||||
|
"Implementation " + info_->name + " supports too many services",
|
||||||
static_cast< cppu::OWeakObject * >(this));
|
static_cast< cppu::OWeakObject * >(this));
|
||||||
}
|
}
|
||||||
css::uno::Reference< css::uno::XInterface > f0;
|
css::uno::Sequence< rtl::OUString > names(
|
||||||
// Shortcut loading via SharedLibrary loader, to pass in prefix argument
|
static_cast< sal_Int32 >(info_->services.size()));
|
||||||
// (which the loader's activate implementation would normally obtain through
|
sal_Int32 i = 0;
|
||||||
// the legacy xKey argument):
|
for (std::vector< rtl::OUString >::const_iterator j(
|
||||||
if (!implementation->alienContext.is()
|
info_->services.begin());
|
||||||
&& implementation->loader == "com.sun.star.loader.SharedLibrary")
|
j != info_->services.end(); ++j)
|
||||||
{
|
{
|
||||||
rtl::OUString prefix(implementation->prefix);
|
names[i++] = *j;
|
||||||
if (!prefix.isEmpty()) {
|
}
|
||||||
prefix += "_";
|
return names;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
f0 = cppu::loadSharedLibComponentFactory(
|
void FactoryWrapper::loadImplementation() {
|
||||||
uri, rtl::OUString(), implementation->name, this,
|
{
|
||||||
css::uno::Reference< css::registry::XRegistryKey >(), prefix);
|
osl::MutexGuard g(mutex_);
|
||||||
} catch (css::loader::CannotActivateFactoryException & e) {
|
if (loaded_) {
|
||||||
throw css::uno::DeploymentException(
|
return;
|
||||||
"Cannot activate implementation " + uri + ": " + e.Message,
|
|
||||||
static_cast< cppu::OWeakObject * >(this));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SAL_INFO_IF(
|
|
||||||
!implementation->prefix.isEmpty(), "cppuhelper",
|
|
||||||
"Loader " << implementation->loader << " and non-empty prefix "
|
|
||||||
<< implementation->prefix);
|
|
||||||
css::uno::Reference< css::uno::XComponentContext > ctxt;
|
|
||||||
css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
|
|
||||||
if (implementation->alienContext.is()) {
|
|
||||||
ctxt = implementation->alienContext;
|
|
||||||
smgr = css::uno::Reference< css::lang::XMultiComponentFactory >(
|
|
||||||
ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
|
|
||||||
} else {
|
|
||||||
assert(context_.is());
|
|
||||||
ctxt = context_;
|
|
||||||
smgr = this;
|
|
||||||
}
|
|
||||||
css::uno::Reference< css::loader::XImplementationLoader > loader(
|
|
||||||
smgr->createInstanceWithContext(implementation->loader, ctxt),
|
|
||||||
css::uno::UNO_QUERY_THROW);
|
|
||||||
try {
|
|
||||||
f0 = loader->activate(
|
|
||||||
implementation->name, rtl::OUString(), uri,
|
|
||||||
css::uno::Reference< css::registry::XRegistryKey >());
|
|
||||||
} catch (css::loader::CannotActivateFactoryException & e) {
|
|
||||||
throw css::uno::DeploymentException(
|
|
||||||
"Cannot activate implementation " + uri + ": " + e.Message,
|
|
||||||
static_cast< cppu::OWeakObject * >(this));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
css::uno::Reference< css::lang::XSingleComponentFactory > f1(
|
css::uno::Reference< css::lang::XSingleComponentFactory > f1;
|
||||||
f0, css::uno::UNO_QUERY);
|
|
||||||
css::uno::Reference< css::lang::XSingleServiceFactory > f2;
|
css::uno::Reference< css::lang::XSingleServiceFactory > f2;
|
||||||
if (!f1.is()) {
|
//TODO: There is a race here, as the relevant service factory can already
|
||||||
f2 = css::uno::Reference< css::lang::XSingleServiceFactory >(
|
// have been removed and loading can thus fail, as the entity from which to
|
||||||
f0, css::uno::UNO_QUERY);
|
// load can disappear once the service factory is removed:
|
||||||
|
manager_->loadImplementation(info_, &f1, &f2);
|
||||||
|
if (!(f1.is() || f2.is())) {
|
||||||
|
throw css::uno::DeploymentException(
|
||||||
|
"Implementation " + info_->name + " does not provide a factory",
|
||||||
|
static_cast< cppu::OWeakObject * >(this));
|
||||||
}
|
}
|
||||||
osl::MutexGuard g(rBHelper.rMutex);
|
osl::MutexGuard g(mutex_);
|
||||||
if (!(isDisposed() || implementation->loaded)) {
|
if (!loaded_) {
|
||||||
implementation->loaded = true;
|
loaded_ = true;
|
||||||
implementation->factory1 = f1;
|
factory1_ = f1;
|
||||||
implementation->factory2 = f2;
|
factory2_ = f2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1818,12 +2013,12 @@ css::uno::Reference< css::uno::XComponentContext > bootstrapComponentContext(
|
|||||||
assert(i->second[0].get() != 0);
|
assert(i->second[0].get() != 0);
|
||||||
SAL_INFO_IF(
|
SAL_INFO_IF(
|
||||||
i->second.size() > 1, "cppuhelper",
|
i->second.size() > 1, "cppuhelper",
|
||||||
"Arbitrarily chosing " << i->second[0]->name
|
"Arbitrarily chosing " << i->second[0]->info->name
|
||||||
<< " among multiple implementations for " << i->first);
|
<< " among multiple implementations for " << i->first);
|
||||||
context_values.push_back(
|
context_values.push_back(
|
||||||
cppu::ContextEntry_Init(
|
cppu::ContextEntry_Init(
|
||||||
"/singletons/" + i->first,
|
"/singletons/" + i->first,
|
||||||
css::uno::makeAny(i->second[0]->name), true));
|
css::uno::makeAny(i->second[0]->info->name), true));
|
||||||
}
|
}
|
||||||
cppu::add_access_control_entries(&context_values, bootstrap);
|
cppu::add_access_control_entries(&context_values, bootstrap);
|
||||||
assert(!context_values.empty());
|
assert(!context_values.empty());
|
||||||
|
Reference in New Issue
Block a user