1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
25 #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
26 #include <cppuhelper/factory.hxx>
27 #include <cppuhelper/shlib.hxx>
28 #include <osl/module.hxx>
29 #include <uno/environment.hxx>
30 #include <uno/mapping.hxx>
32 #include <loadsharedlibcomponentfactory.hxx>
34 #if defined DISABLE_DYNLOADING
35 #include <osl/detail/component-mapping.h>
38 css::uno::Environment
cppuhelper::detail::getEnvironment(
39 rtl::OUString
const & name
, rtl::OUString
const & implementation
)
41 assert(!implementation
.isEmpty());
42 rtl::OUString
n(name
);
43 static char const * log
= std::getenv("UNO_ENV_LOG");
44 if (log
!= 0 && *log
!= 0) {
45 rtl::OString
imps(log
);
46 for (sal_Int32 i
= 0; i
!= -1;) {
47 rtl::OString
imp(imps
.getToken(0, ';', i
));
48 //TODO: this assumes UNO_ENV_LOG only contains ASCII characters:
49 if (implementation
.equalsAsciiL(imp
.getStr(), imp
.getLength())) {
55 return css::uno::Environment(n
);
60 #if !defined DISABLE_DYNLOADING
62 css::uno::Environment
getEnvironmentFromModule(
63 osl::Module
const & module
, css::uno::Environment
const & target
,
64 rtl::OUString
const & implementation
, rtl::OUString
const & prefix
)
66 char const * name
= 0;
67 css::uno::Environment env
;
68 rtl::OUString
fullPrefix(prefix
);
69 if (!fullPrefix
.isEmpty()) {
72 component_getImplementationEnvironmentExtFunc fp1
73 = reinterpret_cast<component_getImplementationEnvironmentExtFunc
>(
74 module
.getFunctionSymbol(fullPrefix
+ COMPONENT_GETENVEXT
));
77 &name
, reinterpret_cast<uno_Environment
**>(&env
),
78 (rtl::OUStringToOString(implementation
, RTL_TEXTENCODING_ASCII_US
)
82 component_getImplementationEnvironmentFunc fp2
83 = reinterpret_cast<component_getImplementationEnvironmentFunc
>(
84 module
.getFunctionSymbol(fullPrefix
+ COMPONENT_GETENV
));
86 (*fp2
)(&name
, reinterpret_cast<uno_Environment
**>(&env
));
88 name
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
; //TODO: fail
91 if (!env
.is() && name
!= 0) {
92 env
= cppuhelper::detail::getEnvironment(
93 rtl::OUString::createFromAscii(name
), implementation
);
100 extern "C" void getFactory(va_list * args
) {
101 component_getFactoryFunc fn
= va_arg(*args
, component_getFactoryFunc
);
102 rtl::OString
const * implementation
= va_arg(*args
, rtl::OString
const *);
103 void * smgr
= va_arg(*args
, void *);
104 void * key
= va_arg(*args
, void *);
105 void ** factory
= va_arg(*args
, void **);
106 *factory
= (*fn
)(implementation
->getStr(), smgr
, key
);
109 css::uno::Reference
<css::uno::XInterface
> invokeComponentFactory(
110 css::uno::Environment
const & source
, css::uno::Environment
const & target
,
111 component_getFactoryFunc function
, rtl::OUString
const & uri
,
112 rtl::OUString
const & implementation
,
113 css::uno::Reference
<css::lang::XMultiServiceFactory
> const & serviceManager
)
115 if (!(source
.is() && target
.is())) {
116 throw css::loader::CannotActivateFactoryException(
117 "cannot get environments",
118 css::uno::Reference
<css::uno::XInterface
>());
121 rtl::OUStringToOString(implementation
, RTL_TEXTENCODING_ASCII_US
));
122 if (source
.get() == target
.get()) {
123 return css::uno::Reference
<css::uno::XInterface
>(
124 static_cast<css::uno::XInterface
*>(
125 (*function
)(impl
.getStr(), serviceManager
.get(), 0)),
128 css::uno::Mapping
mapTo(source
, target
);
129 css::uno::Mapping
mapFrom(target
, source
);
130 if (!(mapTo
.is() && mapFrom
.is())) {
131 throw css::loader::CannotActivateFactoryException(
132 "cannot get mappings",
133 css::uno::Reference
<css::uno::XInterface
>());
135 void * smgr
= mapTo
.mapInterface(
136 serviceManager
.get(),
137 cppu::UnoType
<css::lang::XMultiServiceFactory
>::get());
139 target
.invoke(getFactory
, function
, &impl
, smgr
, 0, &factory
);
141 (*target
.get()->pExtEnv
->releaseInterface
)(
142 target
.get()->pExtEnv
, smgr
);
145 throw css::loader::CannotActivateFactoryException(
146 ("calling factory function for \"" + implementation
+ "\" in <"
147 + uri
+ "> returned null"),
148 css::uno::Reference
<css::uno::XInterface
>());
150 css::uno::Reference
<css::uno::XInterface
> res
;
151 mapFrom
.mapInterface(
152 reinterpret_cast<void **>(&res
), factory
,
153 cppu::UnoType
<css::uno::XInterface
>::get());
154 (*target
.get()->pExtEnv
->releaseInterface
)(
155 target
.get()->pExtEnv
, factory
);
162 void cppuhelper::detail::loadSharedLibComponentFactory(
163 rtl::OUString
const & uri
, rtl::OUString
const & environment
,
164 rtl::OUString
const & prefix
, rtl::OUString
const & implementation
,
165 rtl::OUString
const & constructor
,
166 css::uno::Reference
<css::lang::XMultiServiceFactory
> const & serviceManager
,
167 ImplementationConstructorFn
** constructorFunction
,
168 css::uno::Reference
<css::uno::XInterface
> * factory
)
170 assert(constructor
.isEmpty() || !environment
.isEmpty());
172 (constructorFunction
== 0 && constructor
.isEmpty())
173 || *constructorFunction
== 0);
174 assert(factory
!= 0 && !factory
->is());
175 #if defined DISABLE_DYNLOADING
176 assert(!environment
.isEmpty());
177 if (constructor
.isEmpty()) {
178 css::uno::Environment
curEnv(css::uno::Environment::getCurrent());
179 css::uno::Environment
env(getEnvironment(environment
, implementation
));
180 if (!(curEnv
.is() && env
.is())) {
181 throw css::loader::CannotActivateFactoryException(
182 "cannot get environments",
183 css::uno::Reference
<css::uno::XInterface
>());
185 if (curEnv
.get() != env
.get()) {
188 rtl::OUString
name(prefix
== "direct" ? implementation
: uri
);
189 SAL_INFO("cppuhelper.shlib", "prefix=" << prefix
<< " implementation=" << implementation
<< " uri=" << uri
);
190 lib_to_factory_mapping
const * map
= lo_get_factory_map();
191 component_getFactoryFunc fp
= 0;
192 for (int i
= 0; map
[i
].name
!= 0; ++i
) {
193 if (name
.equalsAscii(map
[i
].name
)) {
194 fp
= map
[i
].component_getFactory_function
;
199 SAL_WARN("cppuhelper", "unknown factory name \"" << name
<< "\"");
200 #if defined IOS && !defined SAL_LOG_WARN
201 // If the above SAL_WARN expanded to nothing, print to stderr...
202 fprintf(stderr
, "Unknown factory name %s\n", OUStringToOString(name
, RTL_TEXTENCODING_UTF8
).getStr());
204 throw css::loader::CannotActivateFactoryException(
205 "unknown factory name \"" + name
+ "\"",
206 css::uno::Reference
<css::uno::XInterface
>());
208 *factory
= invokeComponentFactory(
209 css::uno::Environment::getCurrent(),
210 getEnvironment(environment
, implementation
), fp
, uri
,
211 implementation
, serviceManager
);
213 SAL_INFO("cppuhelper.shlib", "constructor=" << constructor
);
214 lib_to_constructor_mapping
const * map
= lo_get_constructor_map();
215 for (int i
= 0; map
[i
].name
!= 0; ++i
) {
216 if (constructor
.equalsAscii(map
[i
].name
)) {
218 = reinterpret_cast<ImplementationConstructorFn
*>(
219 map
[i
].constructor_function
);
223 SAL_WARN("cppuhelper", "unknown constructor name \"" << constructor
<< "\"");
224 #if defined IOS && !defined SAL_LOG_WARN
225 // If the above SAL_WARN expanded to nothing, print to stderr...
226 fprintf(stderr
, "Unknown constructor name %s\n", OUStringToOString(constructor
, RTL_TEXTENCODING_UTF8
).getStr());
228 throw css::loader::CannotActivateFactoryException(
229 "unknown constructor name \"" + constructor
+ "\"",
230 css::uno::Reference
<css::uno::XInterface
>());
233 osl::Module
mod(uri
, SAL_LOADMODULE_LAZY
| SAL_LOADMODULE_GLOBAL
);
235 throw css::loader::CannotActivateFactoryException(
236 "loading component library <" + uri
+ "> failed",
237 css::uno::Reference
<css::uno::XInterface
>());
239 if (constructor
.isEmpty()) {
241 if (prefix
== "direct") {
242 sym
= implementation
.replace('.', '_') + "_" + COMPONENT_GETFACTORY
;
243 } else if (!prefix
.isEmpty()) {
244 sym
= prefix
+ "_" + COMPONENT_GETFACTORY
;
246 sym
= COMPONENT_GETFACTORY
;
248 oslGenericFunction fp
= mod
.getFunctionSymbol(sym
);
250 throw css::loader::CannotActivateFactoryException(
251 ("no factory symbol \"" + sym
+ "\" in component library <"
253 css::uno::Reference
<css::uno::XInterface
>());
255 css::uno::Environment
curEnv(css::uno::Environment::getCurrent());
256 *factory
= invokeComponentFactory(
258 (environment
.isEmpty()
259 ? getEnvironmentFromModule(mod
, curEnv
, implementation
, prefix
)
260 : getEnvironment(environment
, implementation
)),
261 reinterpret_cast<component_getFactoryFunc
>(fp
), uri
, implementation
,
264 oslGenericFunction fp
= mod
.getFunctionSymbol(constructor
);
266 throw css::loader::CannotActivateFactoryException(
267 ("no constructor symbol \"" + constructor
268 + "\" in component library <" + uri
+ ">"),
269 css::uno::Reference
<css::uno::XInterface
>());
271 *constructorFunction
= reinterpret_cast<ImplementationConstructorFn
*>(
278 css::uno::Reference
<css::uno::XInterface
> cppu::loadSharedLibComponentFactory(
279 rtl::OUString
const & uri
, rtl::OUString
const & rPath
,
280 rtl::OUString
const & rImplName
,
281 css::uno::Reference
<css::lang::XMultiServiceFactory
> const & xMgr
,
282 css::uno::Reference
<css::registry::XRegistryKey
> const & xKey
)
283 SAL_THROW((css::loader::CannotActivateFactoryException
))
285 assert(rPath
.isEmpty()); (void) rPath
;
286 assert(!xKey
.is()); (void) xKey
;
287 css::uno::Reference
<css::uno::XInterface
> fac
;
288 cppuhelper::detail::loadSharedLibComponentFactory(
289 uri
, "", "", rImplName
, "", xMgr
, 0, &fac
);
293 #if !defined DISABLE_DYNLOADING
297 extern "C" void writeInfo(va_list * args
) {
298 component_writeInfoFunc fn
= va_arg(*args
, component_writeInfoFunc
);
299 void * smgr
= va_arg(*args
, void *);
300 void * key
= va_arg(*args
, void *);
301 sal_Bool
* ok
= va_arg(*args
, sal_Bool
*);
302 *ok
= (*fn
)(smgr
, key
);
307 void cppu::writeSharedLibComponentInfo(
308 rtl::OUString
const & uri
, rtl::OUString
const & rPath
,
309 css::uno::Reference
<css::lang::XMultiServiceFactory
> const & xMgr
,
310 css::uno::Reference
<css::registry::XRegistryKey
> const & xKey
)
311 SAL_THROW((css::registry::CannotRegisterImplementationException
))
313 assert(rPath
.isEmpty()); (void) rPath
;
314 osl::Module
mod(uri
, SAL_LOADMODULE_LAZY
| SAL_LOADMODULE_GLOBAL
);
316 throw css::registry::CannotRegisterImplementationException(
317 "loading component library <" + uri
+ "> failed",
318 css::uno::Reference
<css::uno::XInterface
>());
320 oslGenericFunction fp
= mod
.getFunctionSymbol(COMPONENT_WRITEINFO
);
322 throw css::registry::CannotRegisterImplementationException(
323 ("no symbol \"" COMPONENT_WRITEINFO
"\" in component library <"
325 css::uno::Reference
<css::uno::XInterface
>());
327 css::uno::Environment
curEnv(css::uno::Environment::getCurrent());
328 css::uno::Environment
env(getEnvironmentFromModule(mod
, curEnv
, "", ""));
329 if (!(curEnv
.is() && env
.is())) {
330 throw css::registry::CannotRegisterImplementationException(
331 "cannot get environments",
332 css::uno::Reference
<css::uno::XInterface
>());
334 css::uno::Mapping
map(curEnv
, env
);
336 throw css::registry::CannotRegisterImplementationException(
337 "cannot get mapping", css::uno::Reference
<css::uno::XInterface
>());
339 void * smgr
= map
.mapInterface(
340 xMgr
.get(), cppu::UnoType
<css::lang::XMultiServiceFactory
>::get());
341 void * key
= map
.mapInterface(
342 xKey
.get(), cppu::UnoType
<css::registry::XRegistryKey
>::get());
344 env
.invoke(writeInfo
, fp
, smgr
, key
, &ok
);
345 (*env
.get()->pExtEnv
->releaseInterface
)(env
.get()->pExtEnv
, key
);
347 (*env
.get()->pExtEnv
->releaseInterface
)(env
.get()->pExtEnv
, smgr
);
350 throw css::registry::CannotRegisterImplementationException(
351 ("calling \"" COMPONENT_WRITEINFO
"\" in component library <" + uri
352 + "> returned false"),
353 css::uno::Reference
<css::uno::XInterface
>());
359 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */