LibreOffice Module cppuhelper (master) 1
shlib.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <cassert>
23#include <cstdlib>
24#include <string_view>
25
26#ifdef IOS
27#include <premac.h>
28#include <Foundation/Foundation.h>
29#include <postmac.h>
30#endif
31
32#include <com/sun/star/loader/CannotActivateFactoryException.hpp>
33#include <com/sun/star/registry/CannotRegisterImplementationException.hpp>
34#include <com/sun/star/registry/XRegistryKey.hpp>
36#include <cppuhelper/shlib.hxx>
37#include <o3tl/string_view.hxx>
38#include <osl/module.hxx>
39#include <sal/log.hxx>
40#include <uno/environment.hxx>
41#include <uno/mapping.hxx>
42
44
45#if defined DISABLE_DYNLOADING
46#include <osl/detail/component-mapping.h>
47#endif
48
50 OUString const & name, std::u16string_view implementation)
51{
52 OUString n(name);
53 if (!implementation.empty()) {
54 static char const * log = std::getenv("UNO_ENV_LOG");
55 if (log != nullptr && *log != 0) {
56 OString imps(log);
57 for (sal_Int32 i = 0; i != -1;) {
58 std::string_view imp(o3tl::getToken(imps, 0, ';', i));
59 //TODO: this assumes UNO_ENV_LOG only contains ASCII characters:
60 if (o3tl::equalsAscii(implementation, imp))
61 {
62 n += ":log";
63 break;
64 }
65 }
66 }
67 }
68 return css::uno::Environment(n);
69}
70
71namespace {
72
73#if !defined DISABLE_DYNLOADING
74
75css::uno::Environment getEnvironmentFromModule(
76 osl::Module const & module, css::uno::Environment const & target,
77 std::u16string_view implementation, OUString const & prefix)
78{
79 char const * name = nullptr;
80 css::uno::Environment env;
81 OUString fullPrefix(prefix);
82 if (!fullPrefix.isEmpty()) {
83 fullPrefix += "_";
84 }
87 module.getFunctionSymbol(fullPrefix + COMPONENT_GETENVEXT));
88 if (fp1 != nullptr) {
89 (*fp1)(
90 &name, reinterpret_cast<uno_Environment **>(&env),
91 (OUStringToOString(implementation, RTL_TEXTENCODING_ASCII_US)
92 .getStr()),
93 target.get());
94 } else {
97 module.getFunctionSymbol(fullPrefix + COMPONENT_GETENV));
98 if (fp2 != nullptr) {
99 (*fp2)(&name, reinterpret_cast<uno_Environment **>(&env));
100 } else {
101 name = CPPU_CURRENT_LANGUAGE_BINDING_NAME; //TODO: fail
102 }
103 }
104 if (!env.is() && name != nullptr) {
106 OUString::createFromAscii(name), implementation);
107 }
108 return env;
109}
110
111#endif
112
113extern "C" void getFactory(va_list * args) {
115 OString const * implementation = va_arg(*args, OString const *);
116 void * smgr = va_arg(*args, void *);
117 void ** factory = va_arg(*args, void **);
118 *factory = (*fn)(implementation->getStr(), smgr, nullptr);
119}
120
121css::uno::Reference<css::uno::XInterface> invokeComponentFactory(
122 css::uno::Environment const & source, css::uno::Environment const & target,
123 component_getFactoryFunc function, std::u16string_view uri,
124 std::u16string_view implementation,
125 css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager)
126{
127 if (!(source.is() && target.is())) {
128 throw css::loader::CannotActivateFactoryException(
129 "cannot get environments",
130 css::uno::Reference<css::uno::XInterface>());
131 }
132 OString impl(
133 OUStringToOString(implementation, RTL_TEXTENCODING_ASCII_US));
134 if (source.get() == target.get()) {
135 return css::uno::Reference<css::uno::XInterface>(
136 static_cast<css::uno::XInterface *>(
137 (*function)(impl.getStr(), serviceManager.get(), nullptr)),
138 SAL_NO_ACQUIRE);
139 }
140 css::uno::Mapping mapTo(source, target);
141 css::uno::Mapping mapFrom(target, source);
142 if (!(mapTo.is() && mapFrom.is())) {
143 throw css::loader::CannotActivateFactoryException(
144 "cannot get mappings",
145 css::uno::Reference<css::uno::XInterface>());
146 }
147 void * smgr = mapTo.mapInterface(
148 serviceManager.get(),
150 void * factory = nullptr;
151 target.invoke(getFactory, function, &impl, smgr, &factory);
152 if (smgr != nullptr) {
153 (*target.get()->pExtEnv->releaseInterface)(
154 target.get()->pExtEnv, smgr);
155 }
156 if (factory == nullptr) {
157 throw css::loader::CannotActivateFactoryException(
158 (OUString::Concat("calling factory function for \"") + implementation + "\" in <"
159 + uri + "> returned null"),
160 css::uno::Reference<css::uno::XInterface>());
161 }
162 css::uno::Reference<css::uno::XInterface> res;
163 mapFrom.mapInterface(
164 reinterpret_cast<void **>(&res), factory,
166 (*target.get()->pExtEnv->releaseInterface)(
167 target.get()->pExtEnv, factory);
168 return res;
169}
170
171#if !defined DISABLE_DYNLOADING
172
173extern "C" void getInstance(va_list * args) {
175 void * ctxt = va_arg(*args, void *);
176 assert(ctxt);
177 void * argseq = va_arg(*args, void *);
178 assert(argseq);
179 void ** instance = va_arg(*args, void **);
180 assert(instance);
181 assert(*instance == nullptr);
182 *instance = (*fn)(static_cast<css::uno::XComponentContext*>(ctxt),
183 *static_cast<css::uno::Sequence<css::uno::Any> const*>(argseq));
184}
185
186cppuhelper::WrapperConstructorFn mapConstructorFn(
187 css::uno::Environment const & source, css::uno::Environment const & target,
188 cppuhelper::ImplementationConstructorFn *const constructorFunction)
189{
190 if (!(source.is() && target.is())) {
191 throw css::loader::CannotActivateFactoryException(
192 "cannot get environments",
193 css::uno::Reference<css::uno::XInterface>());
194 }
195 if (source.get() == target.get()) {
196 return cppuhelper::WrapperConstructorFn(constructorFunction);
197 }
198 // note: it should be valid to capture these mappings because they are
199 // ref-counted, and the returned closure will always be invoked in the
200 // "source" environment
201 css::uno::Mapping mapTo(source, target);
202 css::uno::Mapping mapFrom(target, source);
203 if (!(mapTo.is() && mapFrom.is())) {
204 throw css::loader::CannotActivateFactoryException(
205 "cannot get mappings",
206 css::uno::Reference<css::uno::XInterface>());
207 }
208 return [mapFrom, mapTo, target, constructorFunction]
209 (css::uno::XComponentContext *const context, css::uno::Sequence<css::uno::Any> const& args)
210 {
211 void *const ctxt = mapTo.mapInterface(
212 context,
214 if (args.hasElements()) {
215 std::abort(); // TODO map args
216 }
217 void * instance = nullptr;
218 target.invoke(getInstance, constructorFunction, ctxt, &args, &instance);
219 if (ctxt != nullptr) {
220 (*target.get()->pExtEnv->releaseInterface)(
221 target.get()->pExtEnv, ctxt);
222 }
223 css::uno::XInterface * res = nullptr;
224 if (instance == nullptr) {
225 return res;
226 }
227 mapFrom.mapInterface(
228 reinterpret_cast<void **>(&res), instance,
230 (*target.get()->pExtEnv->releaseInterface)(
231 target.get()->pExtEnv, instance);
232 return res;
233 };
234}
235
236#endif
237
238}
239
241 OUString const & uri, OUString const & environment,
242 OUString const & prefix, OUString const & implementation,
243 OUString const & constructor,
244 css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager,
245 WrapperConstructorFn * constructorFunction,
246 css::uno::Reference<css::uno::XInterface> * factory)
247{
248 assert(constructor.isEmpty() || !environment.isEmpty());
249 assert(
250 (constructorFunction == nullptr && constructor.isEmpty())
251 || !*constructorFunction);
252 assert(factory != nullptr && !factory->is());
253#if defined DISABLE_DYNLOADING
254 assert(!environment.isEmpty());
255 if (constructor.isEmpty()) {
256 css::uno::Environment curEnv(css::uno::Environment::getCurrent());
257 css::uno::Environment env(getEnvironment(environment, implementation));
258 if (!(curEnv.is() && env.is())) {
259 throw css::loader::CannotActivateFactoryException(
260 "cannot get environments",
261 css::uno::Reference<css::uno::XInterface>());
262 }
263 if (curEnv.get() != env.get()) {
264 std::abort();//TODO
265 }
266 SAL_INFO("cppuhelper.shlib", "prefix=" << prefix << " implementation=" << implementation << " uri=" << uri);
267 lib_to_factory_mapping const * map = lo_get_factory_map();
269 for (int i = 0; map[i].name != 0; ++i) {
270 if (uri.equalsAscii(map[i].name)) {
271 fp = map[i].component_getFactory_function;
272 break;
273 }
274 }
275 if (fp == 0) {
276 SAL_WARN("cppuhelper", "unknown factory name \"" << uri << "\"");
277#ifdef IOS
278 NSLog(@"Unknown factory %s", uri.toUtf8().getStr());
279#endif
280 throw css::loader::CannotActivateFactoryException(
281 "unknown factory name \"" + uri + "\"",
282 css::uno::Reference<css::uno::XInterface>());
283 }
284 *factory = invokeComponentFactory(
285 css::uno::Environment::getCurrent(),
286 getEnvironment(environment, implementation), fp, uri,
287 implementation, serviceManager);
288 } else {
289 SAL_INFO("cppuhelper.shlib", "constructor=" << constructor);
290 lib_to_constructor_mapping const * map = lo_get_constructor_map();
291 for (int i = 0; map[i].name != 0; ++i) {
292 if (constructor.equalsAscii(map[i].name)) {
293 *constructorFunction
294 = reinterpret_cast<ImplementationConstructorFn *>(
295 map[i].constructor_function);
296 return;
297 }
298 }
299 SAL_WARN("cppuhelper", "unknown constructor name \"" << constructor << "\"");
300#ifdef IOS
301 NSLog(@"Unknown constructor %s", constructor.toUtf8().getStr());
302#endif
303 throw css::loader::CannotActivateFactoryException(
304 "unknown constructor name \"" + constructor + "\"",
305 css::uno::Reference<css::uno::XInterface>());
306 }
307#else
308 osl::Module mod(uri, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL);
309 if (!mod.is()) {
310 throw css::loader::CannotActivateFactoryException(
311 "loading component library <" + uri + "> failed",
312 css::uno::Reference<css::uno::XInterface>());
313 }
314 if (constructor.isEmpty()) {
315 OUString sym;
316 SAL_INFO("cppuhelper.shlib", "prefix=" << prefix << " implementation=" << implementation << " uri=" << uri);
317 if (!prefix.isEmpty()) {
318 sym = prefix + "_" COMPONENT_GETFACTORY;
319 } else {
321 }
322 oslGenericFunction fp = mod.getFunctionSymbol(sym);
323 if (fp == nullptr) {
324 throw css::loader::CannotActivateFactoryException(
325 ("no factory symbol \"" + sym + "\" in component library <"
326 + uri + ">"),
327 css::uno::Reference<css::uno::XInterface>());
328 }
329 css::uno::Environment curEnv(css::uno::Environment::getCurrent());
330 *factory = invokeComponentFactory(
331 curEnv,
332 (environment.isEmpty()
333 ? getEnvironmentFromModule(mod, curEnv, implementation, prefix)
334 : getEnvironment(environment, implementation)),
335 reinterpret_cast<component_getFactoryFunc>(fp), uri, implementation,
336 serviceManager);
337 } else {
338 SAL_INFO("cppuhelper.shlib", "constructor=" << constructor);
339 oslGenericFunction fp = mod.getFunctionSymbol(constructor);
340 if (fp == nullptr) {
341 throw css::loader::CannotActivateFactoryException(
342 ("no constructor symbol \"" + constructor
343 + "\" in component library <" + uri + ">"),
344 css::uno::Reference<css::uno::XInterface>());
345 }
346 css::uno::Environment curEnv(css::uno::Environment::getCurrent());
347 *constructorFunction = mapConstructorFn(
348 curEnv,
349 (environment.isEmpty()
350 ? getEnvironmentFromModule(mod, curEnv, implementation, prefix)
351 : getEnvironment(environment, implementation)),
352 reinterpret_cast<ImplementationConstructorFn *>(fp));
353 }
354 mod.release();
355#endif
356}
357
358css::uno::Reference<css::uno::XInterface> cppu::loadSharedLibComponentFactory(
359 OUString const & uri, OUString const & rPath,
360 OUString const & rImplName,
361 css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr,
362 css::uno::Reference<css::registry::XRegistryKey> const & xKey)
363{
364 assert(rPath.isEmpty()); (void) rPath;
365 assert(!xKey.is()); (void) xKey;
366 css::uno::Reference<css::uno::XInterface> fac;
368 uri, "", "", rImplName, "", xMgr, nullptr, &fac);
369 return fac;
370}
371
372#if !defined DISABLE_DYNLOADING
373
374namespace {
375
376extern "C" void writeInfo(va_list * args) {
378 void * smgr = va_arg(*args, void *);
379 void * key = va_arg(*args, void *);
380 sal_Bool * ok = va_arg(*args, sal_Bool *);
381 *ok = (*fn)(smgr, key);
382}
383
384}
385
387 OUString const & uri, OUString const & rPath,
388 css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr,
389 css::uno::Reference<css::registry::XRegistryKey> const & xKey)
390{
391 assert(rPath.isEmpty()); (void) rPath;
392 osl::Module mod(uri, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL);
393 if (!mod.is()) {
394 throw css::registry::CannotRegisterImplementationException(
395 "loading component library <" + uri + "> failed",
396 css::uno::Reference<css::uno::XInterface>());
397 }
398 oslGenericFunction fp = mod.getFunctionSymbol(COMPONENT_WRITEINFO);
399 if (fp == nullptr) {
400 throw css::registry::CannotRegisterImplementationException(
401 ("no symbol \"" COMPONENT_WRITEINFO "\" in component library <"
402 + uri + ">"),
403 css::uno::Reference<css::uno::XInterface>());
404 }
405 css::uno::Environment curEnv(css::uno::Environment::getCurrent());
406 css::uno::Environment env(getEnvironmentFromModule(mod, curEnv, u"", ""));
407 if (!(curEnv.is() && env.is())) {
408 throw css::registry::CannotRegisterImplementationException(
409 "cannot get environments",
410 css::uno::Reference<css::uno::XInterface>());
411 }
412 css::uno::Mapping map(curEnv, env);
413 if (!map.is()) {
414 throw css::registry::CannotRegisterImplementationException(
415 "cannot get mapping", css::uno::Reference<css::uno::XInterface>());
416 }
417 void * smgr = map.mapInterface(
419 void * key = map.mapInterface(
421 sal_Bool ok;
422 env.invoke(writeInfo, fp, smgr, key, &ok);
423 (*env.get()->pExtEnv->releaseInterface)(env.get()->pExtEnv, key);
424 if (smgr != nullptr) {
425 (*env.get()->pExtEnv->releaseInterface)(env.get()->pExtEnv, smgr);
426 }
427 if (!ok) {
428 throw css::registry::CannotRegisterImplementationException(
429 ("calling \"" COMPONENT_WRITEINFO "\" in component library <" + uri
430 + "> returned false"),
431 css::uno::Reference<css::uno::XInterface>());
432 }
433}
434
435#endif
436
437/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
int fac(int n)
css::uno::Type const & get()
void(SAL_CALL * component_getImplementationEnvironmentExtFunc)(char const **ppEnvTypeName, uno_Environment **ppEnv, char const *pImplName, uno_Environment *pTargetEnv)
Function pointer declaration.
Definition: factory.hxx:73
void(SAL_CALL * component_getImplementationEnvironmentFunc)(const char **ppEnvTypeName, uno_Environment **ppEnv)
Function pointer declaration.
Definition: factory.hxx:60
struct _uno_Environment uno_Environment
Definition: factory.hxx:49
#define COMPONENT_WRITEINFO
Definition: factory.hxx:46
sal_Bool(SAL_CALL * component_writeInfoFunc)(void *pServiceManager, void *pRegistryKey)
Function pointer declaration.
Definition: factory.hxx:102
#define COMPONENT_GETFACTORY
Definition: factory.hxx:47
#define COMPONENT_GETENV
Definition: factory.hxx:44
void *(SAL_CALL * component_getFactoryFunc)(const char *pImplName, void *pServiceManager, void *pRegistryKey)
Function pointer declaration.
Definition: factory.hxx:120
#define COMPONENT_GETENVEXT
Definition: factory.hxx:45
const char * name
sal_Int64 n
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
const css::uno::Reference< css::xml::crypto::XSecurityEnvironment > & env
SAL_DLLPUBLIC_EXPORT css::uno::Reference< css::uno::XInterface > SAL_CALL loadSharedLibComponentFactory(OUString const &, OUString const &, OUString const &, css::uno::Reference< css::lang::XMultiServiceFactory > const &, css::uno::Reference< css::registry::XRegistryKey > const &, OUString const &)
Definition: compat.cxx:104
CPPUHELPER_DLLPUBLIC void SAL_CALL 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)
Invokes component_writeInfo() function of specified component library.
css::uno::Environment getEnvironment(OUString const &name, std::u16string_view implementation)
Definition: shlib.cxx:49
void loadSharedLibComponentFactory(OUString const &uri, OUString const &environment, OUString const &prefix, OUString const &implementation, OUString const &constructor, css::uno::Reference< css::lang::XMultiServiceFactory > const &serviceManager, WrapperConstructorFn *constructorFunction, css::uno::Reference< css::uno::XInterface > *factory)
Definition: shlib.cxx:240
css::uno::XInterface * ImplementationConstructorFn(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
std::function< css::uno::XInterface *(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)> WrapperConstructorFn
int i
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
bool equalsAscii(std::u16string_view s1, std::string_view s2)
module
args
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
log
std::map< OUString, rtl::Reference< Entity > > map
unsigned char sal_Bool