summaryrefslogtreecommitdiff
path: root/cppuhelper
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2014-01-16 15:29:41 +0100
committerStephan Bergmann <sbergman@redhat.com>2014-01-16 18:40:05 +0100
commit997d21183322a0a94b96868073808841d2773902 (patch)
tree250e92ab34ac79b4c3a8624a5e3ca8afb8df4d54 /cppuhelper
parent9c46e4069db51ab0fc8b3e197d27b5f947a3fdeb (diff)
Support for singleton constructor functions
The service manager now keeps track of instances of singleton implementations (i.e., implementations whose XML description lists at least one <singleton ...>). These instances will be disposed either when the service manager is disposed, or, for instances that have been instantiated into the component context's /singleton/* map, when the component context is disposed. This change allows to use constructor functions for such singleton implementations, too. Change-Id: I220c9ddc9824e4d7f7556daefb599e2ec36b0e6c
Diffstat (limited to 'cppuhelper')
-rw-r--r--cppuhelper/source/servicemanager.cxx456
-rw-r--r--cppuhelper/source/servicemanager.hxx31
2 files changed, 320 insertions, 167 deletions
diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx
index d7ab48ac447a..9bc31138447b 100644
--- a/cppuhelper/source/servicemanager.cxx
+++ b/cppuhelper/source/servicemanager.cxx
@@ -519,6 +519,58 @@ css::beans::Property getDefaultContextProperty() {
css::beans::PropertyAttribute::READONLY);
}
+class SingletonFactory:
+ public cppu::WeakImplHelper1<css::lang::XSingleComponentFactory>,
+ private boost::noncopyable
+{
+public:
+ SingletonFactory(
+ rtl::Reference< cppuhelper::ServiceManager > const & manager,
+ boost::shared_ptr<
+ cppuhelper::ServiceManager::Data::Implementation > const &
+ implementation):
+ manager_(manager), implementation_(implementation)
+ { assert(manager.is()); assert(implementation.get() != 0); }
+
+private:
+ virtual ~SingletonFactory() {}
+
+ 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);
+
+ rtl::Reference< cppuhelper::ServiceManager > manager_;
+ boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
+ implementation_;
+};
+
+css::uno::Reference< css::uno::XInterface >
+SingletonFactory::createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ manager_->loadImplementation(Context, implementation_);
+ return implementation_->createInstance(Context, true);
+}
+
+css::uno::Reference< css::uno::XInterface >
+SingletonFactory::createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ manager_->loadImplementation(Context, implementation_);
+ return implementation_->createInstanceWithArguments(
+ Context, true, Arguments);
+}
+
class ImplementationWrapper:
public cppu::WeakImplHelper3<
css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
@@ -529,10 +581,10 @@ public:
ImplementationWrapper(
rtl::Reference< cppuhelper::ServiceManager > const & manager,
boost::shared_ptr<
- cppuhelper::ServiceManager::Data::ImplementationInfo > const &
- info):
- manager_(manager), info_(info), loaded_(false), constructor_(0)
- { assert(manager.is() && info.get() != 0); }
+ cppuhelper::ServiceManager::Data::Implementation > const &
+ implementation):
+ manager_(manager), implementation_(implementation)
+ { assert(manager.is()); assert(implementation.get() != 0); }
private:
virtual ~ImplementationWrapper() {}
@@ -565,18 +617,9 @@ private:
virtual css::uno::Sequence< rtl::OUString > SAL_CALL
getSupportedServiceNames() throw (css::uno::RuntimeException);
- void loadImplementation(
- css::uno::Reference< css::uno::XComponentContext > const & context);
-
rtl::Reference< cppuhelper::ServiceManager > manager_;
- boost::shared_ptr< cppuhelper::ServiceManager::Data::ImplementationInfo >
- info_;
-
- osl::Mutex mutex_;
- bool loaded_;
- cppuhelper::ImplementationConstructorFn * constructor_;
- css::uno::Reference< css::lang::XSingleComponentFactory > factory1_;
- css::uno::Reference< css::lang::XSingleServiceFactory > factory2_;
+ boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
+ implementation_;
};
css::uno::Reference< css::uno::XInterface >
@@ -584,15 +627,8 @@ ImplementationWrapper::createInstanceWithContext(
css::uno::Reference< css::uno::XComponentContext > const & Context)
throw (css::uno::Exception, css::uno::RuntimeException)
{
- loadImplementation(Context);
- return constructor_ != 0
- ? css::uno::Reference<css::uno::XInterface>(
- (*constructor_)(
- Context.get(), css::uno::Sequence<css::uno::Any>()),
- SAL_NO_ACQUIRE)
- : factory1_.is()
- ? factory1_->createInstanceWithContext(Context)
- : factory2_->createInstance();
+ manager_->loadImplementation(Context, implementation_);
+ return implementation_->createInstance(Context, false);
}
css::uno::Reference< css::uno::XInterface >
@@ -601,19 +637,9 @@ ImplementationWrapper::createInstanceWithArgumentsAndContext(
css::uno::Reference< css::uno::XComponentContext > const & Context)
throw (css::uno::Exception, css::uno::RuntimeException)
{
- loadImplementation(Context);
- if (constructor_ != 0) {
- css::uno::Reference<css::uno::XInterface> xRet(
- (*constructor_)(Context.get(), Arguments), SAL_NO_ACQUIRE);
- css::uno::Reference<css::lang::XInitialization> xInit(
- xRet, css::uno::UNO_QUERY);
- if (xInit.is())
- xInit->initialize(Arguments);
- return xRet;
- } else
- return factory1_.is()
- ? factory1_->createInstanceWithArgumentsAndContext(Arguments, Context)
- : factory2_->createInstanceWithArguments(Arguments);
+ manager_->loadImplementation(Context, implementation_);
+ return implementation_->createInstanceWithArguments(
+ Context, false, Arguments);
}
css::uno::Reference< css::uno::XInterface >
@@ -635,7 +661,7 @@ ImplementationWrapper::createInstanceWithArguments(
rtl::OUString ImplementationWrapper::getImplementationName()
throw (css::uno::RuntimeException)
{
- return info_->name;
+ return implementation_->info->name;
}
sal_Bool ImplementationWrapper::supportsService(rtl::OUString const & ServiceName)
@@ -648,58 +674,149 @@ css::uno::Sequence< rtl::OUString >
ImplementationWrapper::getSupportedServiceNames()
throw (css::uno::RuntimeException)
{
- if (info_->services.size() > static_cast< sal_uInt32 >(SAL_MAX_INT32)) {
+ if (implementation_->info->services.size()
+ > static_cast< sal_uInt32 >(SAL_MAX_INT32))
+ {
throw css::uno::RuntimeException(
- "Implementation " + info_->name + " supports too many services",
+ ("Implementation " + implementation_->info->name
+ + " supports too many services"),
static_cast< cppu::OWeakObject * >(this));
}
css::uno::Sequence< rtl::OUString > names(
- static_cast< sal_Int32 >(info_->services.size()));
+ static_cast< sal_Int32 >(implementation_->info->services.size()));
sal_Int32 i = 0;
for (std::vector< rtl::OUString >::const_iterator j(
- info_->services.begin());
- j != info_->services.end(); ++j)
+ implementation_->info->services.begin());
+ j != implementation_->info->services.end(); ++j)
{
names[i++] = *j;
}
return names;
}
-void ImplementationWrapper::loadImplementation(
- css::uno::Reference< css::uno::XComponentContext > const & context)
+}
+
+css::uno::Reference<css::uno::XInterface>
+cppuhelper::ServiceManager::Data::Implementation::createInstance(
+ css::uno::Reference<css::uno::XComponentContext> const & context,
+ bool singletonRequest)
{
- {
- osl::MutexGuard g(mutex_);
- if (loaded_) {
- return;
+ if (info->singletons.empty()) {
+ assert(!singletonRequest);
+ if (constructor != 0) {
+ return css::uno::Reference<css::uno::XInterface>(
+ (*constructor)(
+ context.get(), css::uno::Sequence<css::uno::Any>()),
+ SAL_NO_ACQUIRE);
+ }
+ if (factory1.is()) {
+ return factory1->createInstanceWithContext(context);
+ }
+ if (factory2.is()) {
+ return factory2->createInstance();
}
- }
- cppuhelper::ImplementationConstructorFn * ctor = 0;
- css::uno::Reference< css::lang::XSingleComponentFactory > f1;
- css::uno::Reference< css::lang::XSingleServiceFactory > f2;
- //TODO: There is a race here, as the relevant service factory can already
- // have been removed and loading can thus fail, as the entity from which to
- // load can disappear once the service factory is removed:
- manager_->loadImplementation(context, info_, &ctor, &f1, &f2);
- if (ctor == 0 && !f1.is() && !f2.is()) {
throw css::uno::DeploymentException(
- ("Implementation " + info_->name
+ ("Implementation " + info->name
+ " does not provide a constructor or factory"),
- static_cast< cppu::OWeakObject * >(this));
- }
- osl::MutexGuard g(mutex_);
- if (!loaded_) {
- loaded_ = true;
- constructor_ = ctor;
- factory1_ = f1;
- factory2_ = f2;
+ css::uno::Reference<css::uno::XInterface>());
+ } else {
+ osl::MutexGuard g(mutex); //TODO: must be a non-recursive mutex
+ if (singleton.is()) {
+ if (singletonRequest) {
+ dispose = false;
+ }
+ return singleton;
+ }
+ if (constructor != 0) {
+ singleton.set(
+ (*constructor)(
+ context.get(), css::uno::Sequence<css::uno::Any>()),
+ SAL_NO_ACQUIRE);
+ } else if (factory1.is()) {
+ singleton = factory1->createInstanceWithContext(context);
+ } else if (factory2.is()) {
+ singleton = factory2->createInstance();
+ } else {
+ throw css::uno::DeploymentException(
+ ("Implementation " + info->name
+ + " does not provide a constructor or factory"),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ dispose = singleton.is() && !singletonRequest;
+ return singleton;
}
}
+css::uno::Reference<css::uno::XInterface>
+cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
+ css::uno::Reference<css::uno::XComponentContext> const & context,
+ bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
+{
+ if (info->singletons.empty()) {
+ assert(!singletonRequest);
+ if (constructor != 0) {
+ //HACK: The constructor will either observe arguments and return
+ // inst that does not implement XInitialization (or null), or ignore
+ // arguments and return inst that implements XInitialization; this
+ // should be removed again once XInitialization-based
+ // implementations have become rare:
+ css::uno::Reference<css::uno::XInterface> inst(
+ (*constructor)(context.get(), arguments), SAL_NO_ACQUIRE);
+ css::uno::Reference<css::lang::XInitialization> init(
+ inst, css::uno::UNO_QUERY);
+ if (init.is()) {
+ init->initialize(arguments);
+ }
+ return inst;
+ }
+ if (factory1.is()) {
+ return factory1->createInstanceWithArgumentsAndContext(
+ arguments, context);
+ }
+ if (factory2.is()) {
+ return factory2->createInstanceWithArguments(arguments);
+ }
+ throw css::uno::DeploymentException(
+ "Implementation " + info->name + " does not provide a factory",
+ css::uno::Reference<css::uno::XInterface>());
+ } else {
+ osl::MutexGuard g(mutex); //TODO: must be a non-recursive mutex
+ if (singleton.is()) {
+ SAL_WARN(
+ "cppuhelper",
+ "createInstanceWithArguments request for already instantiated"
+ " singleton implementation " << info->name);
+ if (singletonRequest) {
+ dispose = false;
+ }
+ return singleton;
+ }
+ if (constructor != 0) {
+ //HACK: see above
+ singleton.set(
+ (*constructor)(context.get(), arguments), SAL_NO_ACQUIRE);
+ css::uno::Reference<css::lang::XInitialization> init(
+ singleton, css::uno::UNO_QUERY);
+ if (init.is()) {
+ init->initialize(arguments);
+ }
+ } else if (factory1.is()) {
+ singleton = factory1->createInstanceWithArgumentsAndContext(
+ arguments, context);
+ } else if (factory2.is()) {
+ singleton = factory2->createInstanceWithArguments(arguments);
+ } else {
+ throw css::uno::DeploymentException(
+ "Implementation " + info->name + " does not provide a factory",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ dispose = singleton.is() && !singletonRequest;
+ return singleton;
+ }
}
void cppuhelper::ServiceManager::addSingletonContextEntries(
- std::vector< cppu::ContextEntry_Init > * entries) const
+ std::vector< cppu::ContextEntry_Init > * entries)
{
assert(entries != 0);
for (Data::ImplementationMap::const_iterator i(data_.singletons.begin());
@@ -714,44 +831,50 @@ void cppuhelper::ServiceManager::addSingletonContextEntries(
entries->push_back(
cppu::ContextEntry_Init(
"/singletons/" + i->first,
- css::uno::makeAny(i->second[0]->info->name), true));
+ css::uno::makeAny<
+ css::uno::Reference<css::lang::XSingleComponentFactory> >(
+ new SingletonFactory(this, i->second[0])),
+ true));
}
}
void cppuhelper::ServiceManager::loadImplementation(
css::uno::Reference< css::uno::XComponentContext > const & context,
- boost::shared_ptr< Data::ImplementationInfo > const & info,
- ImplementationConstructorFn ** constructor,
- css::uno::Reference< css::lang::XSingleComponentFactory > * factory1,
- css::uno::Reference< css::lang::XSingleServiceFactory > * factory2)
+ boost::shared_ptr< Data::Implementation > & implementation)
{
- assert(
- info.get() != 0 && constructor != 0 && *constructor == 0
- && factory1 != 0 && !factory1->is() && factory2 != 0
- && !factory2->is());
+ assert(implementation.get() != 0);
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (implementation->status == Data::Implementation::STATUS_LOADED) {
+ return;
+ }
+ }
rtl::OUString uri;
try {
- uri = cppu::bootstrap_expandUri(info->uri);
+ uri = cppu::bootstrap_expandUri(implementation->info->uri);
} catch (css::lang::IllegalArgumentException & e) {
throw css::uno::DeploymentException(
- "Cannot expand URI" + info->uri + ": " + e.Message,
+ "Cannot expand URI" + implementation->info->uri + ": " + e.Message,
static_cast< cppu::OWeakObject * >(this));
}
+ cppuhelper::ImplementationConstructorFn * ctor = 0;
css::uno::Reference< css::uno::XInterface > f0;
// Special handling of SharedLibrary loader, with support for environment,
// constructor, and prefix arguments:
- if (!info->alienContext.is()
- && info->loader == "com.sun.star.loader.SharedLibrary")
+ if (!implementation->info->alienContext.is()
+ && implementation->info->loader == "com.sun.star.loader.SharedLibrary")
{
cppuhelper::detail::loadSharedLibComponentFactory(
- uri, info->environment, info->prefix, info->name, info->constructor,
- this, constructor, &f0);
- if (constructor != 0 && *constructor != 0) {
- assert(!info->environment.isEmpty());
+ uri, implementation->info->environment,
+ implementation->info->prefix, implementation->info->name,
+ implementation->info->constructor, this, &ctor, &f0);
+ if (ctor != 0) {
+ assert(!implementation->info->environment.isEmpty());
css::uno::Environment curEnv(css::uno::Environment::getCurrent());
css::uno::Environment env(
cppuhelper::detail::getEnvironment(
- info->environment, info->name));
+ implementation->info->environment,
+ implementation->info->name));
if (!(curEnv.is() && env.is())) {
throw css::uno::DeploymentException(
"cannot get environments",
@@ -763,21 +886,23 @@ void cppuhelper::ServiceManager::loadImplementation(
}
} else {
SAL_WARN_IF(
- !info->environment.isEmpty(), "cppuhelper",
- "Loader " << info->loader << " and non-empty environment "
- << info->environment);
+ !implementation->info->environment.isEmpty(), "cppuhelper",
+ "Loader " << implementation->info->loader
+ << " and non-empty environment "
+ << implementation->info->environment);
SAL_WARN_IF(
- !info->prefix.isEmpty(), "cppuhelper",
- "Loader " << info->loader << " and non-empty constructor "
- << info->constructor);
+ !implementation->info->prefix.isEmpty(), "cppuhelper",
+ "Loader " << implementation->info->loader
+ << " and non-empty constructor "
+ << implementation->info->constructor);
SAL_WARN_IF(
- !info->prefix.isEmpty(), "cppuhelper",
- "Loader " << info->loader << " and non-empty prefix "
- << info->prefix);
+ !implementation->info->prefix.isEmpty(), "cppuhelper",
+ "Loader " << implementation->info->loader
+ << " and non-empty prefix " << implementation->info->prefix);
css::uno::Reference< css::uno::XComponentContext > ctxt;
css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
- if (info->alienContext.is()) {
- ctxt = info->alienContext;
+ if (implementation->info->alienContext.is()) {
+ ctxt = implementation->info->alienContext;
smgr = css::uno::Reference< css::lang::XMultiComponentFactory >(
ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
} else {
@@ -786,28 +911,69 @@ void cppuhelper::ServiceManager::loadImplementation(
smgr = this;
}
css::uno::Reference< css::loader::XImplementationLoader > loader(
- smgr->createInstanceWithContext(info->loader, ctxt),
+ smgr->createInstanceWithContext(implementation->info->loader, ctxt),
css::uno::UNO_QUERY_THROW);
f0 = loader->activate(
- info->name, rtl::OUString(), uri,
+ implementation->info->name, rtl::OUString(), uri,
css::uno::Reference< css::registry::XRegistryKey >());
}
- factory1->set(f0, css::uno::UNO_QUERY);
- if (!factory1->is()) {
- factory2->set(f0, css::uno::UNO_QUERY);
+ css::uno::Reference<css::lang::XSingleComponentFactory> f1;
+ css::uno::Reference<css::lang::XSingleServiceFactory> f2;
+ if (ctor == 0) {
+ f1.set(f0, css::uno::UNO_QUERY);
+ if (!f1.is()) {
+ f2.set(f0, css::uno::UNO_QUERY);
+ if (!f2.is()) {
+ throw css::uno::DeploymentException(
+ ("Implementation " + implementation->info->name
+ + " does not provide a constructor or factory"),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ }
+ }
+ //TODO: There is a race here, as the relevant service factory can be removed
+ // 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.
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (!(isDisposed()
+ || implementation->status == Data::Implementation::STATUS_LOADED))
+ {
+ implementation->status = Data::Implementation::STATUS_LOADED;
+ implementation->constructor = ctor;
+ implementation->factory1 = f1;
+ implementation->factory2 = f2;
}
}
void cppuhelper::ServiceManager::disposing() {
+ std::vector< css::uno::Reference<css::uno::XInterface> > sngls;
std::vector< css::uno::Reference< css::lang::XComponent > > comps;
Data clear;
{
osl::MutexGuard g(rBHelper.rMutex);
+ for (Data::NamedImplementations::const_iterator i(
+ data_.namedImplementations.begin());
+ i != data_.namedImplementations.end(); ++i)
+ {
+ assert(i->second.get() != 0);
+ if (!i->second->info->singletons.empty()) {
+ osl::MutexGuard g2(i->second->mutex);
+ if (i->second->dispose) {
+ sngls.push_back(i->second->singleton);
+ }
+ }
+ }
for (Data::DynamicImplementations::const_iterator i(
data_.dynamicImplementations.begin());
i != data_.dynamicImplementations.end(); ++i)
{
assert(i->second.get() != 0);
+ if (!i->second->info->singletons.empty()) {
+ osl::MutexGuard g2(i->second->mutex);
+ if (i->second->dispose) {
+ sngls.push_back(i->second->singleton);
+ }
+ }
if (i->second->component.is()) {
comps.push_back(i->second->component);
}
@@ -818,6 +984,24 @@ void cppuhelper::ServiceManager::disposing() {
data_.singletons.swap(clear.singletons);
}
for (std::vector<
+ css::uno::Reference<css::uno::XInterface> >::const_iterator i(
+ sngls.begin());
+ i != sngls.end(); ++i)
+ {
+ css::uno::Reference<css::lang::XComponent> comp(
+ *i, css::uno::UNO_QUERY);
+ if (comp.is()) {
+ try {
+ comp->dispose();
+ } catch (css::uno::RuntimeException & e) {
+ SAL_WARN(
+ "cppuhelper",
+ "Ignoring RuntimeException \"" << e.Message
+ << "\" while disposing singleton");
+ }
+ }
+ }
+ for (std::vector<
css::uno::Reference< css::lang::XComponent > >::const_iterator i(
comps.begin());
i != comps.end(); ++i)
@@ -903,23 +1087,9 @@ cppuhelper::ServiceManager::createInstanceWithContext(
{
boost::shared_ptr< Data::Implementation > impl(
findServiceImplementation(Context, aServiceSpecifier));
- if (impl.get() == 0) {
- return css::uno::Reference< css::uno::XInterface >();
- }
- if (impl->constructor != 0) {
- return css::uno::Reference<css::uno::XInterface>(
- (*impl->constructor)(
- Context.get(), css::uno::Sequence<css::uno::Any>()),
- SAL_NO_ACQUIRE);
- } else if (impl->factory1.is()) {
- return impl->factory1->createInstanceWithContext(Context);
- }
- if (impl->factory2.is()) {
- return impl->factory2->createInstance();
- }
- throw css::uno::DeploymentException(
- "Implementation " + impl->info->name + " does not provide a factory",
- static_cast< cppu::OWeakObject * >(this));
+ return impl.get() == 0
+ ? css::uno::Reference< css::uno::XInterface >()
+ : impl->createInstance(Context, false);
}
css::uno::Reference< css::uno::XInterface >
@@ -931,28 +1101,9 @@ cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
{
boost::shared_ptr< Data::Implementation > impl(
findServiceImplementation(Context, ServiceSpecifier));
- if (impl.get() == 0) {
- return css::uno::Reference< css::uno::XInterface >();
- }
- if (impl->constructor != 0) {
- css::uno::Reference<css::uno::XInterface> xRet(
- (*impl->constructor)(Context.get(), Arguments),
- SAL_NO_ACQUIRE);
- css::uno::Reference<css::lang::XInitialization> xInit(
- xRet, css::uno::UNO_QUERY);
- if (xInit.is())
- xInit->initialize(Arguments);
- return xRet;
- } else if (impl->factory1.is()) {
- return impl->factory1->createInstanceWithArgumentsAndContext(
- Arguments, Context);
- }
- if (impl->factory2.is()) {
- return impl->factory2->createInstanceWithArguments(Arguments);
- }
- throw css::uno::DeploymentException(
- "Implementation " + impl->info->name + " does not provide a factory",
- static_cast< cppu::OWeakObject * >(this));
+ return impl.get() == 0
+ ? css::uno::Reference< css::uno::XInterface >()
+ : impl->createInstanceWithArguments(Context, false, Arguments);
}
css::uno::Type cppuhelper::ServiceManager::getElementType()
@@ -1126,15 +1277,15 @@ cppuhelper::ServiceManager::createContentEnumeration(
factories.clear();
break;
}
- if (!impl->loaded) {
+ if (impl->status == Data::Implementation::STATUS_NEW) {
// Postpone actual implementation instantiation as long as
// possible (so that e.g. opening LO's "Tools - Macros" menu
// does not try to instantiate a JVM, which can lead to a
// synchronous error dialog when no JVM is specified, and
// showing the dialog while hovering over a menu can cause
// trouble):
- impl->factory1 = new ImplementationWrapper(this, impl->info);
- impl->loaded = true;
+ impl->factory1 = new ImplementationWrapper(this, *i);
+ impl->status = Data::Implementation::STATUS_WRAPPER;
}
}
if (impl->factory1.is()) {
@@ -1784,23 +1935,10 @@ cppuhelper::ServiceManager::findServiceImplementation(
impl = i->second[0];
}
assert(impl.get() != 0);
- loaded = impl->loaded;
+ loaded = impl->status == Data::Implementation::STATUS_LOADED;
}
- //TODO: There is a race here, as the relevant service factory can be removed
- // 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.
if (!loaded) {
- cppuhelper::ImplementationConstructorFn * ctor = 0;
- css::uno::Reference< css::lang::XSingleComponentFactory > f1;
- css::uno::Reference< css::lang::XSingleServiceFactory > f2;
- loadImplementation(context, impl->info, &ctor, &f1, &f2);
- osl::MutexGuard g(rBHelper.rMutex);
- if (!(isDisposed() || impl->loaded)) {
- impl->loaded = true;
- impl->constructor = ctor;
- impl->factory1 = f1;
- impl->factory2 = f2;
- }
+ loadImplementation(context, impl);
}
return impl;
}
diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx
index 74f2f4acb51f..cefeb316bd9c 100644
--- a/cppuhelper/source/servicemanager.hxx
+++ b/cppuhelper/source/servicemanager.hxx
@@ -105,7 +105,7 @@ public:
new ImplementationInfo(
name, loader, uri, environment, constructorName, prefix,
alienContext, rdbFile)),
- constructor(0), loaded(false)
+ constructor(0), status(STATUS_NEW)
{}
Implementation(
@@ -118,15 +118,33 @@ public:
theComponent):
info(new ImplementationInfo(name)), constructor(0),
factory1(theFactory1), factory2(theFactory2),
- component(theComponent), loaded(true)
+ component(theComponent), status(STATUS_LOADED)
{}
+ css::uno::Reference<css::uno::XInterface> createInstance(
+ css::uno::Reference<css::uno::XComponentContext> const &
+ context,
+ bool singletonRequest);
+
+ css::uno::Reference<css::uno::XInterface>
+ createInstanceWithArguments(
+ css::uno::Reference<css::uno::XComponentContext> const &
+ context,
+ bool singletonRequest,
+ css::uno::Sequence<css::uno::Any> const & arguments);
+
+ enum Status { STATUS_NEW, STATUS_WRAPPER, STATUS_LOADED };
+
boost::shared_ptr< ImplementationInfo > info;
ImplementationConstructorFn * constructor;
css::uno::Reference< css::lang::XSingleComponentFactory > factory1;
css::uno::Reference< css::lang::XSingleServiceFactory > factory2;
css::uno::Reference< css::lang::XComponent > component;
- bool loaded;
+ Status status;
+
+ osl::Mutex mutex;
+ css::uno::Reference<css::uno::XInterface> singleton;
+ bool dispose;
};
typedef std::map< rtl::OUString, boost::shared_ptr< Implementation > >
@@ -166,7 +184,7 @@ public:
}
void addSingletonContextEntries(
- std::vector< cppu::ContextEntry_Init > * entries) const;
+ std::vector< cppu::ContextEntry_Init > * entries);
css::uno::Reference< css::uno::XComponentContext > getContext() const {
assert(context_.is());
@@ -175,10 +193,7 @@ public:
void loadImplementation(
css::uno::Reference< css::uno::XComponentContext > const & context,
- boost::shared_ptr< Data::ImplementationInfo > const & info,
- ImplementationConstructorFn ** constructor,
- css::uno::Reference< css::lang::XSingleComponentFactory > * factory1,
- css::uno::Reference< css::lang::XSingleServiceFactory > * factory2);
+ boost::shared_ptr< Data::Implementation > & implementation);
private:
virtual ~ServiceManager() {}