Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/stoc/source/servicemanager/servicemanager.cxx
Line
Count
Source
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 <o3tl/any.hxx>
23
#include <osl/mutex.hxx>
24
#include <osl/diagnose.h>
25
#include <sal/log.hxx>
26
27
#include <cppuhelper/basemutex.hxx>
28
#include <cppuhelper/factory.hxx>
29
#include <cppuhelper/weakref.hxx>
30
#include <cppuhelper/implbase.hxx>
31
#include <cppuhelper/compbase.hxx>
32
#include <cppuhelper/supportsservice.hxx>
33
#include <comphelper/sequence.hxx>
34
#include <rtl/ref.hxx>
35
36
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
37
#include <com/sun/star/lang/XMultiComponentFactory.hpp>
38
#include <com/sun/star/lang/XServiceInfo.hpp>
39
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
40
#include <com/sun/star/lang/XSingleComponentFactory.hpp>
41
#include <com/sun/star/lang/XInitialization.hpp>
42
#include <com/sun/star/lang/XEventListener.hpp>
43
#include <com/sun/star/lang/DisposedException.hpp>
44
#include <com/sun/star/beans/XPropertySet.hpp>
45
#include <com/sun/star/beans/PropertyAttribute.hpp>
46
#include <com/sun/star/registry/XRegistryKey.hpp>
47
#include <com/sun/star/registry/XSimpleRegistry.hpp>
48
#include <com/sun/star/container/XSet.hpp>
49
#include <com/sun/star/container/XElementAccess.hpp>
50
#include <com/sun/star/container/XEnumeration.hpp>
51
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
52
#include <com/sun/star/uno/XComponentContext.hpp>
53
54
#include <iterator>
55
#include <mutex>
56
#include <string_view>
57
#include <unordered_map>
58
#include <unordered_set>
59
#include <utility>
60
61
using namespace com::sun::star;
62
using namespace css::uno;
63
using namespace css::beans;
64
using namespace css::registry;
65
using namespace css::lang;
66
using namespace css::container;
67
using namespace cppu;
68
using namespace osl;
69
70
namespace {
71
72
Sequence< OUString > retrieveAsciiValueList(
73
    const Reference< XSimpleRegistry > &xReg, const OUString &keyName )
74
0
{
75
0
    Reference< XEnumerationAccess > xAccess( xReg, UNO_QUERY );
76
0
    Sequence< OUString > seq;
77
0
    if( xAccess.is() )
78
0
    {
79
0
        Reference< XEnumeration > xEnum = xAccess->createEnumeration();
80
0
        while( xEnum.is() && xEnum->hasMoreElements() )
81
0
        {
82
0
            Reference< XSimpleRegistry > xTempReg;
83
0
            xEnum->nextElement() >>= xTempReg;
84
0
            if( xTempReg.is() )
85
0
            {
86
0
                const Sequence< OUString > seq2 = retrieveAsciiValueList( xTempReg, keyName );
87
88
0
                if( seq2.hasElements() )
89
0
                {
90
0
                    sal_Int32 n1Len = seq.getLength();
91
0
                    sal_Int32 n2Len = seq2.getLength();
92
93
0
                    seq.realloc( n1Len + n2Len );
94
0
                    std::copy(seq2.begin(), seq2.end(), std::next(seq.getArray(), n1Len));
95
0
                }
96
0
            }
97
0
        }
98
0
    }
99
0
    else if( xReg.is () )
100
0
    {
101
0
        try
102
0
        {
103
0
            Reference< XRegistryKey > rRootKey = xReg->getRootKey();
104
0
            if( rRootKey.is() )
105
0
            {
106
0
                Reference<XRegistryKey > xKey = rRootKey->openKey(keyName);
107
0
                if( xKey.is() )
108
0
                {
109
0
                    seq = xKey->getAsciiListValue();
110
0
                }
111
0
            }
112
0
        }
113
0
        catch( InvalidRegistryException & )
114
0
        {
115
0
        }
116
0
        catch (InvalidValueException &)
117
0
        {
118
0
        }
119
0
    }
120
0
    return seq;
121
0
}
122
123
/*****************************************************************************
124
    Enumeration by ServiceName
125
*****************************************************************************/
126
127
typedef std::unordered_set< Reference<XInterface > > HashSet_Ref;
128
129
130
class ServiceEnumeration_Impl : public WeakImplHelper< XEnumeration >
131
{
132
public:
133
    explicit ServiceEnumeration_Impl( const Sequence< Reference<XInterface > > & rFactories )
134
0
        : aFactories( rFactories )
135
0
        , nIt( 0 )
136
0
        {}
137
138
    // XEnumeration
139
    sal_Bool SAL_CALL hasMoreElements() override;
140
    Any SAL_CALL nextElement() override;
141
private:
142
    std::mutex                          aMutex;
143
    Sequence< Reference<XInterface > >  aFactories;
144
    sal_Int32                           nIt;
145
};
146
147
// XEnumeration
148
sal_Bool ServiceEnumeration_Impl::hasMoreElements()
149
0
{
150
0
    std::scoped_lock aGuard( aMutex );
151
0
    return nIt != aFactories.getLength();
152
0
}
153
154
// XEnumeration
155
Any ServiceEnumeration_Impl::nextElement()
156
0
{
157
0
    std::scoped_lock aGuard( aMutex );
158
0
    if( nIt == aFactories.getLength() )
159
0
        throw NoSuchElementException(u"no more elements"_ustr);
160
161
0
    return Any( &aFactories[nIt++], cppu::UnoType<XInterface>::get());
162
0
}
163
164
165
class PropertySetInfo_Impl : public WeakImplHelper< beans::XPropertySetInfo >
166
{
167
    Sequence< beans::Property > m_properties;
168
169
public:
170
    explicit PropertySetInfo_Impl( Sequence< beans::Property > const & properties )
171
0
        : m_properties( properties )
172
0
        {}
173
174
    // XPropertySetInfo impl
175
    virtual Sequence< beans::Property > SAL_CALL getProperties() override;
176
    virtual beans::Property SAL_CALL getPropertyByName( OUString const & name ) override;
177
    virtual sal_Bool SAL_CALL hasPropertyByName( OUString const & name ) override;
178
};
179
180
Sequence< beans::Property > PropertySetInfo_Impl::getProperties()
181
0
{
182
0
    return m_properties;
183
0
}
184
185
beans::Property PropertySetInfo_Impl::getPropertyByName( OUString const & name )
186
0
{
187
0
    for ( sal_Int32 nPos = m_properties.getLength(); nPos--; )
188
0
    {
189
0
        if (m_properties[nPos].Name == name)
190
0
            return m_properties[nPos];
191
0
    }
192
0
    throw beans::UnknownPropertyException(
193
0
        "unknown property: " + name );
194
0
}
195
196
sal_Bool PropertySetInfo_Impl::hasPropertyByName( OUString const & name )
197
0
{
198
0
    return std::any_of(std::cbegin(m_properties), std::cend(m_properties),
199
0
        [&name](const beans::Property& rProp) { return rProp.Name == name; });
200
0
}
201
202
203
/*****************************************************************************
204
    Enumeration by implementation
205
*****************************************************************************/
206
class ImplementationEnumeration_Impl : public WeakImplHelper< XEnumeration >
207
{
208
public:
209
    explicit ImplementationEnumeration_Impl( HashSet_Ref xImplementationMap )
210
0
        : aImplementationMap(std::move( xImplementationMap ))
211
0
        , aIt( aImplementationMap.begin() )
212
0
        {}
213
214
    // XEnumeration
215
    virtual sal_Bool SAL_CALL hasMoreElements() override;
216
    virtual Any SAL_CALL nextElement() override;
217
218
private:
219
    std::mutex                      aMutex;
220
    HashSet_Ref                     aImplementationMap;
221
    HashSet_Ref::iterator           aIt;
222
};
223
224
// XEnumeration
225
sal_Bool ImplementationEnumeration_Impl::hasMoreElements()
226
0
{
227
0
    std::scoped_lock aGuard( aMutex );
228
0
    return aIt != aImplementationMap.end();
229
0
}
230
231
// XEnumeration
232
Any ImplementationEnumeration_Impl::nextElement()
233
0
{
234
0
    std::scoped_lock aGuard( aMutex );
235
0
    if( aIt == aImplementationMap.end() )
236
0
        throw NoSuchElementException(u"no more elements"_ustr);
237
238
0
    Any ret( &(*aIt), cppu::UnoType<XInterface>::get());
239
0
    ++aIt;
240
0
    return ret;
241
0
}
242
243
/*****************************************************************************
244
    Hash tables
245
*****************************************************************************/
246
typedef std::unordered_set
247
<
248
    OUString
249
> HashSet_OWString;
250
251
typedef std::unordered_multimap
252
<
253
    OUString,
254
    Reference<XInterface >
255
> HashMultimap_OWString_Interface;
256
257
typedef std::unordered_map
258
<
259
    OUString,
260
    Reference<XInterface >
261
> HashMap_OWString_Interface;
262
263
/*****************************************************************************
264
    class OServiceManager_Listener
265
*****************************************************************************/
266
class OServiceManager_Listener : public WeakImplHelper< XEventListener >
267
{
268
private:
269
    WeakReference<XSet > xSMgr;
270
271
public:
272
    explicit OServiceManager_Listener( const Reference<XSet > & rSMgr )
273
0
        : xSMgr( rSMgr )
274
0
        {}
275
276
    // XEventListener
277
    virtual void SAL_CALL disposing(const EventObject & rEvt ) override;
278
};
279
280
void OServiceManager_Listener::disposing(const EventObject & rEvt )
281
0
{
282
0
    Reference<XSet > x( xSMgr );
283
0
    if( !x.is() )
284
0
        return;
285
286
0
    try
287
0
    {
288
0
        x->remove( Any( &rEvt.Source, cppu::UnoType<XInterface>::get()) );
289
0
    }
290
0
    catch( const IllegalArgumentException & )
291
0
    {
292
0
        OSL_FAIL( "IllegalArgumentException caught" );
293
0
    }
294
0
    catch( const NoSuchElementException & )
295
0
    {
296
0
        OSL_FAIL( "NoSuchElementException caught" );
297
0
    }
298
0
}
299
300
301
/*****************************************************************************
302
    class OServiceManager
303
*****************************************************************************/
304
305
typedef WeakComponentImplHelper<
306
    lang::XMultiServiceFactory, lang::XMultiComponentFactory, lang::XServiceInfo,
307
    lang::XInitialization,
308
    container::XSet, container::XContentEnumerationAccess,
309
    beans::XPropertySet > t_OServiceManager_impl;
310
311
class OServiceManager
312
    : public cppu::BaseMutex
313
    , public t_OServiceManager_impl
314
{
315
public:
316
    explicit OServiceManager( Reference< XComponentContext > const & xContext );
317
318
    // XInitialization
319
    void SAL_CALL initialize( Sequence< Any > const & args ) override;
320
321
    // XServiceInfo
322
    virtual OUString SAL_CALL getImplementationName() override;
323
    virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
324
    virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
325
326
    // XMultiComponentFactory
327
    virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
328
        OUString const & rServiceSpecifier, Reference< XComponentContext > const & xContext ) override;
329
    virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
330
        OUString const & rServiceSpecifier,
331
        Sequence< Any > const & rArguments,
332
        Reference< XComponentContext > const & xContext ) override;
333
//      virtual Sequence< OUString > SAL_CALL getAvailableServiceNames()
334
//          throw (RuntimeException);
335
336
    // XMultiServiceFactory
337
    virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
338
    virtual Reference<XInterface > SAL_CALL createInstance(const OUString &) override;
339
    virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const OUString &, const Sequence<Any >& Arguments) override;
340
341
    // The same as the getAvailableServiceNames, but only unique names
342
    Sequence< OUString > getUniqueAvailableServiceNames(
343
        HashSet_OWString & aNameSet );
344
345
    // XElementAccess
346
    virtual Type SAL_CALL getElementType() override;
347
    virtual sal_Bool SAL_CALL hasElements() override;
348
349
    // XEnumerationAccess
350
    virtual Reference<XEnumeration > SAL_CALL createEnumeration() override;
351
352
    // XSet
353
    virtual sal_Bool SAL_CALL has( const Any & Element ) override;
354
    virtual void SAL_CALL insert( const Any & Element ) override;
355
    virtual void SAL_CALL remove( const Any & Element ) override;
356
357
    // XContentEnumerationAccess
358
    //Sequence< OUString >          getAvailableServiceNames() throw( (Exception) );
359
    virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) override;
360
361
    // XComponent
362
    virtual void SAL_CALL dispose() override;
363
364
    // XPropertySet
365
    Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
366
    void SAL_CALL setPropertyValue(const OUString& PropertyName, const Any& aValue) override;
367
    Any SAL_CALL getPropertyValue(const OUString& PropertyName) override;
368
    void SAL_CALL addPropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) override;
369
    void SAL_CALL removePropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) override;
370
    void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) override;
371
    void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) override;
372
373
protected:
374
    bool is_disposed() const;
375
    void check_undisposed() const;
376
    virtual void SAL_CALL disposing() override;
377
378
    bool haveFactoryWithThisImplementation(const OUString& aImplName);
379
380
    virtual Sequence< Reference< XInterface > > queryServiceFactories(
381
        const OUString& aServiceName, Reference< XComponentContext > const & xContext );
382
383
    Reference< XComponentContext >  m_xContext;
384
385
    Reference< beans::XPropertySetInfo > m_xPropertyInfo;
386
387
    // factories which have been loaded and not inserted( by XSet::insert)
388
    // are remembered by this set.
389
    HashSet_Ref m_SetLoadedFactories;
390
private:
391
392
    Reference<XEventListener >      getFactoryListener();
393
394
395
    HashMultimap_OWString_Interface m_ServiceMap;
396
    HashSet_Ref                     m_ImplementationMap;
397
    HashMap_OWString_Interface      m_ImplementationNameMap;
398
    rtl::Reference<OServiceManager_Listener > xFactoryListener;
399
    bool                            m_bInDisposing;
400
};
401
402
403
bool OServiceManager::is_disposed() const
404
0
{
405
    // ought to be guarded by m_mutex:
406
0
    return (m_bInDisposing || rBHelper.bDisposed);
407
0
}
408
409
410
void OServiceManager::check_undisposed() const
411
0
{
412
0
    if (is_disposed())
413
0
    {
414
0
        throw lang::DisposedException(
415
0
            u"service manager instance has already been disposed!"_ustr,
416
0
            const_cast<OServiceManager *>(this)->getXWeak() );
417
0
    }
418
0
}
419
420
421
typedef WeakComponentImplHelper<
422
    lang::XMultiServiceFactory, lang::XMultiComponentFactory, lang::XServiceInfo,
423
    container::XSet, container::XContentEnumerationAccess,
424
    beans::XPropertySet > t_OServiceManagerWrapper_impl;
425
426
class OServiceManagerWrapper : public cppu::BaseMutex, public t_OServiceManagerWrapper_impl
427
{
428
    Reference< XComponentContext > m_xContext;
429
    Reference< XMultiComponentFactory > m_root;
430
    Reference< XMultiComponentFactory > const & getRoot() const
431
0
    {
432
0
        if (! m_root.is())
433
0
        {
434
0
            throw lang::DisposedException(
435
0
                u"service manager instance has already been disposed!"_ustr );
436
0
        }
437
0
        return m_root;
438
0
    }
439
440
protected:
441
    virtual void SAL_CALL disposing() override;
442
443
public:
444
    explicit OServiceManagerWrapper(
445
        Reference< XComponentContext > const & xContext );
446
447
    // XServiceInfo
448
    virtual OUString SAL_CALL getImplementationName() override
449
0
        { return Reference< XServiceInfo >(getRoot(), UNO_QUERY_THROW)->getImplementationName(); }
450
    virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override
451
0
        { return Reference< XServiceInfo >(getRoot(), UNO_QUERY_THROW)->supportsService( ServiceName ); }
452
    virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override
453
0
        { return Reference< XServiceInfo >(getRoot(), UNO_QUERY_THROW)->getSupportedServiceNames(); }
454
455
    // XMultiComponentFactory
456
    virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
457
        OUString const & rServiceSpecifier, Reference< XComponentContext > const & xContext ) override
458
0
        { return getRoot()->createInstanceWithContext( rServiceSpecifier, xContext ); }
459
    virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
460
        OUString const & rServiceSpecifier,
461
        Sequence< Any > const & rArguments,
462
        Reference< XComponentContext > const & xContext ) override
463
0
        { return getRoot()->createInstanceWithArgumentsAndContext( rServiceSpecifier, rArguments, xContext ); }
464
//      virtual Sequence< OUString > SAL_CALL getAvailableServiceNames()
465
//          throw (RuntimeException);
466
467
    // XMultiServiceFactory
468
    virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() override
469
0
        { return getRoot()->getAvailableServiceNames(); }
470
    virtual Reference<XInterface > SAL_CALL createInstance(const OUString & name) override
471
0
        { return getRoot()->createInstanceWithContext( name, m_xContext ); }
472
    virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const OUString & name, const Sequence<Any >& Arguments) override
473
0
        { return getRoot()->createInstanceWithArgumentsAndContext( name, Arguments, m_xContext ); }
474
475
    // XElementAccess
476
    virtual Type SAL_CALL getElementType() override
477
0
        { return Reference< XElementAccess >(getRoot(), UNO_QUERY_THROW)->getElementType(); }
478
    virtual sal_Bool SAL_CALL hasElements() override
479
0
        { return Reference< XElementAccess >(getRoot(), UNO_QUERY_THROW)->hasElements(); }
480
481
    // XEnumerationAccess
482
    virtual Reference<XEnumeration > SAL_CALL createEnumeration() override
483
0
        { return Reference< XEnumerationAccess >(getRoot(), UNO_QUERY_THROW)->createEnumeration(); }
484
485
    // XSet
486
    virtual sal_Bool SAL_CALL has( const Any & Element ) override
487
0
        { return Reference< XSet >(getRoot(), UNO_QUERY_THROW)->has( Element ); }
488
    virtual void SAL_CALL insert( const Any & Element ) override
489
0
        { Reference< XSet >(getRoot(), UNO_QUERY_THROW)->insert( Element ); }
490
    virtual void SAL_CALL remove( const Any & Element ) override
491
0
        { Reference< XSet >(getRoot(), UNO_QUERY_THROW)->remove( Element ); }
492
493
    // XContentEnumerationAccess
494
    //Sequence< OUString >          getAvailableServiceNames() throw( (Exception) );
495
    virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) override
496
0
        { return Reference< XContentEnumerationAccess >(getRoot(), UNO_QUERY_THROW)->createContentEnumeration( aServiceName ); }
497
498
    // XPropertySet
499
    Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() override
500
0
        { return Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->getPropertySetInfo(); }
501
502
    void SAL_CALL setPropertyValue(const OUString& PropertyName, const Any& aValue) override;
503
    Any SAL_CALL getPropertyValue(const OUString& PropertyName) override;
504
505
    void SAL_CALL addPropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) override
506
0
        { Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->addPropertyChangeListener( PropertyName, aListener ); }
507
    void SAL_CALL removePropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) override
508
0
        { Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->removePropertyChangeListener( PropertyName, aListener ); }
509
    void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) override
510
0
        { Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->addVetoableChangeListener( PropertyName, aListener ); }
511
    void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) override
512
0
        { Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->removeVetoableChangeListener( PropertyName, aListener ); }
513
};
514
515
void SAL_CALL OServiceManagerWrapper::setPropertyValue(
516
    const OUString& PropertyName, const Any& aValue )
517
0
{
518
0
    if ( PropertyName == "DefaultContext" )
519
0
    {
520
0
        Reference< XComponentContext > xContext;
521
0
        if (!(aValue >>= xContext))
522
0
        {
523
0
            throw IllegalArgumentException(
524
0
                u"no XComponentContext given!"_ustr,
525
0
                getXWeak(), 1 );
526
0
        }
527
528
0
        MutexGuard aGuard( m_aMutex );
529
0
        m_xContext = std::move(xContext);
530
531
0
    }
532
0
    else
533
0
    {
534
0
        Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->setPropertyValue( PropertyName, aValue );
535
0
    }
536
0
}
537
538
Any SAL_CALL OServiceManagerWrapper::getPropertyValue(
539
    const OUString& PropertyName )
540
0
{
541
0
    if ( PropertyName == "DefaultContext" )
542
0
    {
543
0
        MutexGuard aGuard( m_aMutex );
544
0
        if( m_xContext.is() )
545
0
            return Any( m_xContext );
546
0
        else
547
0
            return Any();
548
0
    }
549
0
    else
550
0
    {
551
0
        return Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->getPropertyValue( PropertyName );
552
0
    }
553
0
}
554
555
void OServiceManagerWrapper::disposing()
556
0
{
557
0
    m_xContext.clear();
558
559
// no m_root->dispose(), because every context disposes its service manager...
560
0
    m_root.clear();
561
0
}
562
563
OServiceManagerWrapper::OServiceManagerWrapper(
564
    Reference< XComponentContext > const & xContext )
565
0
    : t_OServiceManagerWrapper_impl( m_aMutex )
566
0
    , m_xContext( xContext )
567
0
    , m_root( xContext->getServiceManager() )
568
0
{
569
0
    if (! m_root.is())
570
0
    {
571
0
        throw RuntimeException(
572
0
            u"no service manager to wrap"_ustr );
573
0
    }
574
0
}
575
576
577
/**
578
 * Create a ServiceManager
579
 */
580
OServiceManager::OServiceManager( Reference< XComponentContext > const & xContext )
581
0
    : t_OServiceManager_impl( m_aMutex )
582
0
    , m_xContext( xContext )
583
0
    , m_bInDisposing( false )
584
0
{}
585
586
// XComponent
587
void OServiceManager::dispose()
588
0
{
589
0
    if (rBHelper.bDisposed || rBHelper.bInDispose)
590
0
        return;
591
0
    t_OServiceManager_impl::dispose();
592
0
}
593
594
void OServiceManager::disposing()
595
0
{
596
    // dispose all factories
597
0
    HashSet_Ref aImpls;
598
0
    {
599
0
        MutexGuard aGuard( m_aMutex );
600
0
        m_bInDisposing = true;
601
0
        aImpls = m_ImplementationMap;
602
0
    }
603
0
    for( const auto& rxImpl : aImpls )
604
0
    {
605
0
        try
606
0
        {
607
0
            Reference<XComponent > xComp( Reference<XComponent >::query( rxImpl ) );
608
0
            if( xComp.is() )
609
0
                xComp->dispose();
610
0
        }
611
0
        catch (const RuntimeException & exc)
612
0
        {
613
0
            SAL_INFO("stoc", "RuntimeException occurred upon disposing factory: " << exc);
614
0
        }
615
0
    }
616
617
    // dispose
618
0
    HashSet_Ref aImplMap;
619
0
    {
620
0
        MutexGuard aGuard( m_aMutex );
621
        // erase all members
622
0
        m_ServiceMap = HashMultimap_OWString_Interface();
623
0
        aImplMap = m_ImplementationMap;
624
0
        m_ImplementationMap = HashSet_Ref();
625
0
        m_ImplementationNameMap = HashMap_OWString_Interface();
626
0
        m_SetLoadedFactories= HashSet_Ref();
627
0
    }
628
629
0
    m_xContext.clear();
630
631
    // not only the Event should hold the object
632
0
    OSL_ASSERT( m_refCount != 1 );
633
0
}
634
635
// XPropertySet
636
Reference<XPropertySetInfo > OServiceManager::getPropertySetInfo()
637
0
{
638
0
    check_undisposed();
639
0
    if (! m_xPropertyInfo.is())
640
0
    {
641
0
        Sequence< beans::Property > seq{ beans::Property(
642
0
            u"DefaultContext"_ustr, -1, cppu::UnoType<decltype(m_xContext)>::get(), 0 ) };
643
0
        Reference< beans::XPropertySetInfo > xInfo( new PropertySetInfo_Impl( seq ) );
644
645
0
        MutexGuard aGuard( m_aMutex );
646
0
        if (! m_xPropertyInfo.is())
647
0
        {
648
0
            m_xPropertyInfo = std::move(xInfo);
649
0
        }
650
0
    }
651
0
    return m_xPropertyInfo;
652
0
}
653
654
void OServiceManager::setPropertyValue(
655
    const OUString& PropertyName, const Any& aValue )
656
0
{
657
0
    check_undisposed();
658
0
    if ( PropertyName != "DefaultContext" )
659
0
    {
660
0
        throw UnknownPropertyException(
661
0
            "unknown property " + PropertyName,
662
0
            getXWeak() );
663
0
    }
664
665
0
    Reference< XComponentContext > xContext;
666
0
    if (!(aValue >>= xContext))
667
0
    {
668
0
        throw IllegalArgumentException(
669
0
            u"no XComponentContext given!"_ustr,
670
0
            getXWeak(), 1 );
671
0
    }
672
673
0
    MutexGuard aGuard( m_aMutex );
674
0
    m_xContext = std::move(xContext);
675
0
}
676
677
Any OServiceManager::getPropertyValue(const OUString& PropertyName)
678
0
{
679
0
    check_undisposed();
680
0
    if ( PropertyName == "DefaultContext" )
681
0
    {
682
0
        MutexGuard aGuard( m_aMutex );
683
0
        if( m_xContext.is() )
684
0
            return Any( m_xContext );
685
0
        else
686
0
            return Any();
687
0
    }
688
0
    else
689
0
    {
690
0
        UnknownPropertyException except("ServiceManager : unknown property " + PropertyName, {});
691
0
        throw except;
692
0
    }
693
0
}
694
695
void OServiceManager::addPropertyChangeListener(
696
    const OUString&, const Reference<XPropertyChangeListener >&)
697
0
{
698
0
    check_undisposed();
699
0
    throw UnknownPropertyException(u"unsupported"_ustr);
700
0
}
701
702
void OServiceManager::removePropertyChangeListener(
703
    const OUString&, const Reference<XPropertyChangeListener >&)
704
0
{
705
0
    check_undisposed();
706
0
    throw UnknownPropertyException(u"unsupported"_ustr);
707
0
}
708
709
void OServiceManager::addVetoableChangeListener(
710
    const OUString&, const Reference<XVetoableChangeListener >&)
711
0
{
712
0
    check_undisposed();
713
0
    throw UnknownPropertyException(u"unsupported"_ustr);
714
0
}
715
716
void OServiceManager::removeVetoableChangeListener(
717
    const OUString&, const Reference<XVetoableChangeListener >&)
718
0
{
719
0
    check_undisposed();
720
0
    throw UnknownPropertyException(u"unsupported"_ustr);
721
0
}
722
723
// OServiceManager
724
Reference<XEventListener > OServiceManager::getFactoryListener()
725
0
{
726
0
    check_undisposed();
727
0
    MutexGuard aGuard( m_aMutex );
728
0
    if( !xFactoryListener.is() )
729
0
        xFactoryListener = new OServiceManager_Listener( this );
730
0
    return xFactoryListener;
731
0
}
732
733
// XMultiServiceFactory, XContentEnumeration
734
Sequence< OUString > OServiceManager::getUniqueAvailableServiceNames(
735
    HashSet_OWString & aNameSet )
736
0
{
737
0
    check_undisposed();
738
0
    MutexGuard aGuard( m_aMutex );
739
0
    for( const auto& rEntry : m_ServiceMap )
740
0
        aNameSet.insert( rEntry.first );
741
742
    /* do not return the implementation names
743
    HashMap_OWString_Interface      m_ImplementationNameMap;
744
    HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.begin();
745
    while( aIt != m_ImplementationNameMap.end() )
746
        aNameSet.insert( (*aIt++).first );
747
    */
748
749
0
    return comphelper::containerToSequence(aNameSet);
750
0
}
751
752
// XMultiComponentFactory
753
Reference< XInterface > OServiceManager::createInstanceWithContext(
754
    OUString const & rServiceSpecifier,
755
    Reference< XComponentContext > const & xContext )
756
0
{
757
0
    check_undisposed();
758
#if OSL_DEBUG_LEVEL > 0
759
    Reference< beans::XPropertySet > xProps( xContext->getServiceManager(), UNO_QUERY );
760
    OSL_ASSERT( xProps.is() );
761
    if (xProps.is())
762
    {
763
        Reference< XComponentContext > xDefContext;
764
        xProps->getPropertyValue( u"DefaultContext"_ustr ) >>= xDefContext;
765
        OSL_ENSURE(
766
            xContext == xDefContext,
767
            "### default context of service manager singleton differs from context holding it!" );
768
    }
769
#endif
770
771
0
    const Sequence< Reference< XInterface > > factories(
772
0
        queryServiceFactories( rServiceSpecifier, xContext ) );
773
0
    for ( Reference< XInterface > const & xFactory : factories )
774
0
    {
775
0
        try
776
0
        {
777
0
            if (xFactory.is())
778
0
            {
779
0
                Reference< XSingleComponentFactory > xFac( xFactory, UNO_QUERY );
780
0
                if (xFac.is())
781
0
                {
782
0
                    return xFac->createInstanceWithContext( xContext );
783
0
                }
784
0
                else
785
0
                {
786
0
                    Reference< XSingleServiceFactory > xFac2( xFactory, UNO_QUERY );
787
0
                    if (xFac2.is())
788
0
                    {
789
0
                        SAL_INFO("stoc", "ignoring given context raising service " << rServiceSpecifier << "!!!");
790
0
                        return xFac2->createInstance();
791
0
                    }
792
0
                }
793
0
            }
794
0
        }
795
0
        catch (const lang::DisposedException & exc)
796
0
        {
797
0
            SAL_INFO("stoc", "DisposedException occurred: " << exc);
798
0
        }
799
0
    }
800
801
0
    return Reference< XInterface >();
802
0
}
803
// XMultiComponentFactory
804
Reference< XInterface > OServiceManager::createInstanceWithArgumentsAndContext(
805
    OUString const & rServiceSpecifier,
806
    Sequence< Any > const & rArguments,
807
    Reference< XComponentContext > const & xContext )
808
0
{
809
0
    check_undisposed();
810
#if OSL_DEBUG_LEVEL > 0
811
    Reference< beans::XPropertySet > xProps( xContext->getServiceManager(), UNO_QUERY );
812
    OSL_ASSERT( xProps.is() );
813
    if (xProps.is())
814
    {
815
        Reference< XComponentContext > xDefContext;
816
        xProps->getPropertyValue( u"DefaultContext"_ustr ) >>= xDefContext;
817
        OSL_ENSURE(
818
            xContext == xDefContext,
819
            "### default context of service manager singleton differs from context holding it!" );
820
    }
821
#endif
822
823
0
    const Sequence< Reference< XInterface > > factories(
824
0
        queryServiceFactories( rServiceSpecifier, xContext ) );
825
0
    for ( Reference< XInterface > const & xFactory : factories )
826
0
    {
827
0
        try
828
0
        {
829
0
            if (xFactory.is())
830
0
            {
831
0
                Reference< XSingleComponentFactory > xFac( xFactory, UNO_QUERY );
832
0
                if (xFac.is())
833
0
                {
834
0
                    return xFac->createInstanceWithArgumentsAndContext( rArguments, xContext );
835
0
                }
836
0
                else
837
0
                {
838
0
                    Reference< XSingleServiceFactory > xFac2( xFactory, UNO_QUERY );
839
0
                    if (xFac2.is())
840
0
                    {
841
0
                        SAL_INFO("stoc", "ignoring given context raising service " << rServiceSpecifier << "!!!");
842
0
                        return xFac2->createInstanceWithArguments( rArguments );
843
0
                    }
844
0
                }
845
0
            }
846
0
        }
847
0
        catch (const lang::DisposedException & exc)
848
0
        {
849
0
            SAL_INFO("stoc", "DisposedException occurred: " << exc);
850
0
        }
851
0
    }
852
853
0
    return Reference< XInterface >();
854
0
}
855
856
// XMultiServiceFactory, XMultiComponentFactory, XContentEnumeration
857
Sequence< OUString > OServiceManager::getAvailableServiceNames()
858
0
{
859
0
    check_undisposed();
860
    // all names
861
0
    HashSet_OWString aNameSet;
862
0
    return getUniqueAvailableServiceNames( aNameSet );
863
0
}
864
865
// XMultipleServiceFactory
866
Reference<XInterface > OServiceManager::createInstance(
867
    const OUString& rServiceSpecifier )
868
0
{
869
0
    return createInstanceWithContext(
870
0
        rServiceSpecifier, m_xContext );
871
0
}
872
873
// XMultipleServiceFactory
874
Reference<XInterface > OServiceManager::createInstanceWithArguments(
875
    const OUString& rServiceSpecifier,
876
    const Sequence<Any >& rArguments )
877
0
{
878
0
    return createInstanceWithArgumentsAndContext(
879
0
        rServiceSpecifier, rArguments, m_xContext );
880
0
}
881
882
// XInitialization
883
void OServiceManager::initialize( Sequence< Any > const & )
884
0
{
885
0
    check_undisposed();
886
0
    OSL_FAIL( "not impl!" );
887
0
}
888
889
// XServiceInfo
890
OUString OServiceManager::getImplementationName()
891
0
{
892
0
    return u"com.sun.star.comp.stoc.OServiceManager"_ustr;
893
0
}
894
895
// XServiceInfo
896
sal_Bool OServiceManager::supportsService(const OUString& ServiceName)
897
0
{
898
0
    return cppu::supportsService(this, ServiceName);
899
0
}
900
901
// XServiceInfo
902
Sequence< OUString > OServiceManager::getSupportedServiceNames()
903
0
{
904
0
    return { u"com.sun.star.lang.MultiServiceFactory"_ustr, u"com.sun.star.lang.ServiceManager"_ustr };
905
0
}
906
907
908
Sequence< Reference< XInterface > > OServiceManager::queryServiceFactories(
909
    const OUString& aServiceName, Reference< XComponentContext > const & )
910
0
{
911
0
    Sequence< Reference< XInterface > > ret;
912
913
0
    MutexGuard aGuard( m_aMutex );
914
0
    ::std::pair<
915
0
          HashMultimap_OWString_Interface::iterator,
916
0
          HashMultimap_OWString_Interface::iterator> p(
917
0
              m_ServiceMap.equal_range( aServiceName ) );
918
919
0
    if (p.first == p.second) // no factories
920
0
    {
921
        // no service found, look for an implementation
922
0
        HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.find( aServiceName );
923
0
        if( aIt != m_ImplementationNameMap.end() )
924
0
        {
925
0
            Reference< XInterface > const & x = aIt->second;
926
            // an implementation found
927
0
            ret = Sequence< Reference< XInterface > >( &x, 1 );
928
0
        }
929
0
    }
930
0
    else
931
0
    {
932
0
        ::std::vector< Reference< XInterface > > vec;
933
0
        vec.reserve( 4 );
934
0
        while (p.first != p.second)
935
0
        {
936
0
            vec.push_back( p.first->second );
937
0
            ++p.first;
938
0
        }
939
0
        ret = Sequence< Reference< XInterface > >( vec.data(), vec.size() );
940
0
    }
941
942
0
    return ret;
943
0
}
944
945
// XContentEnumerationAccess
946
Reference<XEnumeration > OServiceManager::createContentEnumeration(
947
    const OUString& aServiceName )
948
0
{
949
0
    check_undisposed();
950
0
    Sequence< Reference< XInterface > > factories(
951
0
        OServiceManager::queryServiceFactories( aServiceName, m_xContext ) );
952
0
    if (factories.hasElements())
953
0
        return new ServiceEnumeration_Impl( factories );
954
0
    else
955
0
        return Reference< XEnumeration >();
956
0
}
957
958
// XEnumeration
959
Reference<XEnumeration > OServiceManager::createEnumeration()
960
0
{
961
0
    check_undisposed();
962
0
    MutexGuard aGuard( m_aMutex );
963
0
    return new ImplementationEnumeration_Impl( m_ImplementationMap );
964
0
}
965
966
// XElementAccess
967
Type OServiceManager::getElementType()
968
0
{
969
0
    check_undisposed();
970
0
    return cppu::UnoType<XInterface>::get();
971
0
}
972
973
// XElementAccess
974
sal_Bool OServiceManager::hasElements()
975
0
{
976
0
    check_undisposed();
977
0
    MutexGuard aGuard( m_aMutex );
978
0
    return !m_ImplementationMap.empty();
979
0
}
980
981
// XSet
982
sal_Bool OServiceManager::has( const Any & Element )
983
0
{
984
0
    check_undisposed();
985
0
    if( Element.getValueTypeClass() == TypeClass_INTERFACE )
986
0
    {
987
0
        Reference<XInterface > xEle( Element, UNO_QUERY_THROW );
988
0
        MutexGuard aGuard( m_aMutex );
989
0
        return m_ImplementationMap.find( xEle ) !=
990
0
            m_ImplementationMap.end();
991
0
    }
992
0
    else if (auto implName = o3tl::tryAccess<OUString>(Element))
993
0
    {
994
0
        MutexGuard aGuard( m_aMutex );
995
0
        return m_ImplementationNameMap.find( *implName ) !=
996
0
            m_ImplementationNameMap.end();
997
0
    }
998
0
    return false;
999
0
}
1000
1001
// XSet
1002
void OServiceManager::insert( const Any & Element )
1003
0
{
1004
0
    check_undisposed();
1005
0
    if( Element.getValueTypeClass() != TypeClass_INTERFACE )
1006
0
    {
1007
0
        throw IllegalArgumentException(
1008
0
            "exception interface, got " + Element.getValueTypeName(),
1009
0
            Reference< XInterface >(), 0 );
1010
0
    }
1011
0
    Reference<XInterface > xEle( Element, UNO_QUERY_THROW );
1012
1013
0
    {
1014
0
    MutexGuard aGuard( m_aMutex );
1015
0
    HashSet_Ref::iterator aIt = m_ImplementationMap.find( xEle );
1016
0
    if( aIt != m_ImplementationMap.end() )
1017
0
    {
1018
0
        throw ElementExistException( u"element already exists!"_ustr );
1019
0
    }
1020
1021
    // put into the implementation hashmap
1022
0
    m_ImplementationMap.insert( xEle );
1023
1024
    // put into the implementation name hashmap
1025
0
    Reference<XServiceInfo > xInfo( Reference<XServiceInfo >::query( xEle ) );
1026
0
    if( xInfo.is() )
1027
0
    {
1028
0
        OUString aImplName = xInfo->getImplementationName();
1029
0
        if( !aImplName.isEmpty() )
1030
0
            m_ImplementationNameMap[ aImplName ] = xEle;
1031
1032
        //put into the service map
1033
0
        const Sequence< OUString > aServiceNames = xInfo->getSupportedServiceNames();
1034
0
        for( const OUString& rServiceName : aServiceNames )
1035
0
        {
1036
0
            m_ServiceMap.emplace(
1037
0
                rServiceName, *o3tl::doAccess<Reference<XInterface>>(Element) );
1038
0
        }
1039
0
    }
1040
0
    }
1041
    // add the disposing listener to the factory
1042
0
    Reference<XComponent > xComp( Reference<XComponent >::query( xEle ) );
1043
0
    if( xComp.is() )
1044
0
        xComp->addEventListener( getFactoryListener() );
1045
0
}
1046
1047
// helper function
1048
bool OServiceManager::haveFactoryWithThisImplementation(const OUString& aImplName)
1049
0
{
1050
0
    return m_ImplementationNameMap.contains(aImplName);
1051
0
}
1052
1053
// XSet
1054
void OServiceManager::remove( const Any & Element )
1055
0
{
1056
0
    if (is_disposed())
1057
0
        return;
1058
1059
0
    Reference<XInterface > xEle;
1060
0
    if (Element.getValueTypeClass() == TypeClass_INTERFACE)
1061
0
    {
1062
0
        xEle.set( Element, UNO_QUERY_THROW );
1063
0
    }
1064
0
    else if (auto implName = o3tl::tryAccess<OUString>(Element))
1065
0
    {
1066
0
        MutexGuard aGuard( m_aMutex );
1067
0
        HashMap_OWString_Interface::const_iterator const iFind(
1068
0
            m_ImplementationNameMap.find( *implName ) );
1069
0
        if (iFind == m_ImplementationNameMap.end())
1070
0
        {
1071
0
            throw NoSuchElementException(
1072
0
                "element is not in: " + *implName,
1073
0
                getXWeak() );
1074
0
        }
1075
0
        xEle = iFind->second;
1076
0
    }
1077
0
    else
1078
0
    {
1079
0
        throw IllegalArgumentException(
1080
0
            "expected interface or string, got " + Element.getValueTypeName(),
1081
0
            Reference< XInterface >(), 0 );
1082
0
    }
1083
1084
    // remove the disposing listener from the factory
1085
0
    Reference<XComponent > xComp( Reference<XComponent >::query( xEle ) );
1086
0
    if( xComp.is() )
1087
0
        xComp->removeEventListener( getFactoryListener() );
1088
1089
0
    MutexGuard aGuard( m_aMutex );
1090
0
    HashSet_Ref::iterator aIt = m_ImplementationMap.find( xEle );
1091
0
    if( aIt == m_ImplementationMap.end() )
1092
0
    {
1093
0
        throw NoSuchElementException(
1094
0
            u"element not found"_ustr,
1095
0
            getXWeak() );
1096
0
    }
1097
    //First remove all factories which have been loaded by ORegistryServiceManager.
1098
0
    m_SetLoadedFactories.erase( *aIt);
1099
    //Remove from the implementation map. It contains all factories of m_SetLoadedFactories
1100
    //which have been added directly through XSet, that is not via ORegistryServiceManager
1101
0
    m_ImplementationMap.erase( aIt );
1102
1103
    // remove from the implementation name hashmap
1104
0
    Reference<XServiceInfo > xInfo( Reference<XServiceInfo >::query( xEle ) );
1105
0
    if( xInfo.is() )
1106
0
    {
1107
0
        OUString aImplName = xInfo->getImplementationName();
1108
0
        if( !aImplName.isEmpty() )
1109
0
            m_ImplementationNameMap.erase( aImplName );
1110
0
    }
1111
1112
    //remove from the service map
1113
0
    Reference<XServiceInfo > xSF( Reference<XServiceInfo >::query( xEle ) );
1114
0
    if( !xSF.is() )
1115
0
        return;
1116
1117
0
    const Sequence< OUString > aServiceNames = xSF->getSupportedServiceNames();
1118
0
    for( const OUString& rServiceName : aServiceNames )
1119
0
    {
1120
0
        std::pair<HashMultimap_OWString_Interface::iterator, HashMultimap_OWString_Interface::iterator> p =
1121
0
            m_ServiceMap.equal_range( rServiceName );
1122
1123
0
        while( p.first != p.second )
1124
0
        {
1125
0
            if( xEle == (*p.first).second )
1126
0
            {
1127
0
                m_ServiceMap.erase( p.first );
1128
0
                break;
1129
0
            }
1130
0
            ++p.first;
1131
0
        }
1132
0
    }
1133
0
}
1134
1135
/*****************************************************************************
1136
    class ORegistryServiceManager
1137
*****************************************************************************/
1138
class ORegistryServiceManager : public OServiceManager
1139
{
1140
public:
1141
    explicit ORegistryServiceManager( Reference< XComponentContext > const & xContext );
1142
1143
    // XInitialization
1144
    void SAL_CALL initialize(const Sequence< Any >& Arguments) override;
1145
1146
    // XServiceInfo
1147
    OUString SAL_CALL getImplementationName() override
1148
0
        { return u"com.sun.star.comp.stoc.ORegistryServiceManager"_ustr; }
1149
1150
    Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
1151
1152
    // XMultiServiceFactory
1153
    Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
1154
1155
    // XContentEnumerationAccess
1156
    //Sequence< OUString >          getAvailableServiceNames() throw( (Exception) );
1157
    Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) override;
1158
1159
    // XComponent
1160
    void SAL_CALL dispose() override;
1161
1162
    // OServiceManager
1163
    Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
1164
    Any SAL_CALL getPropertyValue(const OUString& PropertyName) override;
1165
1166
protected:
1167
    //OServiceManager
1168
    Sequence< Reference< XInterface > > queryServiceFactories(
1169
        const OUString& aServiceName, Reference< XComponentContext > const & xContext ) override;
1170
private:
1171
    Reference<XRegistryKey >        getRootKey();
1172
    Reference<XInterface > loadWithImplementationName(
1173
        const OUString & rImplName, Reference< XComponentContext > const & xContext );
1174
    Sequence<OUString>          getFromServiceName(std::u16string_view serviceName) const;
1175
    Reference<XInterface > loadWithServiceName(
1176
        std::u16string_view rImplName, Reference< XComponentContext > const & xContext );
1177
    void                        fillAllNamesFromRegistry( HashSet_OWString & );
1178
1179
    bool                    m_searchedRegistry;
1180
    Reference<XSimpleRegistry > m_xRegistry;    // readonly property Registry
1181
    Reference<XRegistryKey >    m_xRootKey;
1182
1183
#if OSL_DEBUG_LEVEL > 0
1184
    bool m_init;
1185
#endif
1186
};
1187
1188
/**
1189
 * Create a ServiceManager
1190
 */
1191
ORegistryServiceManager::ORegistryServiceManager( Reference< XComponentContext > const & xContext )
1192
0
    : OServiceManager( xContext )
1193
0
    , m_searchedRegistry(false)
1194
#if OSL_DEBUG_LEVEL > 0
1195
    , m_init( false )
1196
#endif
1197
0
{
1198
0
}
1199
1200
// XComponent
1201
void ORegistryServiceManager::dispose()
1202
0
{
1203
0
    if (rBHelper.bDisposed || rBHelper.bInDispose)
1204
0
        return;
1205
0
    OServiceManager::dispose();
1206
    // dispose
1207
0
    MutexGuard aGuard( m_aMutex );
1208
    // erase all members
1209
0
    m_xRegistry.clear();
1210
0
    m_xRootKey.clear();
1211
0
}
1212
1213
/**
1214
 * Return the root key of the registry. The Default registry service is ordered
1215
 * if no registry is set.
1216
 */
1217
//Reference<XServiceProvider > create_DefaultRegistry_ServiceProvider();
1218
1219
Reference<XRegistryKey > ORegistryServiceManager::getRootKey()
1220
0
{
1221
0
    if( !m_xRootKey.is() )
1222
0
    {
1223
0
        MutexGuard aGuard( m_aMutex );
1224
        //  DefaultRegistry suchen !!!!
1225
0
        if( !m_xRegistry.is() && !m_searchedRegistry )
1226
0
        {
1227
            // NB. we only search this once
1228
0
            m_searchedRegistry = true;
1229
1230
0
            m_xRegistry.set(
1231
0
                createInstanceWithContext(
1232
0
                    u"com.sun.star.registry.DefaultRegistry"_ustr,
1233
0
                    m_xContext ),
1234
0
                UNO_QUERY );
1235
0
        }
1236
0
        if( m_xRegistry.is() && !m_xRootKey.is() )
1237
0
            m_xRootKey = m_xRegistry->getRootKey();
1238
0
    }
1239
1240
0
    return m_xRootKey;
1241
0
}
1242
1243
/**
1244
 * Create a service provider from the registry with an implementation name
1245
 */
1246
Reference<XInterface > ORegistryServiceManager::loadWithImplementationName(
1247
    const OUString& name, Reference< XComponentContext > const & xContext )
1248
0
{
1249
0
    Reference<XInterface > ret;
1250
1251
0
    Reference<XRegistryKey > xRootKey = getRootKey();
1252
0
    if( !xRootKey.is() )
1253
0
        return ret;
1254
1255
0
    try
1256
0
    {
1257
0
        OUString implementationName = "/IMPLEMENTATIONS/" + name;
1258
0
        Reference<XRegistryKey > xImpKey = m_xRootKey->openKey(implementationName);
1259
1260
0
        if( xImpKey.is() )
1261
0
        {
1262
0
            Reference< lang::XMultiServiceFactory > xMgr;
1263
0
            if (xContext.is())
1264
0
                xMgr.set( xContext->getServiceManager(), UNO_QUERY_THROW );
1265
0
            else
1266
0
                xMgr.set( this );
1267
0
            ret = createSingleRegistryFactory( xMgr, name, xImpKey );
1268
0
            insert( Any( ret ) );
1269
            // Remember this factory as loaded in contrast to inserted ( XSet::insert)
1270
            // factories. Those loaded factories in this set are candidates for being
1271
            // released on an unloading notification.
1272
0
            m_SetLoadedFactories.insert( ret);
1273
0
        }
1274
0
    }
1275
0
    catch (InvalidRegistryException &)
1276
0
    {
1277
0
    }
1278
1279
0
    return ret;
1280
0
}
1281
1282
/**
1283
 * Return all implementation out of the registry.
1284
 */
1285
Sequence<OUString> ORegistryServiceManager::getFromServiceName(
1286
    std::u16string_view serviceName ) const
1287
0
{
1288
0
    OUString buf = OUString::Concat("/SERVICES/") + serviceName;
1289
0
    return retrieveAsciiValueList( m_xRegistry, buf );
1290
0
}
1291
1292
/**
1293
 * Create a service provider from the registry
1294
 */
1295
Reference<XInterface > ORegistryServiceManager::loadWithServiceName(
1296
    std::u16string_view serviceName, Reference< XComponentContext > const & xContext )
1297
0
{
1298
0
    const Sequence<OUString> implEntries = getFromServiceName( serviceName );
1299
0
    for (const auto& rEntry : implEntries)
1300
0
    {
1301
0
        Reference< XInterface > x( loadWithImplementationName( rEntry, xContext ) );
1302
0
        if (x.is())
1303
0
            return x;
1304
0
    }
1305
1306
0
    return Reference<XInterface >();
1307
0
}
1308
1309
/**
1310
 * Return a sequence of all service names from the registry.
1311
 */
1312
void ORegistryServiceManager::fillAllNamesFromRegistry( HashSet_OWString & rSet )
1313
0
{
1314
0
    Reference<XRegistryKey > xRootKey = getRootKey();
1315
0
    if( !xRootKey.is() )
1316
0
        return;
1317
1318
0
    try
1319
0
    {
1320
0
        Reference<XRegistryKey > xServicesKey = xRootKey->openKey( u"SERVICES"_ustr );
1321
        // root + /Services + /
1322
0
        if( xServicesKey.is() )
1323
0
        {
1324
0
            sal_Int32 nPrefix = xServicesKey->getKeyName().getLength() +1;
1325
0
            const Sequence<Reference<XRegistryKey > > aKeys = xServicesKey->openKeys();
1326
0
            std::transform(aKeys.begin(), aKeys.end(), std::inserter(rSet, rSet.end()),
1327
0
                [nPrefix](const Reference<XRegistryKey>& rKey) -> OUString {
1328
0
                    return rKey->getKeyName().copy( nPrefix ); });
1329
0
        }
1330
0
    }
1331
0
    catch (InvalidRegistryException &)
1332
0
    {
1333
0
    }
1334
0
}
1335
1336
// XInitialization
1337
void ORegistryServiceManager::initialize(const Sequence< Any >& Arguments)
1338
0
{
1339
0
    check_undisposed();
1340
0
    MutexGuard aGuard( m_aMutex );
1341
0
    if (Arguments.hasElements())
1342
0
    {
1343
0
        m_xRootKey.clear();
1344
0
        Arguments[ 0 ] >>= m_xRegistry;
1345
0
    }
1346
#if OSL_DEBUG_LEVEL > 0
1347
    // to find all bootstrapping processes to be fixed...
1348
    OSL_ENSURE( !m_init, "### second init of service manager instance!" );
1349
    m_init = true;
1350
#endif
1351
0
}
1352
1353
// XMultiServiceFactory, XContentEnumeration
1354
Sequence< OUString > ORegistryServiceManager::getAvailableServiceNames()
1355
0
{
1356
0
    check_undisposed();
1357
0
    MutexGuard aGuard( m_aMutex );
1358
    // all names
1359
0
    HashSet_OWString aNameSet;
1360
1361
    // all names from the registry
1362
0
    fillAllNamesFromRegistry( aNameSet );
1363
1364
0
    return OServiceManager::getUniqueAvailableServiceNames( aNameSet );
1365
0
}
1366
1367
// XServiceInfo
1368
Sequence< OUString > ORegistryServiceManager::getSupportedServiceNames()
1369
0
{
1370
0
    return { u"com.sun.star.lang.MultiServiceFactory"_ustr, u"com.sun.star.lang.RegistryServiceManager"_ustr };
1371
0
}
1372
1373
1374
// OServiceManager
1375
Sequence< Reference< XInterface > > ORegistryServiceManager::queryServiceFactories(
1376
    const OUString& aServiceName, Reference< XComponentContext > const & xContext )
1377
0
{
1378
0
    Sequence< Reference< XInterface > > ret(
1379
0
        OServiceManager::queryServiceFactories( aServiceName, xContext ) );
1380
0
    if (ret.hasElements())
1381
0
    {
1382
0
        return ret;
1383
0
    }
1384
0
    else
1385
0
    {
1386
0
        MutexGuard aGuard( m_aMutex );
1387
0
        Reference< XInterface > x( loadWithServiceName( aServiceName, xContext ) );
1388
0
        if (! x.is())
1389
0
            x = loadWithImplementationName( aServiceName, xContext );
1390
0
        return Sequence< Reference< XInterface > >( &x, 1 );
1391
0
    }
1392
0
}
1393
1394
// XContentEnumerationAccess
1395
Reference<XEnumeration > ORegistryServiceManager::createContentEnumeration(
1396
    const OUString& aServiceName )
1397
0
{
1398
0
    check_undisposed();
1399
0
    MutexGuard aGuard(m_aMutex);
1400
    // get all implementation names registered under this service name from the registry
1401
0
    const Sequence<OUString> aImpls = getFromServiceName( aServiceName );
1402
    // load and insert all factories specified by the registry
1403
0
    for( const OUString& aImplName : aImpls )
1404
0
    {
1405
0
        if ( !haveFactoryWithThisImplementation(aImplName) )
1406
0
        {
1407
0
            loadWithImplementationName( aImplName, m_xContext );
1408
0
        }
1409
0
    }
1410
    // call the superclass to enumerate all contents
1411
0
    return OServiceManager::createContentEnumeration( aServiceName );
1412
0
}
1413
1414
// OServiceManager
1415
Reference<XPropertySetInfo > ORegistryServiceManager::getPropertySetInfo()
1416
0
{
1417
0
    check_undisposed();
1418
0
    if (! m_xPropertyInfo.is())
1419
0
    {
1420
0
        Sequence< beans::Property > seq{
1421
0
            beans::Property(u"DefaultContext"_ustr, -1, cppu::UnoType<decltype(m_xContext)>::get(), 0),
1422
0
            beans::Property(u"Registry"_ustr, -1, cppu::UnoType<decltype(m_xRegistry)>::get(),
1423
0
                            beans::PropertyAttribute::READONLY)
1424
0
        };
1425
0
        Reference< beans::XPropertySetInfo > xInfo( new PropertySetInfo_Impl( seq ) );
1426
1427
0
        MutexGuard aGuard( m_aMutex );
1428
0
        if (! m_xPropertyInfo.is())
1429
0
        {
1430
0
            m_xPropertyInfo = std::move(xInfo);
1431
0
        }
1432
0
    }
1433
0
    return m_xPropertyInfo;
1434
0
}
1435
1436
Any ORegistryServiceManager::getPropertyValue(const OUString& PropertyName)
1437
0
{
1438
0
    check_undisposed();
1439
0
    if ( PropertyName == "Registry" )
1440
0
    {
1441
0
        MutexGuard aGuard( m_aMutex );
1442
0
        if( m_xRegistry.is() )
1443
0
            return Any( m_xRegistry );
1444
0
        else
1445
0
            return Any();
1446
0
    }
1447
0
    return OServiceManager::getPropertyValue( PropertyName );
1448
0
}
1449
1450
} // namespace
1451
1452
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1453
com_sun_star_comp_stoc_OServiceManager_get_implementation(
1454
    css::uno::XComponentContext *context,
1455
    css::uno::Sequence<css::uno::Any> const &)
1456
0
{
1457
0
    return cppu::acquire(new OServiceManager(context));
1458
0
}
1459
1460
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1461
com_sun_star_comp_stoc_ORegistryServiceManager_get_implementation(
1462
    css::uno::XComponentContext *context,
1463
    css::uno::Sequence<css::uno::Any> const &)
1464
0
{
1465
0
    return cppu::acquire(new ORegistryServiceManager(context));
1466
0
}
1467
1468
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1469
com_sun_star_comp_stoc_OServiceManagerWrapper_get_implementation(
1470
    css::uno::XComponentContext *context,
1471
    css::uno::Sequence<css::uno::Any> const &)
1472
0
{
1473
0
    return cppu::acquire(new OServiceManagerWrapper(context));
1474
0
}
1475
1476
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */