20#include <unordered_map>
22#include <osl/diagnose.h>
23#include <osl/mutex.hxx>
27#include <uno/lbnames.h>
28#include <uno/mapping.hxx>
34#include <compbase2.hxx>
36#include <com/sun/star/container/XNameContainer.hpp>
37#include <com/sun/star/lang/XSingleServiceFactory.hpp>
38#include <com/sun/star/lang/XSingleComponentFactory.hpp>
39#include <com/sun/star/lang/XMultiComponentFactory.hpp>
40#include <com/sun/star/lang/XComponent.hpp>
41#include <com/sun/star/beans/XPropertySet.hpp>
42#include <com/sun/star/uno/DeploymentException.hpp>
43#include <com/sun/star/uno/RuntimeException.hpp>
50constexpr OUStringLiteral
SMGR_SINGLETON =
u"/singletons/com.sun.star.lang.theServiceManager";
51constexpr OUStringLiteral
TDMGR_SINGLETON =
u"/singletons/com.sun.star.reflection.theTypeDescriptionManager";
52constexpr OUStringLiteral
AC_SINGLETON =
u"/singletons/com.sun.star.security.theAccessController";
61static void try_dispose( std::unique_lock<std::mutex>& rGuard, Reference< XInterface >
const & xInstance )
63 Reference< lang::XComponent > xComp( xInstance, UNO_QUERY );
72static void try_dispose( std::unique_lock<std::mutex>& rGuard, Reference< lang::XComponent >
const & xComp )
84class DisposingForwarder
85 :
public WeakImplHelper< lang::XEventListener >
89 explicit DisposingForwarder( Reference< lang::XComponent >
const & xTarget )
96 static inline void listen(
97 Reference< lang::XComponent >
const & xSource,
98 Reference< lang::XComponent >
const & xTarget );
100 virtual void SAL_CALL disposing( lang::EventObject
const & rSource )
override;
105inline void DisposingForwarder::listen(
106 Reference< lang::XComponent >
const & xSource,
107 Reference< lang::XComponent >
const & xTarget )
111 xSource->addEventListener(
new DisposingForwarder( xTarget ) );
115void DisposingForwarder::disposing( lang::EventObject
const & )
123class ComponentContext
125 container::XNameContainer >
135 ContextEntry( Any value_,
bool lateInit_ )
140 typedef std::unordered_map< OUString, ContextEntry > t_map;
143 Reference< lang::XMultiComponentFactory >
m_xSMgr;
146 Any lookupMap( OUString
const & rName );
148 virtual void disposing(std::unique_lock<std::mutex>&)
override;
151 ContextEntry_Init
const * pEntries, sal_Int32 nEntries,
152 Reference< XComponentContext >
const & xDelegate );
155 virtual Any SAL_CALL getValueByName( OUString
const & rName )
override;
156 virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager()
override;
159 virtual void SAL_CALL insertByName(
160 OUString
const & name, Any
const & element )
override;
161 virtual void SAL_CALL removeByName( OUString
const & name )
override;
163 virtual void SAL_CALL replaceByName(
164 OUString
const & name, Any
const & element )
override;
166 virtual Any SAL_CALL getByName( OUString
const & name )
override;
167 virtual Sequence<OUString> SAL_CALL getElementNames()
override;
168 virtual sal_Bool SAL_CALL hasByName( OUString
const & name )
override;
170 virtual Type SAL_CALL getElementType()
override;
171 virtual sal_Bool SAL_CALL hasElements()
override;
178void ComponentContext::insertByName(
179 OUString
const & name, Any
const & element )
184 name.startsWith(
"/singletons/" ) &&
185 !element.hasValue() );
186 std::unique_lock guard( m_aMutex );
187 std::pair<t_map::iterator, bool> insertion(
m_map.emplace(
189 if (! insertion.second)
190 throw container::ElementExistException(
191 "element already exists: " + name,
192 static_cast<OWeakObject *
>(
this) );
196void ComponentContext::removeByName( OUString
const & name )
198 std::unique_lock guard( m_aMutex );
199 t_map::iterator iFind(
m_map.find( name ) );
200 if (iFind ==
m_map.end())
201 throw container::NoSuchElementException(
202 "no such element: " + name,
203 static_cast<OWeakObject *
>(
this) );
210void ComponentContext::replaceByName(
211 OUString
const & name, Any
const & element )
213 std::unique_lock guard( m_aMutex );
214 t_map::iterator iFind(
m_map.find( name ) );
215 if (iFind ==
m_map.end())
216 throw container::NoSuchElementException(
217 "no such element: " + name,
218 static_cast<OWeakObject *
>(
this) );
219 if (
name.startsWith(
"/singletons/" ) &&
222 iFind->second.value.clear();
223 iFind->second.lateInit =
true;
227 iFind->second.value = element;
228 iFind->second.lateInit =
false;
234Any ComponentContext::getByName( OUString
const & name )
236 return getValueByName( name );
240Sequence<OUString> ComponentContext::getElementNames()
242 std::unique_lock guard( m_aMutex );
247sal_Bool ComponentContext::hasByName( OUString
const & name )
249 std::unique_lock guard( m_aMutex );
255Type ComponentContext::getElementType()
261sal_Bool ComponentContext::hasElements()
263 std::unique_lock guard( m_aMutex );
264 return !
m_map.empty();
268Any ComponentContext::lookupMap( OUString
const & rName )
270 std::unique_lock guard( m_aMutex );
271 t_map::iterator iFind(
m_map.find( rName ) );
272 if (iFind ==
m_map.end())
275 ContextEntry& rFindEntry = iFind->second;
276 if (! rFindEntry.lateInit)
277 return rFindEntry.value;
280 Reference< XInterface > xInstance;
285 Any usesService( getValueByName( rName +
"/service" ) );
286 Any args_( getValueByName( rName +
"/arguments" ) );
288 if (args_.hasValue() && !(args_ >>= args))
293 Reference< lang::XSingleComponentFactory > xFac;
294 if (usesService >>= xFac)
296 xInstance =
args.hasElements()
297 ? xFac->createInstanceWithArgumentsAndContext( args,
this )
298 : xFac->createInstanceWithContext(
this );
302 Reference< lang::XSingleServiceFactory > xFac2;
303 if (usesService >>= xFac2)
306 xInstance =
args.hasElements()
307 ? xFac2->createInstanceWithArguments( args )
308 : xFac2->createInstance();
312 OUString serviceName;
313 if ((usesService >>= serviceName) &&
314 !serviceName.isEmpty())
316 xInstance =
args.hasElements()
317 ?
m_xSMgr->createInstanceWithArgumentsAndContext(
318 serviceName, args,
this )
319 :
m_xSMgr->createInstanceWithContext(
329 catch (
const Exception & exc)
333 "exception occurred raising singleton \"" << rName <<
"\": "
338 "cppuhelper",
"no service object raising singleton " << rName);
342 iFind =
m_map.find( rName );
343 if (iFind !=
m_map.end())
345 ContextEntry & rEntry = iFind->second;
348 rEntry.value <<= xInstance;
349 rEntry.lateInit =
false;
354 if (ret != xInstance) {
361Any ComponentContext::getValueByName( OUString
const & rName )
364 if ( rName ==
"_root" )
368 return Any( Reference<XComponentContext>(
this) );
371 Any ret( lookupMap( rName ) );
379Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager()
383 throw DeploymentException(
384 "null component context service manager",
385 static_cast<OWeakObject *
>(
this) );
390void ComponentContext::disposing(std::unique_lock<std::mutex>& rGuard)
392 Reference< lang::XComponent > xTDMgr, xAC;
395 for (
auto& [rName, rEntry] :
m_map )
406 rEntry.value.clear();
407 rEntry.lateInit =
false;
412 Reference< lang::XComponent > xComp;
413 rEntry.value >>= xComp;
450 &envs, &envCount, &rtl_allocateMemory, OUString(
"java").pData);
451 assert(envCount >= 0);
452 assert(envCount == 0 || envs !=
nullptr);
454 for (sal_Int32 i = 0;
i != envCount; ++
i) {
455 assert(envs[i] !=
nullptr);
456 assert(envs[i]->dispose !=
nullptr);
457 (*envs[
i]->dispose)(envs[i]);
463ComponentContext::ComponentContext(
464 ContextEntry_Init
const * pEntries, sal_Int32 nEntries,
465 Reference< XComponentContext >
const & xDelegate )
468 for ( sal_Int32 nPos = 0;
nPos < nEntries; ++
nPos )
470 ContextEntry_Init
const & rEntry = pEntries[
nPos ];
477 if (rEntry.bLateInitService)
480 m_map.emplace( rEntry.name, ContextEntry(
Any(),
true ) );
482 m_map.emplace( rEntry.name +
"/service", ContextEntry( rEntry.value,
false ) );
488 m_map.emplace( rEntry.name, ContextEntry( rEntry.value,
false ) );
496 Reference< lang::XMultiComponentFactory > xMgr(
m_xDelegate->getServiceManager() );
500 osl_atomic_increment( &m_refCount );
505 xMgr->createInstanceWithContext(
506 "com.sun.star.comp.stoc.OServiceManagerWrapper", xDelegate ),
509 Reference< beans::XPropertySet > xProps(
m_xSMgr, UNO_QUERY );
510 OSL_ASSERT( xProps.is() );
513 Reference< XComponentContext > xThis(
this );
514 xProps->setPropertyValue(
"DefaultContext",
Any( xThis ) );
519 osl_atomic_decrement( &m_refCount );
522 osl_atomic_decrement( &m_refCount );
530 sal_Int32 nEntries = va_arg(*pParam, sal_Int32);
531 XComponentContext * pDelegatee = va_arg(*pParam, XComponentContext *);
532 void ** ppContext = va_arg(*pParam,
void **);
533 uno::Mapping * pTarget2curr = va_arg(*pParam, uno::Mapping *);
535 Reference<XComponentContext> xDelegate(pDelegatee, SAL_NO_ACQUIRE);
536 Reference<XComponentContext> xContext;
542 ComponentContext *
p =
new ComponentContext( pEntries, nEntries, xDelegate );
545 DisposingForwarder::listen( Reference< lang::XComponent >::query( xDelegate ),
p );
555 xContext = xDelegate;
558 *ppContext = pTarget2curr->mapInterface(xContext.get(),
cppu::UnoType<
decltype(xContext)>::get());
563 Reference< XComponentContext >
const & xDelegate )
565 uno::Environment curr_env(Environment::getCurrent());
566 uno::Environment source_env(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
568 uno::Mapping curr2source(curr_env, source_env);
569 uno::Mapping source2curr(source_env, curr_env);
571 std::unique_ptr<ContextEntry_Init[]> mapped_entries(
new ContextEntry_Init[nEntries]);
578 const_cast<void *
>(pEntries[
nPos].
value.getValue()),
583 void * mapped_delegate = curr2source.mapInterface(xDelegate.get(),
cppu::UnoType<
decltype(xDelegate)>::get());
584 XComponentContext * pXComponentContext =
nullptr;
585 source_env.invoke(
s_createComponentContext_v, mapped_entries.get(), nEntries, mapped_delegate, &pXComponentContext, &source2curr);
586 mapped_entries.reset();
588 return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE);
void SAL_CALL uno_type_any_constructAndConvert(uno_Any *pDest, void *pSource, typelib_TypeDescriptionReference *pType, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
css::uno::Type const & get()
Reference< lang::XMultiComponentFactory > m_xSMgr
constexpr OUStringLiteral SMGR_SINGLETON
constexpr OUStringLiteral TDMGR_SINGLETON
Reference< XComponentContext > m_xDelegate
Reference< lang::XComponent > m_xTarget
constexpr OUStringLiteral AC_SINGLETON
Reference< XInterface > xTarget
struct _uno_Environment uno_Environment
void SAL_CALL uno_getRegisteredEnvironments(uno_Environment ***pppEnvs, sal_Int32 *pnLen, uno_memAlloc memAlloc, rtl_uString *pEnvDcp) SAL_THROW_EXTERN_C()
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
css::uno::Sequence< typename M::key_type > mapKeysToSequence(M const &map)
static void try_dispose(std::unique_lock< std::mutex > &rGuard, Reference< XInterface > const &xInstance)
static void s_createComponentContext_v(va_list *pParam)
Reference< XComponentContext > SAL_CALL createComponentContext(ContextEntry_Init const *pEntries, sal_Int32 nEntries, Reference< XComponentContext > const &xDelegate)
Context entries init struct calling createComponentContext().
::rtl::OUString name
name of context value
bool bLateInitService
late init denotes an object that will be raised when first get() is calling for it
css::uno::Any value
context value