summaryrefslogtreecommitdiff
path: root/cppuhelper
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2013-12-19 08:48:56 +0100
committerStephan Bergmann <sbergman@redhat.com>2013-12-19 08:48:56 +0100
commitae3a0c8da50b36db395984637f5ad74d3b4887bc (patch)
treec4936b9fba1f24d412d41474ebef44a5f094dbc8 /cppuhelper
parent80d977b896904a0261d32857469c1b3e7516ca1e (diff)
Add .component <implementation constructor="..." feature
...to directly call constructor functions of ComponentContext-based C++ implementations of (non-single-instance) UNO services. The case where these calls would need to be bridged across different environments (e.g., from gcc3 to gcc3:affine) is not yet implemented. bootstrap.component and expwrap.component are adapted accordingly as a proof-of- concept (which had previously been adapted to use the prefix="direct" feature, which may become unnecessary again in the end, depending on how to handle single-instance services/singletons). More to follow. Change-Id: I18682d75bcd29d3d427e31331b4ce8161dbb846d
Diffstat (limited to 'cppuhelper')
-rw-r--r--cppuhelper/source/loadsharedlibcomponentfactory.hxx19
-rw-r--r--cppuhelper/source/servicemanager.cxx156
-rw-r--r--cppuhelper/source/servicemanager.hxx31
-rw-r--r--cppuhelper/source/shlib.cxx659
4 files changed, 434 insertions, 431 deletions
diff --git a/cppuhelper/source/loadsharedlibcomponentfactory.hxx b/cppuhelper/source/loadsharedlibcomponentfactory.hxx
index 9809c558cc09..9119674f9af6 100644
--- a/cppuhelper/source/loadsharedlibcomponentfactory.hxx
+++ b/cppuhelper/source/loadsharedlibcomponentfactory.hxx
@@ -14,18 +14,29 @@
#include <com/sun/star/uno/Reference.hxx>
+#include <servicemanager.hxx>
+
namespace com { namespace sun { namespace star {
namespace lang { class XMultiServiceFactory; }
- namespace uno { class XInterface; }
+ namespace uno {
+ class Environment;
+ class XInterface;
+ }
} } }
namespace rtl { class OUString; }
namespace cppuhelper { namespace detail {
-css::uno::Reference<css::uno::XInterface> loadSharedLibComponentFactory(
+css::uno::Environment getEnvironment(
+ rtl::OUString const & name, rtl::OUString const & implementation);
+
+void loadSharedLibComponentFactory(
rtl::OUString const & uri, rtl::OUString const & environment,
- rtl::OUString const & prefix, rtl::OUString const & rImplName,
- css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr);
+ rtl::OUString const & prefix, rtl::OUString const & implementation,
+ rtl::OUString const & constructor,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager,
+ ImplementationConstructorFn ** constructorFunction,
+ css::uno::Reference<css::uno::XInterface> * factory);
} }
diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx
index 3420233cc743..9a271d2e383a 100644
--- a/cppuhelper/source/servicemanager.cxx
+++ b/cppuhelper/source/servicemanager.cxx
@@ -40,6 +40,7 @@
#include "rtl/ustring.hxx"
#include "rtl/strbuf.hxx"
#include "sal/log.hxx"
+#include "uno/environment.hxx"
#include <loadsharedlibcomponentfactory.hxx>
@@ -344,18 +345,76 @@ void Parser::handleComponent() {
}
void Parser::handleImplementation() {
- OUString name(getNameAttribute());
+ rtl::OUString attrName;
+ rtl::OUString attrConstructor;
+ xmlreader::Span name;
+ int nsId;
+ while (reader_.nextAttribute(&nsId, &name)) {
+ if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ if (!attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + ": <implementation> has multiple \"name\" attributes"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ attrName = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + ": <implementation> has empty \"name\" attribute"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("constructor")))
+ {
+ if (!attrConstructor.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + (": <implementation> has multiple \"constructor\""
+ " attributes")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ attrConstructor = reader_.getAttributeValue(false)
+ .convertFromUtf8();
+ if (attrConstructor.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + ": element has empty \"constructor\" attribute"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (attrEnvironment_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + (": <implementation> has \"constructor\" attribute but"
+ " <component> has no \"environment\" attribute")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl() + ": unexpected element attribute \""
+ + name.convertFromUtf8() + "\" in <implementation>"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ if (attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + ": <implementation> is missing \"name\" attribute"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
implementation_.reset(
new cppuhelper::ServiceManager::Data::Implementation(
- name, attrLoader_, attrUri_, attrEnvironment_, attrPrefix_,
- alienContext_, reader_.getUrl()));
+ attrName, attrLoader_, attrUri_, attrEnvironment_, attrConstructor,
+ attrPrefix_, alienContext_, reader_.getUrl()));
if (!data_->namedImplementations.insert(
cppuhelper::ServiceManager::Data::NamedImplementations::value_type(
- name, implementation_)).
+ attrName, implementation_)).
second)
{
throw css::registry::InvalidRegistryException(
- (reader_.getUrl() + ": duplicate <implementation name=\"" + name
+ (reader_.getUrl() + ": duplicate <implementation name=\"" + attrName
+ "\">"),
css::uno::Reference< css::uno::XInterface >());
}
@@ -471,7 +530,7 @@ public:
boost::shared_ptr<
cppuhelper::ServiceManager::Data::ImplementationInfo > const &
info):
- manager_(manager), info_(info), loaded_(false)
+ manager_(manager), info_(info), loaded_(false), constructor_(0)
{ assert(manager.is() && info.get() != 0); }
private:
@@ -514,6 +573,7 @@ private:
osl::Mutex mutex_;
bool loaded_;
+ cppuhelper::ImplementationConstructorFn * constructor_;
css::uno::Reference< css::lang::XSingleComponentFactory > factory1_;
css::uno::Reference< css::lang::XSingleServiceFactory > factory2_;
};
@@ -524,7 +584,12 @@ FactoryWrapper::createInstanceWithContext(
throw (css::uno::Exception, css::uno::RuntimeException)
{
loadImplementation(Context);
- return factory1_.is()
+ return constructor_ != 0
+ ? css::uno::Reference<css::uno::XInterface>(
+ (*constructor_)(
+ Context.get(), css::uno::Sequence<css::uno::Any>().get()),
+ SAL_NO_ACQUIRE)
+ : factory1_.is()
? factory1_->createInstanceWithContext(Context)
: factory2_->createInstance();
}
@@ -536,7 +601,10 @@ FactoryWrapper::createInstanceWithArgumentsAndContext(
throw (css::uno::Exception, css::uno::RuntimeException)
{
loadImplementation(Context);
- return factory1_.is()
+ return constructor_ != 0
+ ? css::uno::Reference<css::uno::XInterface>(
+ (*constructor_)(Context.get(), Arguments.get()), SAL_NO_ACQUIRE)
+ : factory1_.is()
? factory1_->createInstanceWithArgumentsAndContext(Arguments, Context)
: factory2_->createInstanceWithArguments(Arguments);
}
@@ -544,10 +612,7 @@ FactoryWrapper::createInstanceWithArgumentsAndContext(
css::uno::Reference< css::uno::XInterface > FactoryWrapper::createInstance()
throw (css::uno::Exception, css::uno::RuntimeException)
{
- loadImplementation(manager_->getContext());
- return factory1_.is()
- ? factory1_->createInstanceWithContext(manager_->getContext())
- : factory2_->createInstance();
+ return createInstanceWithContext(manager_->getContext());
}
css::uno::Reference< css::uno::XInterface >
@@ -555,11 +620,8 @@ FactoryWrapper::createInstanceWithArguments(
css::uno::Sequence< css::uno::Any > const & Arguments)
throw (css::uno::Exception, css::uno::RuntimeException)
{
- loadImplementation(manager_->getContext());
- return factory1_.is()
- ? factory1_->createInstanceWithArgumentsAndContext(
- Arguments, manager_->getContext())
- : factory2_->createInstanceWithArguments(Arguments);
+ return createInstanceWithArgumentsAndContext(
+ Arguments, manager_->getContext());
}
rtl::OUString FactoryWrapper::getImplementationName()
@@ -603,20 +665,23 @@ void FactoryWrapper::loadImplementation(
return;
}
}
+ 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_, &f1, &f2);
- if (!(f1.is() || f2.is())) {
+ manager_->loadImplementation(context, info_, &ctor, &f1, &f2);
+ if (ctor == 0 && !f1.is() && !f2.is()) {
throw css::uno::DeploymentException(
- "Implementation " + info_->name + " does not provide a factory",
+ ("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;
}
@@ -647,11 +712,13 @@ void cppuhelper::ServiceManager::addSingletonContextEntries(
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)
{
assert(
- info.get() != 0 && factory1 != 0 && !factory1->is() && factory2 != 0
+ info.get() != 0 && constructor != 0 && *constructor == 0
+ && factory1 != 0 && !factory1->is() && factory2 != 0
&& !factory2->is());
rtl::OUString uri;
try {
@@ -662,13 +729,29 @@ void cppuhelper::ServiceManager::loadImplementation(
static_cast< cppu::OWeakObject * >(this));
}
css::uno::Reference< css::uno::XInterface > f0;
- // Shortcut loading via SharedLibrary loader, to pass in environment and
- // prefix arguments:
+ // Special handling of SharedLibrary loader, with support for environment,
+ // constructor, and prefix arguments:
if (!info->alienContext.is()
&& info->loader == "com.sun.star.loader.SharedLibrary")
{
- f0 = cppuhelper::detail::loadSharedLibComponentFactory(
- uri, info->environment, info->prefix, info->name, this);
+ cppuhelper::detail::loadSharedLibComponentFactory(
+ uri, info->environment, info->prefix, info->name, info->constructor,
+ this, constructor, &f0);
+ if (constructor != 0 && *constructor != 0) {
+ assert(!info->environment.isEmpty());
+ css::uno::Environment curEnv(css::uno::Environment::getCurrent());
+ css::uno::Environment env(
+ cppuhelper::detail::getEnvironment(
+ info->environment, info->name));
+ if (!(curEnv.is() && env.is())) {
+ throw css::uno::DeploymentException(
+ "cannot get environments",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ if (curEnv.get() != env.get()) {
+ std::abort();//TODO
+ }
+ }
} else {
SAL_WARN_IF(
!info->environment.isEmpty(), "cppuhelper",
@@ -676,6 +759,10 @@ void cppuhelper::ServiceManager::loadImplementation(
<< info->environment);
SAL_WARN_IF(
!info->prefix.isEmpty(), "cppuhelper",
+ "Loader " << info->loader << " and non-empty constructor "
+ << info->constructor);
+ SAL_WARN_IF(
+ !info->prefix.isEmpty(), "cppuhelper",
"Loader " << info->loader << " and non-empty prefix "
<< info->prefix);
css::uno::Reference< css::uno::XComponentContext > ctxt;
@@ -810,7 +897,12 @@ cppuhelper::ServiceManager::createInstanceWithContext(
if (impl.get() == 0) {
return css::uno::Reference< css::uno::XInterface >();
}
- if (impl->factory1.is()) {
+ if (impl->constructor != 0) {
+ return css::uno::Reference<css::uno::XInterface>(
+ (*impl->constructor)(
+ Context.get(), css::uno::Sequence<css::uno::Any>().get()),
+ SAL_NO_ACQUIRE);
+ } else if (impl->factory1.is()) {
return impl->factory1->createInstanceWithContext(Context);
}
if (impl->factory2.is()) {
@@ -833,7 +925,11 @@ cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
if (impl.get() == 0) {
return css::uno::Reference< css::uno::XInterface >();
}
- if (impl->factory1.is()) {
+ if (impl->constructor != 0) {
+ return css::uno::Reference<css::uno::XInterface>(
+ (*impl->constructor)(Context.get(), Arguments.get()),
+ SAL_NO_ACQUIRE);
+ } else if (impl->factory1.is()) {
return impl->factory1->createInstanceWithArgumentsAndContext(
Arguments, Context);
}
@@ -1309,7 +1405,7 @@ bool cppuhelper::ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) {
boost::shared_ptr< Data::Implementation > impl(
new Data::Implementation(
name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"),
- readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "",
+ readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "", "",
css::uno::Reference< css::uno::XComponentContext >(), uri));
if (!data_.namedImplementations.insert(
Data::NamedImplementations::value_type(name, impl)).
@@ -1679,12 +1775,14 @@ cppuhelper::ServiceManager::findServiceImplementation(
// 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, &f1, &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;
}
diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx
index b68cd4b95edd..d76b93f9a4f6 100644
--- a/cppuhelper/source/servicemanager.hxx
+++ b/cppuhelper/source/servicemanager.hxx
@@ -34,10 +34,20 @@
#include "registry/registry.hxx"
#include "rtl/ustring.hxx"
+namespace com { namespace sun { namespace star { namespace lang {
+ class XSingleComponentFactory;
+} } } }
namespace cppu { struct ContextEntry_Init; }
namespace cppuhelper {
+extern "C" {
+
+typedef css::uno::XInterface * SAL_CALL ImplementationConstructorFn(
+ css::uno::XComponentContext *, uno_Sequence *);
+
+}
+
typedef cppu::WeakComponentImplHelper8<
css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
css::lang::XMultiComponentFactory, css::container::XSet,
@@ -55,13 +65,15 @@ public:
rtl::OUString const & theName, rtl::OUString const & theLoader,
rtl::OUString const & theUri,
rtl::OUString const & theEnvironment,
+ rtl::OUString const & theConstructor,
rtl::OUString const & thePrefix,
css::uno::Reference< css::uno::XComponentContext > const &
theAlienContext,
rtl::OUString const & theRdbFile):
name(theName), loader(theLoader), uri(theUri),
- environment(theEnvironment), prefix(thePrefix),
- alienContext(theAlienContext), rdbFile(theRdbFile)
+ environment(theEnvironment), constructor(theConstructor),
+ prefix(thePrefix), alienContext(theAlienContext),
+ rdbFile(theRdbFile)
{}
explicit ImplementationInfo(rtl::OUString const & theName):
@@ -71,6 +83,7 @@ public:
rtl::OUString const loader;
rtl::OUString const uri;
rtl::OUString const environment;
+ rtl::OUString const constructor;
rtl::OUString const prefix;
css::uno::Reference< css::uno::XComponentContext > const
alienContext;
@@ -83,15 +96,16 @@ public:
Implementation(
rtl::OUString const & name, rtl::OUString const & loader,
rtl::OUString const & uri, rtl::OUString const & environment,
+ rtl::OUString const & constructorName,
rtl::OUString const & prefix,
css::uno::Reference< css::uno::XComponentContext > const &
alienContext,
rtl::OUString const & rdbFile):
info(
new ImplementationInfo(
- name, loader, uri, environment, prefix, alienContext,
- rdbFile)),
- loaded(false)
+ name, loader, uri, environment, constructorName, prefix,
+ alienContext, rdbFile)),
+ constructor(0), loaded(false)
{}
Implementation(
@@ -102,11 +116,13 @@ public:
theFactory2,
css::uno::Reference< css::lang::XComponent > const &
theComponent):
- info(new ImplementationInfo(name)), factory1(theFactory1),
- factory2(theFactory2), component(theComponent), loaded(true)
+ info(new ImplementationInfo(name)), constructor(0),
+ factory1(theFactory1), factory2(theFactory2),
+ component(theComponent), loaded(true)
{}
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;
@@ -160,6 +176,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);
diff --git a/cppuhelper/source/shlib.cxx b/cppuhelper/source/shlib.cxx
index 81e02d3eb1ac..972357b3c05c 100644
--- a/cppuhelper/source/shlib.cxx
+++ b/cppuhelper/source/shlib.cxx
@@ -17,456 +17,333 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#include "sal/config.h"
+#include <sal/config.h>
#include <cassert>
+#include <cstdlib>
-#include "osl/module.hxx"
-#include "uno/environment.h"
-#include <uno/lbnames.h>
-#include "uno/mapping.hxx"
-#include "cppuhelper/factory.hxx"
-#include "cppuhelper/shlib.hxx"
-
-#include "com/sun/star/beans/XPropertySet.hpp"
+#include <com/sun/star/loader/CannotActivateFactoryException.hpp>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/shlib.hxx>
+#include <osl/module.hxx>
+#include <uno/environment.hxx>
+#include <uno/mapping.hxx>
#include <loadsharedlibcomponentfactory.hxx>
-#include <stdio.h>
-
-#ifdef ANDROID
+#if defined ANDROID
#include <osl/detail/android-bootstrap.h>
-#endif
-
-#ifdef IOS
+#elif defined IOS
#include <osl/detail/component-mapping.h>
#endif
-using namespace ::osl;
-using namespace ::com::sun::star;
-using namespace ::com::sun::star::uno;
-
-using rtl::OString;
-using rtl::OUString;
-
-namespace {
-
-uno::Environment getEnvironment(
- OUString const & name, OUString const & cImplName)
+css::uno::Environment cppuhelper::detail::getEnvironment(
+ rtl::OUString const & name, rtl::OUString const & implementation)
{
- OUString n(name);
- static const char * pUNO_ENV_LOG = ::getenv( "UNO_ENV_LOG" );
- if (pUNO_ENV_LOG && rtl_str_getLength(pUNO_ENV_LOG) )
- {
- OString implName(OUStringToOString(cImplName, RTL_TEXTENCODING_ASCII_US));
- OString aEnv( pUNO_ENV_LOG );
- sal_Int32 nIndex = 0;
- do
- {
- const OString aStr( aEnv.getToken( 0, ';', nIndex ) );
- if ( aStr.equals(implName) )
- {
- n += ::rtl::OUString(":log");
+ assert(!implementation.isEmpty());
+ rtl::OUString n(name);
+ static char const * log = std::getenv("UNO_ENV_LOG");
+ if (log != 0 && *log != 0) {
+ rtl::OString imps(log);
+ for (sal_Int32 i = 0; i != -1;) {
+ rtl::OString imp(imps.getToken(0, ';', i));
+ //TODO: this assumes UNO_ENV_LOG only contains ASCII characters:
+ if (implementation.equalsAsciiL(imp.getStr(), imp.getLength())) {
+ n += ":log";
break;
}
- } while( nIndex != -1 );
+ }
}
- return uno::Environment(n);
+ return css::uno::Environment(n);
}
-#ifndef DISABLE_DYNLOADING
-
-void getLibEnv(oslModule lib,
- uno::Environment * pEnv,
- uno::Environment const & cTargetEnv,
- OUString const & cImplName = OUString(),
- OUString const & rPrefix = OUString())
-{
- sal_Char const * pEnvTypeName = NULL;
+namespace {
- OUString aGetEnvNameExt = rPrefix + COMPONENT_GETENVEXT;
- component_getImplementationEnvironmentExtFunc pGetImplEnvExt =
- (component_getImplementationEnvironmentExtFunc)osl_getFunctionSymbol(lib, aGetEnvNameExt.pData);
+#if !defined DISABLE_DYNLOADING
- if (pGetImplEnvExt)
- {
- OString implName(OUStringToOString(cImplName, RTL_TEXTENCODING_ASCII_US));
- pGetImplEnvExt(&pEnvTypeName, (uno_Environment **)pEnv, implName.getStr(), cTargetEnv.get());
+css::uno::Environment getEnvironmentFromModule(
+ osl::Module const & module, css::uno::Environment const & target,
+ rtl::OUString const & implementation, rtl::OUString const & prefix)
+{
+ char const * name = 0;
+ css::uno::Environment env;
+ rtl::OUString fullPrefix(prefix);
+ if (!fullPrefix.isEmpty()) {
+ fullPrefix += "_";
}
- else
- {
- OUString aGetEnvName = rPrefix + COMPONENT_GETENV;
- component_getImplementationEnvironmentFunc pGetImplEnv =
- (component_getImplementationEnvironmentFunc)osl_getFunctionSymbol(
- lib, aGetEnvName.pData );
- if (pGetImplEnv)
- pGetImplEnv(&pEnvTypeName, (uno_Environment **)pEnv);
-
- else // this symbol used to be mandatory, but is no longer
- pEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+ component_getImplementationEnvironmentExtFunc fp1
+ = reinterpret_cast<component_getImplementationEnvironmentExtFunc>(
+ module.getFunctionSymbol(fullPrefix + COMPONENT_GETENVEXT));
+ if (fp1 != 0) {
+ (*fp1)(
+ &name, reinterpret_cast<uno_Environment **>(&env),
+ (rtl::OUStringToOString(implementation, RTL_TEXTENCODING_ASCII_US)
+ .getStr()),
+ target.get());
+ } else {
+ component_getImplementationEnvironmentFunc fp2
+ = reinterpret_cast<component_getImplementationEnvironmentFunc>(
+ module.getFunctionSymbol(fullPrefix + COMPONENT_GETENV));
+ if (fp2 != 0) {
+ (*fp2)(&name, reinterpret_cast<uno_Environment **>(&env));
+ } else {
+ name = CPPU_CURRENT_LANGUAGE_BINDING_NAME; //TODO: fail
+ }
}
-
- if (!pEnv->is() && pEnvTypeName)
- {
- *pEnv = getEnvironment(
- OUString::createFromAscii(pEnvTypeName), cImplName);
+ if (!env.is() && name != 0) {
+ env = cppuhelper::detail::getEnvironment(
+ rtl::OUString::createFromAscii(name), implementation);
}
+ return env;
}
#endif
-extern "C" void s_getFactory(va_list * pParam)
-{
- component_getFactoryFunc pSym = va_arg(*pParam, component_getFactoryFunc);
- OString const * pImplName = va_arg(*pParam, OString const *);
- void * pSMgr = va_arg(*pParam, void *);
- void * pKey = va_arg(*pParam, void *);
- void ** ppSSF = va_arg(*pParam, void **);
-
- *ppSSF = pSym(pImplName->getStr(), pSMgr, pKey);
+extern "C" void getFactory(va_list * args) {
+ component_getFactoryFunc fn = va_arg(*args, component_getFactoryFunc);
+ rtl::OString const * implementation = va_arg(*args, rtl::OString const *);
+ void * smgr = va_arg(*args, void *);
+ void * key = va_arg(*args, void *);
+ void ** factory = va_arg(*args, void **);
+ *factory = (*fn)(implementation->getStr(), smgr, key);
}
-}
-
-namespace cppu
-{
-
-/* For backwards compatibility */
-Reference< XInterface > SAL_CALL loadSharedLibComponentFactory(
- OUString const & uri, OUString const & rPath, OUString const & rImplName,
- Reference< lang::XMultiServiceFactory > const & xMgr,
- Reference< registry::XRegistryKey > const & xKey )
- SAL_THROW( (loader::CannotActivateFactoryException) )
+css::uno::Reference<css::uno::XInterface> invokeComponentFactory(
+ css::uno::Environment const & source, css::uno::Environment const & target,
+ component_getFactoryFunc function, rtl::OUString const & uri,
+ rtl::OUString const & implementation,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager)
{
- assert(rPath.isEmpty());
- assert(!xKey.is());
- (void) rPath;
- (void) xKey;
- return cppuhelper::detail::loadSharedLibComponentFactory(
- uri, "", "", rImplName, xMgr);
+ if (!(source.is() && target.is())) {
+ throw css::loader::CannotActivateFactoryException(
+ "cannot get environments",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ rtl::OString impl(
+ rtl::OUStringToOString(implementation, RTL_TEXTENCODING_ASCII_US));
+ if (source.get() == target.get()) {
+ return css::uno::Reference<css::uno::XInterface>(
+ static_cast<css::uno::XInterface *>(
+ (*function)(impl.getStr(), serviceManager.get(), 0)),
+ SAL_NO_ACQUIRE);
+ } else {
+ css::uno::Mapping mapTo(source, target);
+ css::uno::Mapping mapFrom(target, source);
+ if (!(mapTo.is() && mapFrom.is())) {
+ throw css::loader::CannotActivateFactoryException(
+ "cannot get mappings",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ void * smgr = mapTo.mapInterface(
+ serviceManager.get(),
+ cppu::UnoType<css::lang::XMultiServiceFactory>::get());
+ void * factory = 0;
+ target.invoke(getFactory, function, &impl, smgr, 0, &factory);
+ if (smgr != 0) {
+ (*target.get()->pExtEnv->releaseInterface)(
+ target.get()->pExtEnv, smgr);
+ }
+ if (factory == 0) {
+ throw css::loader::CannotActivateFactoryException(
+ ("calling factory function for \"" + implementation + "\" in <"
+ + uri + "> returned null"),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ css::uno::Reference<css::uno::XInterface> res;
+ mapFrom.mapInterface(
+ reinterpret_cast<void **>(&res), factory,
+ cppu::UnoType<css::uno::XInterface>::get());
+ (*target.get()->pExtEnv->releaseInterface)(
+ target.get()->pExtEnv, factory);
+ return res;
+ }
}
}
-namespace
+void cppuhelper::detail::loadSharedLibComponentFactory(
+ rtl::OUString const & uri, rtl::OUString const & environment,
+ rtl::OUString const & prefix, rtl::OUString const & implementation,
+ rtl::OUString const & constructor,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager,
+ ImplementationConstructorFn ** constructorFunction,
+ css::uno::Reference<css::uno::XInterface> * factory)
{
-
-Reference< XInterface > invokeComponentFactory(
- uno::Environment const & env,
- oslGenericFunction pGetter,
- OUString const & rModulePath,
- OUString const & rImplName,
- Reference< ::com::sun::star::lang::XMultiServiceFactory > const & xMgr,
- OUString &rExcMsg )
-{
- Reference< XInterface > xRet;
- uno::Environment currentEnv(Environment::getCurrent());
-
- OString aImplName(
- OUStringToOString( rImplName, RTL_TEXTENCODING_ASCII_US ) );
-
- if (env.is() && currentEnv.is())
- {
-#if OSL_DEBUG_LEVEL > 1
- {
- rtl::OString modPath(rtl::OUStringToOString(rModulePath, RTL_TEXTENCODING_ASCII_US));
- rtl::OString implName(rtl::OUStringToOString(rImplName, RTL_TEXTENCODING_ASCII_US));
- rtl::OString envDcp(rtl::OUStringToOString(env.getTypeName(), RTL_TEXTENCODING_ASCII_US));
-
- fprintf(stderr, "invokeComponentFactory envDcp:%s implName:%s modPath:%s\n", envDcp.getStr(), implName.getStr(), modPath.getStr());
+ assert(constructor.isEmpty() || !environment.isEmpty());
+ assert(
+ (constructorFunction == 0 && constructor.isEmpty())
+ || *constructorFunction == 0);
+ assert(factory != 0 && !factory->is());
+#if defined DISABLE_DYNLOADING
+ assert(!environment.isEmpty());
+ if (constructor.isEmpty()) {
+ css::uno::Environment curEnv(css::uno::Environment::getCurrent());
+ css::uno::Environment env(getEnvironment(environment, implementation));
+ if (!(curEnv.is() && env.is())) {
+ throw css::loader::CannotActivateFactoryException(
+ "cannot get environments",
+ css::uno::Reference<css::uno::XInterface>());
}
-#endif
- if (env.get() == currentEnv.get())
- {
- xRet.set(
- static_cast<css::uno::XInterface *>(
- (*reinterpret_cast<component_getFactoryFunc>(pGetter))(
- aImplName.getStr(), xMgr.get(), 0)),
- SAL_NO_ACQUIRE);
+ if (curEnv.get() != env.get()) {
+ std::abort();//TODO
}
- else
- {
- Mapping aCurrent2Env( currentEnv, env );
- Mapping aEnv2Current( env, currentEnv );
-
- if (aCurrent2Env.is() && aEnv2Current.is())
- {
- void * pSMgr = aCurrent2Env.mapInterface(
- xMgr.get(), ::getCppuType( &xMgr ) );
-
- void * pSSF = NULL;
-
- env.invoke(s_getFactory, pGetter, &aImplName, pSMgr, 0, &pSSF);
-
- if (pSMgr)
- {
- (*env.get()->pExtEnv->releaseInterface)(
- env.get()->pExtEnv, pSMgr );
- }
-
- if (pSSF)
- {
- aEnv2Current.mapInterface(
- reinterpret_cast< void ** >( &xRet ),
- pSSF, ::getCppuType( &xRet ) );
- (env.get()->pExtEnv->releaseInterface)(
- env.get()->pExtEnv, pSSF );
- }
- else
- {
- rExcMsg = rModulePath +
- ": cannot get factory of " +
- "demanded implementation: " +
- OStringToOUString(
- aImplName, RTL_TEXTENCODING_ASCII_US );
- }
+ rtl::OUString name(prefix == "direct" ? implementation : uri);
+ lib_to_factory_mapping const * map = lo_get_factory_map();
+ component_getFactoryFunc fp;
+ for (int i = 0; map[i].name != 0; ++i) {
+ if (name.equalsAscii(map[i].name)) {
+ fp = map[i].component_getFactory_function;
+ break;
}
- else
- {
- rExcMsg =
- "cannot get uno mappings: C++ <=> UNO!";
+ }
+ if (fp == 0) {
+ throw css::loader::CannotActivateFactoryException(
+ "unknown factory name \"" + name + "\"",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ *factory = invokeComponentFactory(
+ css::uno::Environment::getCurrent(),
+ getEnvironment(environment, implementation), fp, uri,
+ implementation, serviceManager);
+ } else {
+ lib_to_constructor_mapping const * map = lo_get_constructor_map();
+ for (int i = 0; map[i].name != 0; ++i) {
+ if (constructor.equalsAscii(map[i].name)) {
+ *constructorFunction
+ = reinterpret_cast<ImplementationConstructorFn *>(
+ map[i].constructor_function);
+ return;
}
}
- }
- else
- {
- rExcMsg = "cannot get uno environments!";
- }
-
- return xRet;
-}
-
-} // namespace
-
-namespace cppuhelper { namespace detail {
-
-css::uno::Reference<css::uno::XInterface> loadSharedLibComponentFactory(
- OUString const & uri, OUString const & rEnvironment,
- OUString const & rPrefix, OUString const & rImplName,
- css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr)
-{
-#ifndef DISABLE_DYNLOADING
- OUString moduleUri(uri);
- oslModule lib = osl_loadModule(
- moduleUri.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL );
- if (! lib)
- {
- OUString const msg("loading component library failed: " + moduleUri);
- SAL_WARN("cppuhelper", msg);
- throw loader::CannotActivateFactoryException(msg,
- Reference< XInterface >() );
+ throw css::loader::CannotActivateFactoryException(
+ "unknown constructor name \"" + constructor + "\"",
+ css::uno::Reference<css::uno::XInterface>());
}
#else
- oslModule lib;
- OUString moduleUri("MAIN");
- if (! osl_getModuleHandle( NULL, &lib))
- {
- throw loader::CannotActivateFactoryException(
- "osl_getModuleHandle of the executable: ",
- Reference< XInterface >() );
- }
-#endif
-
- Reference< XInterface > xRet;
-
- OUString aExcMsg;
-
- OUString aFullPrefix(rPrefix);
- if (!aFullPrefix.isEmpty()) {
- aFullPrefix += "_";
- }
- OUString aGetFactoryName = aFullPrefix + COMPONENT_GETFACTORY;
- if (rPrefix == "direct")
- aGetFactoryName = rImplName.replace('.', '_') + "_" + COMPONENT_GETFACTORY;
-
- oslGenericFunction pSym = NULL;
-
-#ifdef DISABLE_DYNLOADING
-
- OString sName;
- const lib_to_component_mapping *map = NULL;
- if (rPrefix == "direct")
- {
- sName = OUStringToOString(rImplName, RTL_TEXTENCODING_ASCII_US);
- map = lo_get_implementation_map();
- }
- else
- {
- sName = OUStringToOString(uri, RTL_TEXTENCODING_ASCII_US);
- map = lo_get_library_map();
- }
- for (int i = 0; pSym == NULL && map[i].name != NULL; ++i)
- {
- if ( sName == map[i].name )
- pSym = (oslGenericFunction) map[i].component_getFactory_function;
- }
- if ( pSym == NULL )
- {
- fprintf( stderr, "attempting to load unknown library %s\n", OUStringToOString( uri, RTL_TEXTENCODING_ASCII_US ).getStr() );
- assert( !"Attempt to load unknown library" );
+ osl::Module mod(uri, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL);
+ if (!mod.is()) {
+ throw css::loader::CannotActivateFactoryException(
+ "loading component library <" + uri + "> failed",
+ css::uno::Reference<css::uno::XInterface>());
}
-#else
-
- if ( pSym == NULL )
- pSym = osl_getFunctionSymbol( lib, aGetFactoryName.pData );
-#endif
-
- if (pSym != 0)
- {
- uno::Environment env;
- if (rEnvironment.isEmpty()) {
-#if defined DISABLE_DYNLOADING
- //TODO: assert(false); // this cannot happen
- env = getEnvironment(CPPU_CURRENT_LANGUAGE_BINDING_NAME, rImplName);
-
-#else
- getLibEnv(
- lib, &env, Environment::getCurrent(), rImplName, aFullPrefix);
-#endif
+ if (constructor.isEmpty()) {
+ rtl::OUString sym;
+ if (prefix == "direct") {
+ sym = implementation.replace('.', '_') + "_" + COMPONENT_GETFACTORY;
+ } else if (!prefix.isEmpty()) {
+ sym = prefix + "_" + COMPONENT_GETFACTORY;
} else {
- env = getEnvironment(rEnvironment, rImplName);
+ sym = COMPONENT_GETFACTORY;
}
-
- xRet = invokeComponentFactory(
- env, pSym, moduleUri, rImplName, xMgr, aExcMsg );
- }
- else
- {
- aExcMsg = moduleUri;
- aExcMsg += ": cannot get symbol: ";
- aExcMsg += aGetFactoryName;
+ oslGenericFunction fp = mod.getFunctionSymbol(sym);
+ if (fp == 0) {
+ throw css::loader::CannotActivateFactoryException(
+ ("no factory symbol \"" + sym + "\" in component library <"
+ + uri + ">"),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ css::uno::Environment curEnv(css::uno::Environment::getCurrent());
+ *factory = invokeComponentFactory(
+ curEnv,
+ (environment.isEmpty()
+ ? getEnvironmentFromModule(mod, curEnv, implementation, prefix)
+ : getEnvironment(environment, implementation)),
+ reinterpret_cast<component_getFactoryFunc>(fp), uri, implementation,
+ serviceManager);
+ } else {
+ oslGenericFunction fp = mod.getFunctionSymbol(constructor);
+ if (fp == 0) {
+ throw css::loader::CannotActivateFactoryException(
+ ("no constructor symbol \"" + constructor
+ + "\" in component library <" + uri + ">"),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ *constructorFunction = reinterpret_cast<ImplementationConstructorFn *>(
+ fp);
}
-
- if (! xRet.is())
- {
-#ifndef DISABLE_DYNLOADING
- osl_unloadModule( lib );
+ mod.release();
#endif
- SAL_WARN("cppuhelper", "### cannot activate factory: " << aExcMsg);
- throw loader::CannotActivateFactoryException(
- aExcMsg,
- Reference< XInterface >() );
- }
- return xRet;
}
-} }
+#if !defined DISABLE_DYNLOADING
-#ifndef DISABLE_DYNLOADING
-
-//==============================================================================
-extern "C" { static void s_writeInfo(va_list * pParam)
+css::uno::Reference<css::uno::XInterface> cppu::loadSharedLibComponentFactory(
+ rtl::OUString const & uri, rtl::OUString const & rPath,
+ rtl::OUString const & rImplName,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr,
+ css::uno::Reference<css::registry::XRegistryKey> const & xKey)
+ SAL_THROW((css::loader::CannotActivateFactoryException))
{
- component_writeInfoFunc pSym = va_arg(*pParam, component_writeInfoFunc);
- void * pSMgr = va_arg(*pParam, void *);
- void * pKey = va_arg(*pParam, void *);
- sal_Bool * pbRet = va_arg(*pParam, sal_Bool *);
+ assert(rPath.isEmpty()); (void) rPath;
+ assert(!xKey.is()); (void) xKey;
+ css::uno::Reference<css::uno::XInterface> fac;
+ cppuhelper::detail::loadSharedLibComponentFactory(
+ uri, "", "", rImplName, "", xMgr, 0, &fac);
+ return fac;
+}
- *pbRet = pSym(pSMgr, pKey);
+namespace {
-}}
+extern "C" void writeInfo(va_list * args) {
+ component_writeInfoFunc fn = va_arg(*args, component_writeInfoFunc);
+ void * smgr = va_arg(*args, void *);
+ void * key = va_arg(*args, void *);
+ sal_Bool * ok = va_arg(*args, sal_Bool *);
+ *ok = (*fn)(smgr, key);
+}
-namespace cppu {
+}
-void SAL_CALL writeSharedLibComponentInfo(
- OUString const & uri, OUString const & rPath,
- Reference< lang::XMultiServiceFactory > const & xMgr,
- Reference< registry::XRegistryKey > const & xKey )
- SAL_THROW( (registry::CannotRegisterImplementationException) )
+void cppu::writeSharedLibComponentInfo(
+ rtl::OUString const & uri, rtl::OUString const & rPath,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr,
+ css::uno::Reference<css::registry::XRegistryKey> const & xKey)
+ SAL_THROW((css::registry::CannotRegisterImplementationException))
{
- (void) rPath;
- assert(rPath.isEmpty());
- oslModule lib = osl_loadModule(
- uri.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL );
- if (! lib)
- {
- OUString const msg("loading component library failed: " + uri);
- SAL_WARN("cppuhelper", msg);
- throw registry::CannotRegisterImplementationException(msg,
- Reference< XInterface >() );
+ assert(rPath.isEmpty()); (void) rPath;
+ osl::Module mod(uri, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL);
+ if (!mod.is()) {
+ throw css::registry::CannotRegisterImplementationException(
+ "loading component library <" + uri + "> failed",
+ css::uno::Reference<css::uno::XInterface>());
}
-
- sal_Bool bRet = sal_False;
-
- uno::Environment currentEnv(Environment::getCurrent());
- uno::Environment env;
-
- OUString aExcMsg;
-
- getLibEnv(lib, &env, currentEnv);
-
- OUString aWriteInfoName = COMPONENT_WRITEINFO;
- oslGenericFunction pSym = osl_getFunctionSymbol( lib, aWriteInfoName.pData );
- if (pSym != 0)
- {
- if (env.is() && currentEnv.is())
- {
- Mapping aCurrent2Env( currentEnv, env );
- if (aCurrent2Env.is())
- {
- void * pSMgr = aCurrent2Env.mapInterface(
- xMgr.get(), ::getCppuType( &xMgr ) );
- void * pKey = aCurrent2Env.mapInterface(
- xKey.get(), ::getCppuType( &xKey ) );
- if (pKey)
- {
- env.invoke(s_writeInfo, pSym, pSMgr, pKey, &bRet);
-
-
- (*env.get()->pExtEnv->releaseInterface)(
- env.get()->pExtEnv, pKey );
- if (! bRet)
- {
- aExcMsg = uri;
- aExcMsg += ": component_writeInfo() "
- "returned false!";
- }
- }
- else
- {
- // key is mandatory
- aExcMsg = uri;
- aExcMsg += ": registry is mandatory to invoke"
- " component_writeInfo()!";
- }
-
- if (pSMgr)
- {
- (*env.get()->pExtEnv->releaseInterface)(
- env.get()->pExtEnv, pSMgr );
- }
- }
- else
- {
- aExcMsg = "cannot get uno mapping: C++ <=> UNO!";
- }
- }
- else
- {
- aExcMsg = "cannot get uno environments!";
- }
+ oslGenericFunction fp = mod.getFunctionSymbol(COMPONENT_WRITEINFO);
+ if (fp == 0) {
+ throw css::registry::CannotRegisterImplementationException(
+ ("no symbol \"" COMPONENT_WRITEINFO "\" in component library <"
+ + uri + ">"),
+ css::uno::Reference<css::uno::XInterface>());
}
- else
- {
- aExcMsg = uri;
- aExcMsg += ": cannot get symbol: ";
- aExcMsg += aWriteInfoName;
+ css::uno::Environment curEnv(css::uno::Environment::getCurrent());
+ css::uno::Environment env(getEnvironmentFromModule(mod, curEnv, "", ""));
+ if (!(curEnv.is() && env.is())) {
+ throw css::registry::CannotRegisterImplementationException(
+ "cannot get environments",
+ css::uno::Reference<css::uno::XInterface>());
}
-
-//!
-//! OK: please look at #88219#
-//!
-//! ::osl_unloadModule( lib);
- if (! bRet)
- {
- SAL_WARN("cppuhelper", "### cannot write component info: " << aExcMsg);
- throw registry::CannotRegisterImplementationException(
- aExcMsg, Reference< XInterface >() );
+ css::uno::Mapping map(curEnv, env);
+ if (!map.is()) {
+ throw css::registry::CannotRegisterImplementationException(
+ "cannot get mapping", css::uno::Reference<css::uno::XInterface>());
+ }
+ void * smgr = map.mapInterface(
+ xMgr.get(), cppu::UnoType<css::lang::XMultiServiceFactory>::get());
+ void * key = map.mapInterface(
+ xKey.get(), cppu::UnoType<css::registry::XRegistryKey>::get());
+ sal_Bool ok;
+ env.invoke(writeInfo, fp, smgr, key, &ok);
+ (*env.get()->pExtEnv->releaseInterface)(env.get()->pExtEnv, key);
+ if (smgr != 0) {
+ (*env.get()->pExtEnv->releaseInterface)(env.get()->pExtEnv, smgr);
+ }
+ if (!ok) {
+ throw css::registry::CannotRegisterImplementationException(
+ ("calling \"" COMPONENT_WRITEINFO "\" in component library <" + uri
+ + "> returned false"),
+ css::uno::Reference<css::uno::XInterface>());
}
}
-}
-
-#endif // DISABLE_DYNLOADING
+#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */