Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/stoc/source/inspect/introspection.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 <cassert>
23
#include <cstddef>
24
#include <limits>
25
#include <map>
26
#include <memory>
27
#include <mutex>
28
#include <set>
29
30
#include <o3tl/any.hxx>
31
#include <o3tl/string_view.hxx>
32
#include <osl/diagnose.h>
33
#include <sal/log.hxx>
34
#include <cppuhelper/basemutex.hxx>
35
#include <cppuhelper/compbase.hxx>
36
#include <cppuhelper/queryinterface.hxx>
37
#include <cppuhelper/weak.hxx>
38
#include <cppuhelper/implbase.hxx>
39
#include <cppuhelper/supportsservice.hxx>
40
#include <comphelper/sequence.hxx>
41
#include <salhelper/simplereferenceobject.hxx>
42
43
#include <com/sun/star/lang/NoSuchMethodException.hpp>
44
#include <com/sun/star/lang/XServiceInfo.hpp>
45
#include <com/sun/star/lang/XUnoTunnel.hpp>
46
#include <com/sun/star/reflection/XIdlReflection.hpp>
47
#include <com/sun/star/reflection/XIdlClass.hpp>
48
#include <com/sun/star/reflection/XIdlField2.hpp>
49
#include <com/sun/star/reflection/theCoreReflection.hpp>
50
#include <com/sun/star/beans/UnknownPropertyException.hpp>
51
#include <com/sun/star/beans/Property.hpp>
52
#include <com/sun/star/beans/XPropertySet.hpp>
53
#include <com/sun/star/beans/XFastPropertySet.hpp>
54
#include <com/sun/star/beans/XIntrospection.hpp>
55
#include <com/sun/star/beans/XIntrospectionAccess.hpp>
56
#include <com/sun/star/beans/XMaterialHolder.hpp>
57
#include <com/sun/star/beans/XExactName.hpp>
58
#include <com/sun/star/beans/PropertyAttribute.hpp>
59
#include <com/sun/star/beans/PropertyConcept.hpp>
60
#include <com/sun/star/beans/MethodConcept.hpp>
61
#include <com/sun/star/container/XNameContainer.hpp>
62
#include <com/sun/star/container/XIndexContainer.hpp>
63
#include <com/sun/star/container/XEnumerationAccess.hpp>
64
65
#include <rtl/ref.hxx>
66
#include <rtl/ustrbuf.hxx>
67
#include <unordered_map>
68
#include <utility>
69
70
using namespace css::uno;
71
using namespace css::lang;
72
using namespace css::reflection;
73
using namespace css::container;
74
using namespace css::beans;
75
using namespace css::beans::PropertyAttribute;
76
using namespace css::beans::PropertyConcept;
77
using namespace css::beans::MethodConcept;
78
using namespace cppu;
79
using namespace osl;
80
81
namespace
82
{
83
84
typedef WeakImplHelper< XIntrospectionAccess, XMaterialHolder, XExactName,
85
                        XPropertySet, XFastPropertySet, XPropertySetInfo,
86
                        XNameContainer, XIndexContainer, XEnumerationAccess,
87
                        XIdlArray, XUnoTunnel > IntrospectionAccessHelper;
88
89
90
// Special value for Method-Concept, to be able to mark "normal" functions
91
750
#define  MethodConcept_NORMAL_IMPL        0x80000000
92
93
94
// Method to assert, if a class is derived from another class
95
bool isDerivedFrom( const Reference<XIdlClass>& xToTestClass, const Reference<XIdlClass>& xDerivedFromClass )
96
0
{
97
0
    const Sequence< Reference<XIdlClass> > aClassesSeq = xToTestClass->getSuperclasses();
98
99
0
    return std::any_of(aClassesSeq.begin(), aClassesSeq.end(),
100
0
        [&xDerivedFromClass](const Reference<XIdlClass>& rxClass) {
101
0
            return xDerivedFromClass->equals( rxClass )
102
0
                || isDerivedFrom( rxClass, xDerivedFromClass );
103
0
        });
104
0
}
105
106
107
// *** Classification of Properties (no enum, to be able to use Sequence) ***
108
// Properties from a PropertySet-Interface
109
0
#define MAP_PROPERTY_SET    0
110
// Properties from Fields
111
0
#define MAP_FIELD            1
112
// Properties that get described with get/set methods
113
90
#define MAP_GETSET            2
114
// Properties with only a set method
115
0
#define MAP_SETONLY            3
116
117
118
// Increments by which the size of sequences get adjusted
119
75
#define ARRAY_SIZE_STEP        20
120
121
122
//*** IntrospectionAccessStatic_Impl ***
123
124
// Equals to the old IntrospectionAccessImpl, forms now a static
125
// part of the new Instance-related ImplIntrospectionAccess
126
127
// Hashtable for the search of names
128
typedef std::unordered_map
129
<
130
    OUString,
131
    sal_Int32
132
>
133
IntrospectionNameMap;
134
135
136
// Hashtable to assign exact names to the Lower-Case
137
// converted names, for the support of XExactName
138
typedef std::unordered_map
139
<
140
    OUString,
141
    OUString
142
>
143
LowerToExactNameMap;
144
145
146
class IntrospectionAccessStatic_Impl: public salhelper::SimpleReferenceObject
147
{
148
    friend class Implementation;
149
    friend class ImplIntrospectionAccess;
150
151
    // Holding CoreReflection
152
    Reference< XIdlReflection > mxCoreReflection;
153
154
    // InterfaceSequences, to save additional information in a property
155
    // for example the Field at MAP_FIELD, the get/set-Methods at MAP_GETSET, et cetera
156
    std::vector< Reference<XInterface> > aInterfaceSeq1;
157
    std::vector< Reference<XInterface> > aInterfaceSeq2;
158
159
    // Hashtables for names
160
    IntrospectionNameMap maPropertyNameMap;
161
    IntrospectionNameMap maMethodNameMap;
162
    LowerToExactNameMap  maLowerToExactNameMap;
163
164
    // Vector of all Properties, also for delivering from getProperties()
165
    std::vector<Property> maAllPropertySeq;
166
167
    // Mapping of properties to Access-Types
168
    std::vector<sal_Int16> maMapTypeSeq;
169
170
    // Classification of found methods
171
    std::vector<sal_Int32> maPropertyConceptSeq;
172
173
    // Number of Properties
174
    sal_Int32 mnPropCount;
175
176
    // Number of Properties, which are assigned to particular concepts
177
    //sal_Int32 mnDangerousPropCount;
178
    sal_Int32 mnPropertySetPropCount;
179
    sal_Int32 mnAttributePropCount;
180
    sal_Int32 mnMethodPropCount;
181
182
    // Flags which indicate if various interfaces are present
183
    bool mbFastPropSet;
184
    bool mbElementAccess;
185
    bool mbNameAccess;
186
    bool mbNameReplace;
187
    bool mbNameContainer;
188
    bool mbIndexAccess;
189
    bool mbIndexReplace;
190
    bool mbIndexContainer;
191
    bool mbEnumerationAccess;
192
    bool mbIdlArray;
193
    bool mbUnoTunnel;
194
195
    // Original handles of FastPropertySets
196
    std::unique_ptr<sal_Int32[]> mpOrgPropertyHandleArray;
197
198
    // MethodSequence, that accepts all methods
199
    std::vector< Reference<XIdlMethod> > maAllMethodSeq;
200
201
    // Classification of found methods
202
    std::vector<sal_Int32> maMethodConceptSeq;
203
204
    // Number of methods
205
    sal_Int32 mnMethCount;
206
207
    // Sequence of Listener, that can be registered
208
    std::vector< Type > maSupportedListenerSeq;
209
210
    // Helper-methods for adjusting sizes of Sequences
211
    void checkPropertyArraysSize( sal_Int32 iNextIndex );
212
    static void checkInterfaceArraySize( std::vector< Reference<XInterface> >& rSeq, std::vector<Reference<XInterface>>& rInterfaceVec,
213
        sal_Int32 iNextIndex );
214
215
public:
216
    explicit IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ );
217
    sal_Int32 getPropertyIndex( const OUString& aPropertyName ) const;
218
    sal_Int32 getMethodIndex( const OUString& aMethodName ) const;
219
220
    // Methods of XIntrospectionAccess (OLD, now only Impl)
221
    void setPropertyValue(const Any& obj, const OUString& aPropertyName, const Any& aValue) const;
222
//    void setPropertyValue(Any& obj, const OUString& aPropertyName, const Any& aValue) const;
223
    Any getPropertyValue(const Any& obj, const OUString& aPropertyName) const;
224
    void setPropertyValueByIndex(const Any& obj, sal_Int32 nIndex, const Any& aValue) const;
225
//    void setPropertyValueByIndex(Any& obj, sal_Int32 nIndex, const Any& aValue) const;
226
    Any getPropertyValueByIndex(const Any& obj, sal_Int32 nIndex) const;
227
228
0
    const std::vector<Property>& getProperties() const              { return maAllPropertySeq; }
229
15
    const std::vector< Reference<XIdlMethod> >& getMethods() const  { return maAllMethodSeq; }
230
0
    const std::vector< Type >& getSupportedListeners() const        { return maSupportedListenerSeq; }
231
0
    const std::vector<sal_Int32>& getPropertyConcepts() const       { return maPropertyConceptSeq; }
232
0
    const std::vector<sal_Int32>& getMethodConcepts() const         { return maMethodConceptSeq; }
233
};
234
235
236
// Ctor
237
IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ )
238
15
    : mxCoreReflection( xCoreReflection_ )
239
15
{
240
15
    aInterfaceSeq1.resize( ARRAY_SIZE_STEP );
241
15
    aInterfaceSeq2.resize( ARRAY_SIZE_STEP );
242
243
    // Property-Data
244
15
    maAllPropertySeq.resize( ARRAY_SIZE_STEP );
245
15
    maMapTypeSeq.resize( ARRAY_SIZE_STEP );
246
15
    maPropertyConceptSeq.resize( ARRAY_SIZE_STEP );
247
248
15
    mbFastPropSet = false;
249
15
    mbElementAccess = false;
250
15
    mbNameAccess = false;
251
15
    mbNameReplace = false;
252
15
    mbNameContainer = false;
253
15
    mbIndexAccess = false;
254
15
    mbIndexReplace = false;
255
15
    mbIndexContainer = false;
256
15
    mbEnumerationAccess = false;
257
15
    mbIdlArray = false;
258
15
    mbUnoTunnel = false;
259
260
15
    mpOrgPropertyHandleArray = nullptr;
261
262
15
    mnPropCount = 0;
263
    //mnDangerousPropCount = 0;
264
15
    mnPropertySetPropCount = 0;
265
15
    mnAttributePropCount = 0;
266
15
    mnMethodPropCount = 0;
267
268
    // Method-Data
269
15
    mnMethCount = 0;
270
15
}
271
272
sal_Int32 IntrospectionAccessStatic_Impl::getPropertyIndex( const OUString& aPropertyName ) const
273
0
{
274
0
    auto aIt = maPropertyNameMap.find(aPropertyName);
275
0
    if (aIt != maPropertyNameMap.end())
276
0
        return aIt->second;
277
278
0
    return -1;
279
0
}
280
281
sal_Int32 IntrospectionAccessStatic_Impl::getMethodIndex( const OUString& aMethodName ) const
282
0
{
283
0
    auto aIt = maMethodNameMap.find(aMethodName);
284
0
    if (aIt != maMethodNameMap.end())
285
0
    {
286
0
        return aIt->second;
287
0
    }
288
289
    // #95159 Check if full qualified name matches
290
0
    sal_Int32 nSearchFrom = aMethodName.getLength();
291
0
    while( true )
292
0
    {
293
        // Strategy: Search back until the first '_' is found
294
0
        sal_Int32 nFound = aMethodName.lastIndexOf( '_', nSearchFrom );
295
0
        if( nFound == -1 )
296
0
            break;
297
298
0
        OUString aPureMethodName = aMethodName.copy( nFound + 1 );
299
300
0
        aIt = maMethodNameMap.find( aPureMethodName );
301
0
        if (aIt != maMethodNameMap.end())
302
0
        {
303
            // Check if it can be a type?
304
            // Problem: Does not work if package names contain _ ?!
305
0
            OUString aStr = aMethodName.copy( 0, nFound );
306
0
            OUString aTypeName = aStr.replace( '_', '.' );
307
0
            Reference< XIdlClass > xClass = mxCoreReflection->forName( aTypeName );
308
0
            if( xClass.is() )
309
0
            {
310
                // If this is a valid class it could be the right method
311
312
                // Could be the right method, type has to be checked
313
0
                const sal_Int32 iHashResult = aIt->second;
314
315
0
                const Reference<XIdlMethod> xMethod = maAllMethodSeq[iHashResult];
316
317
0
                Reference< XIdlClass > xMethClass = xMethod->getDeclaringClass();
318
0
                if( xClass->equals( xMethClass ) )
319
0
                {
320
0
                    return iHashResult;
321
0
                }
322
0
                else
323
0
                {
324
                    // Could also be another method with the same name
325
                    // Iterate over all methods
326
0
                    size_t nLen = maAllMethodSeq.size();
327
0
                    for (size_t i = 0; i < nLen; ++i)
328
0
                    {
329
0
                        const Reference<XIdlMethod> xMethod2 = maAllMethodSeq[ i ];
330
0
                        if( xMethod2->getName() == aPureMethodName )
331
0
                        {
332
0
                            Reference< XIdlClass > xMethClass2 = xMethod2->getDeclaringClass();
333
334
0
                            if( xClass->equals( xMethClass2 ) )
335
0
                            {
336
0
                                return i;
337
0
                            }
338
0
                        }
339
0
                    }
340
0
                }
341
0
            }
342
0
        }
343
344
0
        nSearchFrom = nFound - 1;
345
0
        if( nSearchFrom < 0 )
346
0
            break;
347
0
    }
348
0
    return -1;
349
0
}
350
351
void IntrospectionAccessStatic_Impl::setPropertyValue( const Any& obj, const OUString& aPropertyName, const Any& aValue ) const
352
//void IntrospectionAccessStatic_Impl::setPropertyValue( Any& obj, const OUString& aPropertyName, const Any& aValue ) const
353
0
{
354
0
    sal_Int32 i = getPropertyIndex( aPropertyName );
355
0
    if( i == -1 )
356
0
        throw UnknownPropertyException(aPropertyName);
357
0
    setPropertyValueByIndex( obj, i, aValue );
358
0
}
359
360
void IntrospectionAccessStatic_Impl::setPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
361
//void IntrospectionAccessStatic_Impl::setPropertyValueByIndex( Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
362
0
{
363
    // Is the passed object something that fits?
364
0
    Reference<XInterface> xInterface;
365
0
    if( !(obj >>= xInterface) )
366
0
    {
367
0
        TypeClass eObjType = obj.getValueTypeClass();
368
0
        if( nSequenceIndex >= mnPropCount)
369
0
            throw IllegalArgumentException(
370
0
                "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), index > propertyCount, " +
371
0
                OUString::number(nSequenceIndex) + " > " + OUString::number(mnPropCount),
372
0
                Reference<XInterface>(), 0);
373
0
        if( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION )
374
0
            throw IllegalArgumentException(
375
0
                "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), expected struct or exception, got" +
376
0
                obj.getValueTypeName(), Reference<XInterface>(), 0);
377
0
    }
378
379
    // Test flags
380
0
    if( (maAllPropertySeq[ nSequenceIndex ].Attributes & READONLY) != 0 )
381
0
    {
382
0
        throw UnknownPropertyException(
383
0
            "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), property at index " + OUString::number(nSequenceIndex) + " is readonly");
384
0
    }
385
386
0
    switch( maMapTypeSeq[ nSequenceIndex ] )
387
0
    {
388
0
        case MAP_PROPERTY_SET:
389
0
        {
390
            // Get Property
391
0
            const Property& rProp = maAllPropertySeq[ nSequenceIndex ];
392
393
            // Convert Interface-Parameter to the correct type
394
0
            bool bUseCopy = false;
395
0
            Any aRealValue;
396
397
0
            if( auto valInterface = o3tl::tryAccess<
398
0
                    css::uno::Reference<css::uno::XInterface>>(aValue) )
399
0
            {
400
0
                Type aPropType = rProp.Type;
401
0
                OUString aTypeName( aPropType.getTypeName() );
402
0
                Reference< XIdlClass > xPropClass = mxCoreReflection->forName( aTypeName );
403
                //Reference<XIdlClass> xPropClass = rProp.Type;
404
0
                if( xPropClass.is() && xPropClass->getTypeClass() == TypeClass_INTERFACE )
405
0
                {
406
0
                    if( valInterface->is() )
407
0
                    {
408
                        //Any queryInterface( const Type& rType );
409
0
                        aRealValue = (*valInterface)->queryInterface( aPropType );
410
0
                        if( aRealValue.hasValue() )
411
0
                            bUseCopy = true;
412
0
                    }
413
0
                }
414
0
            }
415
416
            // Do we have a FastPropertySet and a valid Handle?
417
            // CAUTION: At this point we exploit that the PropertySet
418
            // gets queried at the beginning of the Introspection-Process.
419
0
            sal_Int32 nOrgHandle;
420
0
            if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
421
0
            {
422
                // Retrieve PropertySet-Interface
423
0
                Reference<XFastPropertySet> xFastPropSet =
424
0
                    Reference<XFastPropertySet>::query( xInterface );
425
0
                if( xFastPropSet.is() )
426
0
                {
427
0
                    xFastPropSet->setFastPropertyValue( nOrgHandle, bUseCopy ? aRealValue : aValue );
428
0
                }
429
0
                else
430
0
                {
431
                    // throw UnknownPropertyException
432
0
                }
433
0
            }
434
            // else take the normal one
435
0
            else
436
0
            {
437
                // Retrieve PropertySet-Interface
438
0
                Reference<XPropertySet> xPropSet =
439
0
                    Reference<XPropertySet>::query( xInterface );
440
0
                if( xPropSet.is() )
441
0
                {
442
0
                    xPropSet->setPropertyValue( rProp.Name, bUseCopy ? aRealValue : aValue );
443
0
                }
444
0
                else
445
0
                {
446
                    // throw UnknownPropertyException
447
0
                }
448
0
            }
449
0
        }
450
0
        break;
451
452
0
        case MAP_FIELD:
453
0
        {
454
0
            Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
455
0
            Reference<XIdlField2> xField2(xField, UNO_QUERY);
456
0
            if( xField2.is() )
457
0
            {
458
0
                xField2->set( const_cast<Any&>(obj), aValue );
459
                // IllegalArgumentException
460
                // NullPointerException
461
0
            } else
462
0
            if( xField.is() )
463
0
            {
464
0
                xField->set( obj, aValue );
465
                // IllegalArgumentException
466
                // NullPointerException
467
0
            }
468
0
            else
469
0
            {
470
                // throw IllegalArgumentException();
471
0
            }
472
0
        }
473
0
        break;
474
475
0
        case MAP_GETSET:
476
0
        case MAP_SETONLY:
477
0
        {
478
            // Fetch set method
479
0
            Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq2[ nSequenceIndex ].get());
480
0
            if( xMethod.is() )
481
0
            {
482
0
                Sequence<Any> args( 1 );
483
0
                args.getArray()[0] = aValue;
484
0
                xMethod->invoke( obj, args );
485
0
            }
486
0
            else
487
0
            {
488
                // throw IllegalArgumentException();
489
0
            }
490
0
        }
491
0
        break;
492
0
    }
493
0
}
494
495
Any IntrospectionAccessStatic_Impl::getPropertyValue( const Any& obj, const OUString& aPropertyName ) const
496
0
{
497
0
    sal_Int32 i = getPropertyIndex( aPropertyName );
498
0
    if( i != -1 )
499
0
        return getPropertyValueByIndex( obj, i );
500
501
0
    throw UnknownPropertyException(aPropertyName);
502
0
}
503
504
Any IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex) const
505
0
{
506
0
    Any aRet;
507
508
    // Is there anything suitable in the passed object?
509
0
    Reference<XInterface> xInterface;
510
0
    if( !(obj >>= xInterface) )
511
0
    {
512
0
        TypeClass eObjType = obj.getValueTypeClass();
513
0
        if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) )
514
0
        {
515
            // throw IllegalArgumentException();
516
0
            return aRet;
517
0
        }
518
0
    }
519
520
0
    switch( maMapTypeSeq[ nSequenceIndex ] )
521
0
    {
522
0
        case MAP_PROPERTY_SET:
523
0
        {
524
            // Acquire property
525
0
            const Property& rProp = maAllPropertySeq[ nSequenceIndex ];
526
527
            // Do we have a FastPropertySet and a valid handle?
528
            // NOTE: At this point is exploited that the PropertySet
529
            // is queried at the beginning of introspection process.
530
0
            sal_Int32 nOrgHandle;
531
0
            if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
532
0
            {
533
                // Fetch the PropertySet interface
534
0
                Reference<XFastPropertySet> xFastPropSet =
535
0
                    Reference<XFastPropertySet>::query( xInterface );
536
0
                if( xFastPropSet.is() )
537
0
                {
538
0
                    aRet = xFastPropSet->getFastPropertyValue( nOrgHandle);
539
0
                }
540
0
                else
541
0
                {
542
                    // throw UnknownPropertyException
543
0
                    return aRet;
544
0
                }
545
0
            }
546
            // Otherwise use the normal one
547
0
            else
548
0
            {
549
                // Fetch the PropertySet interface
550
0
                Reference<XPropertySet> xPropSet =
551
0
                    Reference<XPropertySet>::query( xInterface );
552
0
                if( xPropSet.is() )
553
0
                {
554
0
                    aRet = xPropSet->getPropertyValue( rProp.Name );
555
0
                }
556
0
                else
557
0
                {
558
                    // throw UnknownPropertyException
559
0
                    return aRet;
560
0
                }
561
0
            }
562
0
        }
563
0
        break;
564
565
0
        case MAP_FIELD:
566
0
        {
567
0
            Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
568
0
            if( xField.is() )
569
0
            {
570
0
                aRet = xField->get( obj );
571
                // IllegalArgumentException
572
                // NullPointerException
573
0
            }
574
0
            else
575
0
            {
576
                // throw IllegalArgumentException();
577
0
                return aRet;
578
0
            }
579
0
        }
580
0
        break;
581
582
0
        case MAP_GETSET:
583
0
        {
584
            // Fetch get method
585
0
            Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq1[ nSequenceIndex ].get());
586
0
            if( xMethod.is() )
587
0
            {
588
0
                Sequence<Any> args;
589
0
                aRet = xMethod->invoke( obj, args );
590
0
            }
591
0
            else
592
0
            {
593
                // throw IllegalArgumentException();
594
0
                return aRet;
595
0
            }
596
0
        }
597
0
        break;
598
599
0
        case MAP_SETONLY:
600
            // Get method does not exist
601
            // throw WriteOnlyPropertyException();
602
0
            return aRet;
603
0
    }
604
0
    return aRet;
605
0
}
606
607
608
// Helper method to adjust the size of the vectors
609
void IntrospectionAccessStatic_Impl::checkPropertyArraysSize( sal_Int32 iNextIndex )
610
90
{
611
90
    sal_Int32 nLen = static_cast<sal_Int32>(maAllPropertySeq.size());
612
90
    if( iNextIndex >= nLen )
613
0
    {
614
0
        maAllPropertySeq.resize( nLen + ARRAY_SIZE_STEP );
615
0
        maMapTypeSeq.resize( nLen + ARRAY_SIZE_STEP );
616
0
        maPropertyConceptSeq.resize( nLen + ARRAY_SIZE_STEP );
617
0
    }
618
90
}
619
620
void IntrospectionAccessStatic_Impl::checkInterfaceArraySize( std::vector< Reference<XInterface> >& rSeq,
621
    std::vector<Reference<XInterface>>& rInterfaceVec, sal_Int32 iNextIndex )
622
105
{
623
105
    sal_Int32 nLen = rSeq.size();
624
105
    if( iNextIndex >= nLen )
625
0
    {
626
        // Synchronize new size with ARRAY_SIZE_STEP
627
0
        sal_Int32 nMissingSize = iNextIndex - nLen + 1;
628
0
        sal_Int32 nSteps = nMissingSize / ARRAY_SIZE_STEP + 1;
629
0
        sal_Int32 nNewSize = nLen + nSteps * ARRAY_SIZE_STEP;
630
631
0
        rSeq.resize( nNewSize );
632
0
        rInterfaceVec = rSeq;
633
0
    }
634
105
}
635
636
637
//*** ImplIntrospectionAccess ***
638
639
640
// New Impl class as part of the introspection conversion to instance-bound
641
// Introspection with property access via XPropertySet. The old class
642
// ImplIntrospectionAccess lives on as IntrospectionAccessStatic_Impl
643
class ImplIntrospectionAccess : public IntrospectionAccessHelper
644
{
645
    friend class Implementation;
646
647
    // Object under examination
648
    Any maInspectedObject;
649
650
    // As interface
651
    Reference<XInterface> mxIface;
652
653
    // Static introspection data
654
    rtl::Reference< IntrospectionAccessStatic_Impl > mpStaticImpl;
655
656
    // Last Sequence that came with getProperties (optimization)
657
    Sequence<Property> maLastPropertySeq;
658
    sal_Int32 mnLastPropertyConcept;
659
660
    // Last Sequence that came with getMethods (optimization)
661
    Sequence<Reference<XIdlMethod> > maLastMethodSeq;
662
    sal_Int32 mnLastMethodConcept;
663
664
    // Guards the caching of queried interfaces
665
    std::mutex m_aMutex;
666
667
    // Original interfaces of the objects
668
    Reference<XElementAccess>       mxObjElementAccess;
669
    Reference<XNameContainer>       mxObjNameContainer;
670
    Reference<XNameReplace>         mxObjNameReplace;
671
    Reference<XNameAccess>          mxObjNameAccess;
672
    Reference<XIndexContainer>      mxObjIndexContainer;
673
    Reference<XIndexReplace>        mxObjIndexReplace;
674
    Reference<XIndexAccess>         mxObjIndexAccess;
675
    Reference<XEnumerationAccess>   mxObjEnumerationAccess;
676
    Reference<XIdlArray>            mxObjIdlArray;
677
678
    Reference<XElementAccess>       getXElementAccess();
679
    Reference<XNameContainer>       getXNameContainer();
680
    Reference<XNameReplace>         getXNameReplace();
681
    Reference<XNameAccess>          getXNameAccess();
682
    Reference<XIndexContainer>      getXIndexContainer();
683
    Reference<XIndexReplace>        getXIndexReplace();
684
    Reference<XIndexAccess>         getXIndexAccess();
685
    Reference<XEnumerationAccess>   getXEnumerationAccess();
686
    Reference<XIdlArray>            getXIdlArray();
687
688
    void cacheXNameContainer(const std::unique_lock<std::mutex>& rGuard);
689
    void cacheXIndexContainer(const std::unique_lock<std::mutex>& rGuard);
690
691
public:
692
    ImplIntrospectionAccess( Any obj, rtl::Reference< IntrospectionAccessStatic_Impl >  pStaticImpl_ );
693
694
    // Methods from XIntrospectionAccess
695
    virtual sal_Int32 SAL_CALL getSuppliedMethodConcepts() override;
696
    virtual sal_Int32 SAL_CALL getSuppliedPropertyConcepts() override;
697
    virtual Property SAL_CALL getProperty(const OUString& Name, sal_Int32 PropertyConcepts) override;
698
    virtual sal_Bool SAL_CALL hasProperty(const OUString& Name, sal_Int32 PropertyConcepts) override;
699
    virtual Sequence< Property > SAL_CALL getProperties(sal_Int32 PropertyConcepts) override;
700
    virtual Reference<XIdlMethod> SAL_CALL getMethod(const OUString& Name, sal_Int32 MethodConcepts) override;
701
    virtual sal_Bool SAL_CALL hasMethod(const OUString& Name, sal_Int32 MethodConcepts) override;
702
    virtual Sequence< Reference<XIdlMethod> > SAL_CALL getMethods(sal_Int32 MethodConcepts) override;
703
    virtual Sequence< Type > SAL_CALL getSupportedListeners() override;
704
    using OWeakObject::queryAdapter;
705
    virtual Reference<XInterface> SAL_CALL queryAdapter( const Type& rType ) override;
706
707
    // Methods from XMaterialHolder
708
    virtual Any SAL_CALL getMaterial() override;
709
710
    // Methods from XExactName
711
    virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) override;
712
713
    // Methods from XInterface
714
    virtual Any SAL_CALL queryInterface( const Type& rType ) override;
715
15
    virtual void        SAL_CALL acquire() noexcept override { OWeakObject::acquire(); }
716
15
    virtual void        SAL_CALL release() noexcept override { OWeakObject::release(); }
717
718
    // Methods from XPropertySet
719
    virtual Reference<XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
720
    virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, const Any& aValue) override;
721
    virtual Any SAL_CALL getPropertyValue(const OUString& aPropertyName) override;
722
    virtual void SAL_CALL addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) override;
723
    virtual void SAL_CALL removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) override;
724
    virtual void SAL_CALL addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) override;
725
    virtual void SAL_CALL removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) override;
726
727
    // Methods from XFastPropertySet
728
    virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const Any& aValue) override;
729
    virtual Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override;
730
731
    // Methods from XPropertySetInfo
732
    virtual Sequence< Property > SAL_CALL getProperties() override;
733
    virtual Property SAL_CALL getPropertyByName(const OUString& Name) override;
734
    virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& Name) override;
735
736
    // Methods from XElementAccess
737
    virtual Type SAL_CALL getElementType() override;
738
    virtual sal_Bool SAL_CALL hasElements() override;
739
740
    // Methods from XNameAccess
741
    virtual Any SAL_CALL getByName(const OUString& Name) override;
742
    virtual Sequence< OUString > SAL_CALL getElementNames() override;
743
    virtual sal_Bool SAL_CALL hasByName(const OUString& Name) override;
744
745
    // Methods from XNameReplace
746
    virtual void SAL_CALL replaceByName(const OUString& Name, const Any& Element) override;
747
748
    // Methods from XNameContainer
749
    virtual void SAL_CALL insertByName(const OUString& Name, const Any& Element) override;
750
    virtual void SAL_CALL removeByName(const OUString& Name) override;
751
752
    // Methods from XIndexAccess
753
    virtual sal_Int32 SAL_CALL getCount() override;
754
    virtual Any SAL_CALL getByIndex(sal_Int32 Index) override;
755
756
    // Methods from XIndexReplace
757
    virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element) override;
758
759
    // Methods from XIndexContainer
760
    virtual void SAL_CALL insertByIndex(sal_Int32 Index, const Any& Element) override;
761
    virtual void SAL_CALL removeByIndex(sal_Int32 Index) override;
762
763
    // Methods from XEnumerationAccess
764
    virtual Reference<XEnumeration> SAL_CALL createEnumeration() override;
765
766
    // Methods from XIdlArray
767
    virtual void SAL_CALL realloc(Any& array, sal_Int32 length) override;
768
    virtual sal_Int32 SAL_CALL getLen(const Any& array) override;
769
    virtual Any SAL_CALL get(const Any& array, sal_Int32 index) override;
770
    virtual void SAL_CALL set(Any& array, sal_Int32 index, const Any& value) override;
771
772
    // Methods from XUnoTunnel
773
    virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier ) override;
774
};
775
776
ImplIntrospectionAccess::ImplIntrospectionAccess
777
    ( Any obj, rtl::Reference< IntrospectionAccessStatic_Impl >  pStaticImpl_ )
778
15
        : maInspectedObject(std::move( obj )), mpStaticImpl(std::move( pStaticImpl_ )) ,
779
15
          mnLastPropertyConcept(-1), mnLastMethodConcept(-1) //, maAdapter()
780
15
{
781
    // Save object as an interface if possible
782
15
    maInspectedObject >>= mxIface;
783
15
}
784
785
Reference<XElementAccess> ImplIntrospectionAccess::getXElementAccess()
786
0
{
787
0
    std::unique_lock aGuard( m_aMutex );
788
0
    if( !mxObjElementAccess.is() )
789
0
        mxObjElementAccess.set( mxIface, UNO_QUERY );
790
0
    return mxObjElementAccess;
791
0
}
792
793
void ImplIntrospectionAccess::cacheXNameContainer(const std::unique_lock<std::mutex>& /*rGuard*/)
794
0
{
795
0
    Reference<XNameContainer> xNameContainer;
796
0
    Reference<XNameReplace> xNameReplace;
797
0
    Reference<XNameAccess> xNameAccess;
798
0
    if (mpStaticImpl->mbNameContainer)
799
0
    {
800
0
        xNameContainer.set( mxIface, UNO_QUERY );
801
0
        xNameReplace = xNameContainer;
802
0
        xNameAccess = xNameContainer;
803
0
    }
804
0
    else if (mpStaticImpl->mbNameReplace)
805
0
    {
806
0
        xNameReplace.set( mxIface, UNO_QUERY );
807
0
        xNameAccess = xNameReplace;
808
0
    }
809
0
    else if (mpStaticImpl->mbNameAccess)
810
0
    {
811
0
        xNameAccess.set( mxIface, UNO_QUERY );
812
0
    }
813
814
0
    {
815
0
        if( !mxObjNameContainer.is() )
816
0
            mxObjNameContainer = std::move(xNameContainer);
817
0
        if( !mxObjNameReplace.is() )
818
0
            mxObjNameReplace = std::move(xNameReplace);
819
0
        if( !mxObjNameAccess.is() )
820
0
            mxObjNameAccess = std::move(xNameAccess);
821
0
    }
822
0
}
823
824
Reference<XNameContainer> ImplIntrospectionAccess::getXNameContainer()
825
0
{
826
0
    std::unique_lock aGuard( m_aMutex );
827
828
0
    if( !mxObjNameContainer.is() )
829
0
        cacheXNameContainer(aGuard);
830
831
0
    return mxObjNameContainer;
832
0
}
833
834
Reference<XNameReplace> ImplIntrospectionAccess::getXNameReplace()
835
0
{
836
0
    std::unique_lock aGuard( m_aMutex );
837
838
0
    if( !mxObjNameReplace.is() )
839
0
        cacheXNameContainer(aGuard);
840
841
0
    return mxObjNameReplace;
842
0
}
843
844
Reference<XNameAccess> ImplIntrospectionAccess::getXNameAccess()
845
0
{
846
0
    std::unique_lock aGuard( m_aMutex );
847
848
0
    if( !mxObjNameAccess.is() )
849
0
        cacheXNameContainer(aGuard);
850
851
0
    return mxObjNameAccess;
852
0
}
853
854
void ImplIntrospectionAccess::cacheXIndexContainer(const std::unique_lock<std::mutex>& /*rGuard*/)
855
0
{
856
0
    Reference<XIndexContainer> xIndexContainer;
857
0
    Reference<XIndexReplace> xIndexReplace;
858
0
    Reference<XIndexAccess> xIndexAccess;
859
0
    if (mpStaticImpl->mbIndexContainer)
860
0
    {
861
0
        xIndexContainer.set( mxIface, UNO_QUERY );
862
0
        xIndexReplace = xIndexContainer;
863
0
        xIndexAccess = xIndexContainer;
864
0
    }
865
0
    else if (mpStaticImpl->mbIndexReplace)
866
0
    {
867
0
        xIndexReplace.set( mxIface, UNO_QUERY );
868
0
        xIndexAccess = xIndexReplace;
869
0
    }
870
0
    else if (mpStaticImpl->mbIndexAccess)
871
0
    {
872
0
        xIndexAccess.set( mxIface, UNO_QUERY );
873
0
    }
874
875
0
    {
876
0
        if( !mxObjIndexContainer.is() )
877
0
            mxObjIndexContainer = std::move(xIndexContainer);
878
0
        if( !mxObjIndexReplace.is() )
879
0
            mxObjIndexReplace = std::move(xIndexReplace);
880
0
        if( !mxObjIndexAccess.is() )
881
0
            mxObjIndexAccess = std::move(xIndexAccess);
882
0
    }
883
0
}
884
885
Reference<XIndexContainer> ImplIntrospectionAccess::getXIndexContainer()
886
0
{
887
0
    std::unique_lock aGuard( m_aMutex );
888
889
0
    if( !mxObjIndexContainer.is() )
890
0
        cacheXIndexContainer(aGuard);
891
892
0
    return mxObjIndexContainer;
893
0
}
894
895
Reference<XIndexReplace> ImplIntrospectionAccess::getXIndexReplace()
896
0
{
897
0
    std::unique_lock aGuard( m_aMutex );
898
899
0
    if( !mxObjIndexReplace.is() )
900
0
        cacheXIndexContainer(aGuard);
901
902
0
    return mxObjIndexReplace;
903
0
}
904
905
Reference<XIndexAccess> ImplIntrospectionAccess::getXIndexAccess()
906
0
{
907
0
    std::unique_lock aGuard( m_aMutex );
908
909
0
    if( !mxObjIndexAccess.is() )
910
0
        cacheXIndexContainer(aGuard);
911
912
0
    return mxObjIndexAccess;
913
0
}
914
915
Reference<XEnumerationAccess> ImplIntrospectionAccess::getXEnumerationAccess()
916
0
{
917
0
    std::unique_lock aGuard( m_aMutex );
918
0
    if( !mxObjEnumerationAccess.is() )
919
0
        mxObjEnumerationAccess.set( mxIface, UNO_QUERY );
920
0
    return mxObjEnumerationAccess;
921
0
}
922
923
Reference<XIdlArray> ImplIntrospectionAccess::getXIdlArray()
924
0
{
925
0
    std::unique_lock aGuard( m_aMutex );
926
0
    if( !mxObjIdlArray.is() )
927
0
        mxObjIdlArray.set( mxIface, UNO_QUERY );
928
0
    return mxObjIdlArray;
929
0
}
930
931
// Methods from XInterface
932
Any SAL_CALL ImplIntrospectionAccess::queryInterface( const Type& rType )
933
0
{
934
0
    Any aRet( ::cppu::queryInterface(
935
0
        rType,
936
0
        static_cast< XIntrospectionAccess * >( this ),
937
0
        static_cast< XMaterialHolder * >( this ),
938
0
        static_cast< XExactName * >( this ),
939
0
        static_cast< XPropertySet * >( this ),
940
0
        static_cast< XFastPropertySet * >( this ),
941
0
        static_cast< XPropertySetInfo * >( this ) ) );
942
0
    if( !aRet.hasValue() )
943
0
        aRet = OWeakObject::queryInterface( rType );
944
945
0
    if( !aRet.hasValue() )
946
0
    {
947
        // Wrapper for the object interfaces
948
0
        ( mpStaticImpl->mbElementAccess && (aRet = ::cppu::queryInterface
949
0
                    ( rType, static_cast< XElementAccess* >( static_cast< XNameAccess* >( this ) ) ) ).hasValue() )
950
0
        || ( mpStaticImpl->mbNameAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() )
951
0
        || ( mpStaticImpl->mbNameReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XNameReplace* >( this ) ) ).hasValue() )
952
0
        || ( mpStaticImpl->mbNameContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() )
953
0
        || ( mpStaticImpl->mbIndexAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() )
954
0
        || ( mpStaticImpl->mbIndexReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexReplace* >( this ) ) ).hasValue() )
955
0
        || ( mpStaticImpl->mbIndexContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() )
956
0
        || ( mpStaticImpl->mbEnumerationAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() )
957
0
        || ( mpStaticImpl->mbIdlArray && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() )
958
0
        || ( mpStaticImpl->mbUnoTunnel && (aRet = ::cppu::queryInterface( rType, static_cast< XUnoTunnel* >( this ) ) ).hasValue() );
959
0
    }
960
0
    return aRet;
961
0
}
962
963
964
//*** Implementation of ImplIntrospectionAdapter ***
965
966
967
// Methods from XPropertySet
968
Reference<XPropertySetInfo> ImplIntrospectionAccess::getPropertySetInfo()
969
0
{
970
0
    return static_cast<XPropertySetInfo *>(this);
971
0
}
972
973
void ImplIntrospectionAccess::setPropertyValue(const OUString& aPropertyName, const Any& aValue)
974
0
{
975
0
    mpStaticImpl->setPropertyValue( maInspectedObject, aPropertyName, aValue );
976
0
}
977
978
Any ImplIntrospectionAccess::getPropertyValue(const OUString& aPropertyName)
979
0
{
980
0
    return mpStaticImpl->getPropertyValue( maInspectedObject, aPropertyName );
981
0
}
982
983
void ImplIntrospectionAccess::addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
984
0
{
985
0
    if( mxIface.is() )
986
0
    {
987
0
        Reference<XPropertySet> xPropSet =
988
0
            Reference<XPropertySet>::query( mxIface );
989
        //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
990
0
        if( xPropSet.is() )
991
0
            xPropSet->addPropertyChangeListener(aPropertyName, aListener);
992
0
    }
993
0
}
994
995
void ImplIntrospectionAccess::removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
996
0
{
997
0
    if( mxIface.is() )
998
0
    {
999
0
        Reference<XPropertySet> xPropSet =
1000
0
            Reference<XPropertySet>::query( mxIface );
1001
        //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1002
0
        if( xPropSet.is() )
1003
0
            xPropSet->removePropertyChangeListener(aPropertyName, aListener);
1004
0
    }
1005
0
}
1006
1007
void ImplIntrospectionAccess::addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1008
0
{
1009
0
    if( mxIface.is() )
1010
0
    {
1011
0
        Reference<XPropertySet> xPropSet =
1012
0
            Reference<XPropertySet>::query( mxIface );
1013
        //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1014
0
        if( xPropSet.is() )
1015
0
            xPropSet->addVetoableChangeListener(aPropertyName, aListener);
1016
0
    }
1017
0
}
1018
1019
void ImplIntrospectionAccess::removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1020
0
{
1021
0
    if( mxIface.is() )
1022
0
    {
1023
0
        Reference<XPropertySet> xPropSet =
1024
0
            Reference<XPropertySet>::query( mxIface );
1025
0
        if( xPropSet.is() )
1026
0
            xPropSet->removeVetoableChangeListener(aPropertyName, aListener);
1027
0
    }
1028
0
}
1029
1030
1031
// Methods from XFastPropertySet
1032
void ImplIntrospectionAccess::setFastPropertyValue(sal_Int32, const Any&)
1033
0
{
1034
0
}
1035
1036
Any ImplIntrospectionAccess::getFastPropertyValue(sal_Int32)
1037
0
{
1038
0
    return Any();
1039
0
}
1040
1041
// Methods from XPropertySetInfo
1042
Sequence< Property > ImplIntrospectionAccess::getProperties()
1043
0
{
1044
0
    return comphelper::containerToSequence(mpStaticImpl->getProperties());
1045
0
}
1046
1047
Property ImplIntrospectionAccess::getPropertyByName(const OUString& Name)
1048
0
{
1049
0
    return getProperty( Name, PropertyConcept::ALL );
1050
0
}
1051
1052
sal_Bool ImplIntrospectionAccess::hasPropertyByName(const OUString& Name)
1053
0
{
1054
0
    return hasProperty( Name, PropertyConcept::ALL );
1055
0
}
1056
1057
// Methods from XElementAccess
1058
Type ImplIntrospectionAccess::getElementType()
1059
0
{
1060
0
    return getXElementAccess()->getElementType();
1061
0
}
1062
1063
sal_Bool ImplIntrospectionAccess::hasElements()
1064
0
{
1065
0
    return getXElementAccess()->hasElements();
1066
0
}
1067
1068
// Methods from XNameAccess
1069
Any ImplIntrospectionAccess::getByName(const OUString& Name)
1070
0
{
1071
0
    return getXNameAccess()->getByName( Name );
1072
0
}
1073
1074
Sequence< OUString > ImplIntrospectionAccess::getElementNames()
1075
0
{
1076
0
    return getXNameAccess()->getElementNames();
1077
0
}
1078
1079
sal_Bool ImplIntrospectionAccess::hasByName(const OUString& Name)
1080
0
{
1081
0
    return getXNameAccess()->hasByName( Name );
1082
0
}
1083
1084
// Methods from XNameContainer
1085
void ImplIntrospectionAccess::insertByName(const OUString& Name, const Any& Element)
1086
0
{
1087
0
    getXNameContainer()->insertByName( Name, Element );
1088
0
}
1089
1090
void ImplIntrospectionAccess::replaceByName(const OUString& Name, const Any& Element)
1091
0
{
1092
0
    getXNameReplace()->replaceByName( Name, Element );
1093
0
}
1094
1095
void ImplIntrospectionAccess::removeByName(const OUString& Name)
1096
0
{
1097
0
    getXNameContainer()->removeByName( Name );
1098
0
}
1099
1100
// Methods from XIndexAccess
1101
// Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const
1102
sal_Int32 ImplIntrospectionAccess::getCount()
1103
0
{
1104
0
    return getXIndexAccess()->getCount();
1105
0
}
1106
1107
Any ImplIntrospectionAccess::getByIndex(sal_Int32 Index)
1108
0
{
1109
0
    return getXIndexAccess()->getByIndex( Index );
1110
0
}
1111
1112
// Methods from XIndexContainer
1113
void ImplIntrospectionAccess::insertByIndex(sal_Int32 Index, const Any& Element)
1114
0
{
1115
0
    getXIndexContainer()->insertByIndex( Index, Element );
1116
0
}
1117
1118
void ImplIntrospectionAccess::replaceByIndex(sal_Int32 Index, const Any& Element)
1119
0
{
1120
0
    getXIndexReplace()->replaceByIndex( Index, Element );
1121
0
}
1122
1123
void ImplIntrospectionAccess::removeByIndex(sal_Int32 Index)
1124
0
{
1125
0
    getXIndexContainer()->removeByIndex( Index );
1126
0
}
1127
1128
// Methods from XEnumerationAccess
1129
// Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const;
1130
Reference<XEnumeration> ImplIntrospectionAccess::createEnumeration()
1131
0
{
1132
0
    return getXEnumerationAccess()->createEnumeration();
1133
0
}
1134
1135
// Methods from XIdlArray
1136
void ImplIntrospectionAccess::realloc(Any& array, sal_Int32 length)
1137
0
{
1138
0
    getXIdlArray()->realloc( array, length );
1139
0
}
1140
1141
sal_Int32 ImplIntrospectionAccess::getLen(const Any& array)
1142
0
{
1143
0
    return getXIdlArray()->getLen( array );
1144
0
}
1145
1146
Any ImplIntrospectionAccess::get(const Any& array, sal_Int32 index)
1147
0
{
1148
0
    return getXIdlArray()->get( array, index );
1149
0
}
1150
1151
void ImplIntrospectionAccess::set(Any& array, sal_Int32 index, const Any& value)
1152
0
{
1153
0
    getXIdlArray()->set( array, index, value );
1154
0
}
1155
1156
// Methods from XUnoTunnel
1157
sal_Int64 ImplIntrospectionAccess::getSomething( const Sequence< sal_Int8 >& aIdentifier )
1158
0
{
1159
0
    if (Reference<XUnoTunnel> xUnoTunnel{ mxIface, css::uno::UNO_QUERY })
1160
0
        return xUnoTunnel->getSomething(aIdentifier);
1161
0
    return 0;
1162
0
}
1163
1164
1165
//*** Implementation of ImplIntrospectionAccess ***
1166
1167
// Methods from XIntrospectionAccess
1168
sal_Int32 ImplIntrospectionAccess::getSuppliedMethodConcepts()
1169
0
{
1170
0
    return    MethodConcept::DANGEROUS |
1171
0
            PROPERTY |
1172
0
            LISTENER |
1173
0
            ENUMERATION |
1174
0
            NAMECONTAINER |
1175
0
            INDEXCONTAINER;
1176
0
}
1177
1178
sal_Int32 ImplIntrospectionAccess::getSuppliedPropertyConcepts()
1179
0
{
1180
0
    return    PropertyConcept::DANGEROUS |
1181
0
            PROPERTYSET |
1182
0
            ATTRIBUTES |
1183
0
            METHODS;
1184
0
}
1185
1186
Property ImplIntrospectionAccess::getProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1187
0
{
1188
0
    Property aRet;
1189
0
    sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1190
0
    bool bFound = false;
1191
0
    if( i != -1 )
1192
0
    {
1193
0
        sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1194
0
        if( (PropertyConcepts & nConcept) != 0 )
1195
0
        {
1196
0
            aRet = mpStaticImpl->getProperties()[ i ];
1197
0
            bFound = true;
1198
0
        }
1199
0
    }
1200
0
    if( !bFound )
1201
0
        throw NoSuchElementException(Name);
1202
0
    return aRet;
1203
0
}
1204
1205
sal_Bool ImplIntrospectionAccess::hasProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1206
0
{
1207
0
    sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1208
0
    bool bRet = false;
1209
0
    if( i != -1 )
1210
0
    {
1211
0
        sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1212
0
        if( (PropertyConcepts & nConcept) != 0 )
1213
0
            bRet = true;
1214
0
    }
1215
0
    return bRet;
1216
0
}
1217
1218
Sequence< Property > ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts)
1219
0
{
1220
    // If all supported concepts are required, simply pass through the sequence
1221
0
    sal_Int32 nAllSupportedMask =   PROPERTYSET |
1222
0
                                    ATTRIBUTES |
1223
0
                                    METHODS;
1224
0
    if( ( PropertyConcepts & nAllSupportedMask ) == nAllSupportedMask )
1225
0
    {
1226
0
        return comphelper::containerToSequence(mpStaticImpl->getProperties());
1227
0
    }
1228
1229
    // Same sequence as last time?
1230
0
    if( mnLastPropertyConcept == PropertyConcepts )
1231
0
    {
1232
0
        return maLastPropertySeq;
1233
0
    }
1234
1235
    // Number of properties to be delivered
1236
0
    sal_Int32 nCount = 0;
1237
1238
    // There are currently no DANGEROUS properties
1239
    // if( PropertyConcepts & DANGEROUS )
1240
    //    nCount += mpStaticImpl->mnDangerousPropCount;
1241
0
    if( PropertyConcepts & PROPERTYSET )
1242
0
        nCount += mpStaticImpl->mnPropertySetPropCount;
1243
0
    if( PropertyConcepts & ATTRIBUTES )
1244
0
        nCount += mpStaticImpl->mnAttributePropCount;
1245
0
    if( PropertyConcepts & METHODS )
1246
0
        nCount += mpStaticImpl->mnMethodPropCount;
1247
1248
    // Realloc sequence according to the required number
1249
0
    maLastPropertySeq.realloc( nCount );
1250
0
    Property* pDestProps = maLastPropertySeq.getArray();
1251
1252
    // Go through all the properties and apply according to the concept
1253
0
    const std::vector<Property>&  rPropSeq = mpStaticImpl->getProperties();
1254
0
    const std::vector<sal_Int32>& rConcepts = mpStaticImpl->getPropertyConcepts();
1255
0
    sal_Int32 nLen = static_cast<sal_Int32>(rPropSeq.size());
1256
1257
0
    sal_Int32 iDest = 0;
1258
0
    for( sal_Int32 i = 0 ; i < nLen ; i++ )
1259
0
    {
1260
0
        sal_Int32 nConcept = rConcepts[ i ];
1261
0
        if( nConcept & PropertyConcepts )
1262
0
            pDestProps[ iDest++ ] = rPropSeq[ i ];
1263
0
    }
1264
1265
    // Remember PropertyConcept representing maLastPropertySeq
1266
0
    mnLastPropertyConcept = PropertyConcepts;
1267
1268
    // Supply assembled Sequence
1269
0
    return maLastPropertySeq;
1270
0
}
1271
1272
Reference<XIdlMethod> ImplIntrospectionAccess::getMethod(const OUString& Name, sal_Int32 MethodConcepts)
1273
0
{
1274
0
    Reference<XIdlMethod> xRet;
1275
0
    sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1276
0
    if( i != -1 )
1277
0
    {
1278
1279
0
        sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1280
0
        if( (MethodConcepts & nConcept) != 0 )
1281
0
        {
1282
0
            xRet = mpStaticImpl->getMethods()[i];
1283
0
        }
1284
0
    }
1285
0
    if( !xRet.is() )
1286
0
        throw NoSuchMethodException(Name);
1287
0
    return xRet;
1288
0
}
1289
1290
sal_Bool ImplIntrospectionAccess::hasMethod(const OUString& Name, sal_Int32 MethodConcepts)
1291
0
{
1292
0
    sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1293
0
    bool bRet = false;
1294
0
    if( i != -1 )
1295
0
    {
1296
0
        sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1297
0
        if( (MethodConcepts & nConcept) != 0 )
1298
0
            bRet = true;
1299
0
    }
1300
0
    return bRet;
1301
0
}
1302
1303
Sequence< Reference<XIdlMethod> > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts)
1304
15
{
1305
    // If all supported concepts are required, simply pass through the sequence
1306
15
    sal_Int32 nAllSupportedMask =   MethodConcept::DANGEROUS |
1307
15
                                    PROPERTY |
1308
15
                                    LISTENER |
1309
15
                                    ENUMERATION |
1310
15
                                    NAMECONTAINER |
1311
15
                                    INDEXCONTAINER |
1312
15
                                    MethodConcept_NORMAL_IMPL;
1313
15
    if( ( MethodConcepts & nAllSupportedMask ) == nAllSupportedMask )
1314
15
    {
1315
15
        return comphelper::containerToSequence(mpStaticImpl->getMethods());
1316
15
    }
1317
1318
    // Same sequence as last time?
1319
0
    if( mnLastMethodConcept == MethodConcepts )
1320
0
    {
1321
0
        return maLastMethodSeq;
1322
0
    }
1323
1324
    // Get method sequences
1325
0
    const std::vector< Reference<XIdlMethod> >& aMethodSeq = mpStaticImpl->getMethods();
1326
0
    sal_Int32 nLen = static_cast<sal_Int32>(aMethodSeq.size());
1327
1328
    // Realloc sequence according to the required number
1329
    // Unlike Properties, the number can not be determined by counters in
1330
    // inspect() beforehand, since methods can belong to several concepts
1331
0
    maLastMethodSeq.realloc( nLen );
1332
0
    Reference<XIdlMethod>* pDestMethods = maLastMethodSeq.getArray();
1333
1334
    // Go through all the methods and apply according to the concept
1335
0
    sal_Int32 iDest = 0;
1336
0
    for( sal_Int32 i = 0 ; i < nLen ; i++ )
1337
0
    {
1338
0
        sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1339
0
        if( nConcept & MethodConcepts )
1340
0
            pDestMethods[ iDest++ ] = aMethodSeq[ i ];
1341
0
    }
1342
1343
    // Bring to the correct length
1344
0
    maLastMethodSeq.realloc( iDest );
1345
1346
    // Remember MethodConcept representing maLastMethodSeq
1347
0
    mnLastMethodConcept = MethodConcepts;
1348
1349
    // Supply assembled Sequence
1350
0
    return maLastMethodSeq;
1351
0
}
1352
1353
Sequence< Type > ImplIntrospectionAccess::getSupportedListeners()
1354
0
{
1355
0
    return comphelper::containerToSequence(mpStaticImpl->getSupportedListeners());
1356
0
}
1357
1358
Reference<XInterface> SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type& rType )
1359
0
{
1360
0
    Reference<XInterface> xRet;
1361
0
    if(    rType == cppu::UnoType<XInterface>::get()
1362
0
        || rType == cppu::UnoType<XPropertySet>::get()
1363
0
        || rType == cppu::UnoType<XFastPropertySet>::get()
1364
0
        || rType == cppu::UnoType<XPropertySetInfo>::get()
1365
0
        || rType == cppu::UnoType<XElementAccess>::get()
1366
0
        || rType == cppu::UnoType<XNameAccess>::get()
1367
0
        || rType == cppu::UnoType<XNameReplace>::get()
1368
0
        || rType == cppu::UnoType<XNameContainer>::get()
1369
0
        || rType == cppu::UnoType<XIndexAccess>::get()
1370
0
        || rType == cppu::UnoType<XIndexReplace>::get()
1371
0
        || rType == cppu::UnoType<XIndexContainer>::get()
1372
0
        || rType == cppu::UnoType<XEnumerationAccess>::get()
1373
0
        || rType == cppu::UnoType<XIdlArray>::get()
1374
0
        || rType == cppu::UnoType<XUnoTunnel>::get() )
1375
0
    {
1376
0
        queryInterface( rType ) >>= xRet;
1377
0
    }
1378
0
    return xRet;
1379
0
}
1380
1381
// Methods from XMaterialHolder
1382
Any ImplIntrospectionAccess::getMaterial()
1383
0
{
1384
0
    return maInspectedObject;
1385
0
}
1386
1387
// Methods from XExactName
1388
OUString ImplIntrospectionAccess::getExactName( const OUString& rApproximateName )
1389
0
{
1390
0
    OUString aRetStr;
1391
0
    LowerToExactNameMap::iterator aIt =
1392
0
        mpStaticImpl->maLowerToExactNameMap.find( rApproximateName.toAsciiLowerCase() );
1393
0
    if (aIt != mpStaticImpl->maLowerToExactNameMap.end())
1394
0
        aRetStr = (*aIt).second;
1395
0
    return aRetStr;
1396
0
}
1397
1398
struct TypeKey {
1399
    TypeKey(
1400
        css::uno::Reference<css::beans::XPropertySetInfo> theProperties,
1401
        std::vector<css::uno::Type> const & theTypes):
1402
15
        properties(std::move(theProperties))
1403
15
    {
1404
        //TODO: Could even sort the types lexicographically first, to increase
1405
        // the chance of matches between different implementations' getTypes(),
1406
        // but the old scheme of using getImplementationId() would have missed
1407
        // those matches, too:
1408
15
        OUStringBuffer b(static_cast<int>(theTypes.size() * 64));
1409
115
        for (const css::uno::Type& rType : theTypes) {
1410
115
            b.append(rType.getTypeName()
1411
115
                + "*"); // arbitrary delimiter not used by type grammar
1412
115
        }
1413
15
        types = b.makeStringAndClear();
1414
15
    }
1415
1416
    css::uno::Reference<css::beans::XPropertySetInfo> properties;
1417
    OUString types;
1418
};
1419
1420
struct TypeKeyLess {
1421
45
    bool operator ()(TypeKey const & key1, TypeKey const & key2) const {
1422
45
        if (key1.properties.get() < key2.properties.get()) {
1423
0
            return true;
1424
0
        }
1425
45
        if (key1.properties.get() > key2.properties.get()) {
1426
0
            return false;
1427
0
        }
1428
45
        return key1.types < key2.types;
1429
45
    }
1430
};
1431
1432
template<typename Key, typename Less> class Cache {
1433
public:
1434
15
    rtl::Reference<IntrospectionAccessStatic_Impl> find(Key const & key) const {
1435
15
        typename Map::const_iterator i(map_.find(key));
1436
15
        if (i == map_.end()) {
1437
15
            return rtl::Reference<IntrospectionAccessStatic_Impl>();
1438
15
        } else {
1439
0
            if (i->second.hits < std::numeric_limits<unsigned>::max()) {
1440
0
                ++i->second.hits;
1441
0
            }
1442
0
            assert(i->second.access.is());
1443
0
            return i->second.access;
1444
0
        }
1445
15
    }
1446
1447
    void insert(
1448
        Key const & key,
1449
        rtl::Reference<IntrospectionAccessStatic_Impl> const & access)
1450
15
    {
1451
15
        assert(access.is());
1452
15
        typename Map::size_type const MAX = 100;
1453
15
        assert(map_.size() <= MAX);
1454
15
        if (map_.size() == MAX) {
1455
0
            typename Map::iterator del = std::min_element(map_.begin(), map_.end(),
1456
0
                [](const typename Map::value_type& a, const typename Map::value_type& b) {
1457
0
                    return a.second.hits < b.second.hits;
1458
0
                });
1459
0
            map_.erase(del);
1460
0
        }
1461
15
        bool ins = map_.emplace(key, Data(access)).second;
1462
15
        assert(ins); (void)ins;
1463
15
    }
1464
1465
0
    void clear() { map_.clear(); }
1466
1467
private:
1468
    struct Data {
1469
        explicit Data(
1470
            rtl::Reference<IntrospectionAccessStatic_Impl> theAccess):
1471
15
            access(std::move(theAccess)), hits(1)
1472
15
        {}
1473
1474
        rtl::Reference<IntrospectionAccessStatic_Impl> access;
1475
        mutable unsigned hits;
1476
    };
1477
1478
    typedef std::map<Key, Data, Less> Map;
1479
1480
    Map map_;
1481
};
1482
1483
typedef
1484
    cppu::WeakComponentImplHelper<
1485
        css::lang::XServiceInfo, css::beans::XIntrospection>
1486
    Implementation_Base;
1487
1488
class Implementation: private cppu::BaseMutex, public Implementation_Base {
1489
public:
1490
    explicit Implementation(
1491
        css::uno::Reference<css::uno::XComponentContext> const & context):
1492
5
        Implementation_Base(m_aMutex),
1493
5
        reflection_(css::reflection::theCoreReflection::get(context))
1494
5
    {}
1495
1496
private:
1497
0
    virtual void SAL_CALL disposing() override {
1498
0
        osl::MutexGuard g(m_aMutex);
1499
0
        reflection_.clear();
1500
0
        typeCache_.clear();
1501
0
    }
1502
1503
    virtual OUString SAL_CALL getImplementationName() override
1504
0
    { return u"com.sun.star.comp.stoc.Introspection"_ustr; }
1505
1506
    virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
1507
0
    { return cppu::supportsService(this, ServiceName); }
1508
1509
    virtual css::uno::Sequence<OUString> SAL_CALL
1510
    getSupportedServiceNames() override
1511
0
    {
1512
0
        Sequence<OUString> s { u"com.sun.star.beans.Introspection"_ustr };
1513
0
        return s;
1514
0
    }
1515
1516
    virtual css::uno::Reference<css::beans::XIntrospectionAccess> SAL_CALL
1517
    inspect(css::uno::Any const & aObject) override;
1518
1519
    css::uno::Reference<css::reflection::XIdlReflection> reflection_;
1520
    Cache<TypeKey, TypeKeyLess> typeCache_;
1521
};
1522
1523
css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
1524
    css::uno::Any const & aObject)
1525
15
{
1526
15
    css::uno::Reference<css::reflection::XIdlReflection> reflection;
1527
15
    {
1528
15
        osl::MutexGuard g(m_aMutex);
1529
15
        if (rBHelper.bDisposed || rBHelper.bInDispose) {
1530
0
            throw css::lang::DisposedException(
1531
0
                getImplementationName(), getXWeak());
1532
0
        }
1533
15
        reflection = reflection_;
1534
15
    }
1535
0
    css::uno::Any aToInspectObj;
1536
15
    css::uno::Type t;
1537
15
    if (aObject >>= t) {
1538
0
        css::uno::Reference<css::reflection::XIdlClass> c(
1539
0
            reflection->forName(t.getTypeName()));
1540
0
        if (!c.is()) {
1541
0
            SAL_WARN("stoc", "cannot reflect type " << t.getTypeName());
1542
0
            return css::uno::Reference<css::beans::XIntrospectionAccess>();
1543
0
        }
1544
0
        aToInspectObj <<= c;
1545
15
    } else {
1546
15
        aToInspectObj = aObject;
1547
15
    }
1548
1549
    // Examine object
1550
15
    TypeClass eType = aToInspectObj.getValueTypeClass();
1551
15
    if( eType != TypeClass_INTERFACE && eType != TypeClass_STRUCT  && eType != TypeClass_EXCEPTION )
1552
0
        return css::uno::Reference<css::beans::XIntrospectionAccess>();
1553
1554
15
    if( auto x = o3tl::tryAccess<Reference<XInterface>>(aToInspectObj) )
1555
15
    {
1556
15
        if( !x->is() )
1557
0
            return css::uno::Reference<css::beans::XIntrospectionAccess>();
1558
15
    }
1559
1560
    // Pointer to possibly needed new IntrospectionAccessStatic_Impl instance
1561
15
    rtl::Reference< IntrospectionAccessStatic_Impl > pAccess;
1562
1563
    // Check: Is a matching access object already cached?
1564
15
    std::vector< Reference<XIdlClass> >    SupportedClassSeq;
1565
15
    std::vector< Type >                    SupportedTypesSeq;
1566
15
    Reference<XTypeProvider>               xTypeProvider;
1567
15
    Reference<XPropertySetInfo>            xPropSetInfo;
1568
15
    Reference<XPropertySet>                xPropSet;
1569
1570
    // Look for interfaces XTypeProvider and PropertySet
1571
15
    if( eType == TypeClass_INTERFACE )
1572
15
    {
1573
15
        xTypeProvider.set( aToInspectObj, UNO_QUERY );
1574
15
        if( xTypeProvider.is() )
1575
15
        {
1576
15
            SupportedTypesSeq = comphelper::sequenceToContainer<std::vector<Type>>(xTypeProvider->getTypes());
1577
15
        } else {
1578
0
            SAL_WARN(
1579
0
                "stoc",
1580
0
                "object of type \"" << aToInspectObj.getValueTypeName()
1581
0
                    << "\" lacks XTypeProvider");
1582
0
            SupportedTypesSeq = { aToInspectObj.getValueType() };
1583
0
        }
1584
        // Now try to get the PropertySetInfo
1585
15
        xPropSet.set( aToInspectObj, UNO_QUERY );
1586
15
        if( xPropSet.is() )
1587
0
            xPropSetInfo = xPropSet->getPropertySetInfo();
1588
1589
15
    } else {
1590
0
        SupportedTypesSeq = { aToInspectObj.getValueType() };
1591
0
    }
1592
1593
15
    {
1594
15
        osl::MutexGuard g(m_aMutex);
1595
15
        if (rBHelper.bDisposed || rBHelper.bInDispose) {
1596
0
            throw css::lang::DisposedException(
1597
0
                getImplementationName(), getXWeak());
1598
0
        }
1599
15
        TypeKey key(xPropSetInfo, SupportedTypesSeq);
1600
15
        pAccess = typeCache_.find(key);
1601
15
        if (pAccess.is()) {
1602
0
            return new ImplIntrospectionAccess(aToInspectObj, pAccess);
1603
0
        }
1604
15
        pAccess = new IntrospectionAccessStatic_Impl(reflection);
1605
15
        typeCache_.insert(key, pAccess);
1606
15
    }
1607
1608
    // No access cached -> create new
1609
0
    std::vector<Property>& rAllPropArray = pAccess->maAllPropertySeq;
1610
15
    std::vector<Reference<XInterface>>& rInterfaces1 = pAccess->aInterfaceSeq1;
1611
15
    std::vector<Reference<XInterface>>& rInterfaces2 = pAccess->aInterfaceSeq2;
1612
15
    std::vector<sal_Int16>& rMapTypeArray = pAccess->maMapTypeSeq;
1613
15
    std::vector<sal_Int32>& rPropertyConceptArray = pAccess->maPropertyConceptSeq;
1614
1615
    // References to important data from pAccess
1616
15
    sal_Int32& rPropCount = pAccess->mnPropCount;
1617
15
    IntrospectionNameMap& rPropNameMap = pAccess->maPropertyNameMap;
1618
15
    IntrospectionNameMap& rMethodNameMap = pAccess->maMethodNameMap;
1619
15
    LowerToExactNameMap& rLowerToExactNameMap = pAccess->maLowerToExactNameMap;
1620
1621
1622
    //*** Perform analysis ***
1623
1624
15
    if( eType == TypeClass_INTERFACE )
1625
15
    {
1626
15
        size_t nTypeCount = SupportedTypesSeq.size();
1627
15
        if( nTypeCount )
1628
15
        {
1629
15
            SupportedClassSeq.resize( nTypeCount );
1630
1631
130
            for( size_t i = 0 ; i < nTypeCount ; i++ )
1632
115
                SupportedClassSeq[i] = reflection->forName( SupportedTypesSeq[i].getTypeName() );
1633
15
        }
1634
1635
        // First look for particular interfaces that are of particular
1636
        // importance to the introspection
1637
1638
        // Is XPropertySet present?
1639
15
        if( xPropSet.is() && xPropSetInfo.is() )
1640
0
        {
1641
            // Is there also a FastPropertySet?
1642
0
            Reference<XFastPropertySet> xDummy( aToInspectObj, UNO_QUERY );
1643
0
            bool bFast = pAccess->mbFastPropSet = xDummy.is();
1644
1645
0
            Sequence<Property> aPropSeq = xPropSetInfo->getProperties();
1646
0
            sal_Int32 nLen = aPropSeq.getLength();
1647
1648
            // For a FastPropertySet we must remember the original handles
1649
0
            if( bFast )
1650
0
                pAccess->mpOrgPropertyHandleArray.reset( new sal_Int32[ nLen ] );
1651
1652
0
            for( sal_Int32 i = 0 ; i < nLen ; i++ )
1653
0
            {
1654
                // Put property in its own list
1655
0
                pAccess->checkPropertyArraysSize( rPropCount );
1656
0
                Property& rProp = rAllPropArray[ rPropCount ];
1657
0
                rProp = aPropSeq[i];
1658
1659
0
                if( bFast )
1660
0
                    pAccess->mpOrgPropertyHandleArray[ i ] = rProp.Handle;
1661
1662
                // Enter PropCount as a handle for its own FastPropertySet
1663
0
                rProp.Handle = rPropCount;
1664
1665
                // Remember type of property
1666
0
                rMapTypeArray[ rPropCount ] = MAP_PROPERTY_SET;
1667
0
                rPropertyConceptArray[ rPropCount ] = PROPERTYSET;
1668
0
                pAccess->mnPropertySetPropCount++;
1669
1670
                // Enter name in hash table if not already known
1671
0
                OUString aPropName = rProp.Name;
1672
1673
                // Do we already have the name?
1674
0
                IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1675
0
                if( aIt == rPropNameMap.end() )
1676
0
                {
1677
                    // New entry in the hash table
1678
0
                    rPropNameMap[ aPropName ] = rPropCount;
1679
1680
                    // Maintain table for XExactName
1681
0
                    rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1682
0
                }
1683
0
                else
1684
0
                {
1685
0
                    SAL_WARN( "stoc", "Introspection: Property \"" <<
1686
0
                        aPropName << "\" found more than once in PropertySet" );
1687
0
                }
1688
1689
                // Adjust count
1690
0
                rPropCount++;
1691
0
            }
1692
0
        }
1693
1694
        // Indices in the export table
1695
15
        sal_Int32 iAllExportedMethod = 0;
1696
15
        sal_Int32 iAllSupportedListener = 0;
1697
1698
15
        std::set<OUString> seen;
1699
1700
        // Flag, whether XInterface methods should be recorded
1701
        // (this must be done only once, allowed initially)
1702
15
        bool bXInterfaceIsInvalid = false;
1703
1704
        // Flag whether the XInterface methods have already been recorded. If
1705
        // sal_True, bXInterfaceIsInvalid is activated at the end of the interface
1706
        // loop, and XInterface methods are cut off thereafter.
1707
15
        bool bFoundXInterface = false;
1708
1709
15
        size_t nClassCount = SupportedClassSeq.size();
1710
130
        for( size_t nIdx = 0 ; nIdx < nClassCount; nIdx++ )
1711
115
        {
1712
115
            Reference<XIdlClass> xImplClass2 = SupportedClassSeq[nIdx];
1713
360
            while( xImplClass2.is() )
1714
245
            {
1715
                // Fetch interfaces from the implementation
1716
245
                Sequence< Reference<XIdlClass> > aClassSeq = xImplClass2->getInterfaces();
1717
245
                sal_Int32 nIfaceCount = aClassSeq.getLength();
1718
1719
245
                aClassSeq.realloc( nIfaceCount + 1 );
1720
245
                aClassSeq.getArray()[ nIfaceCount ] = xImplClass2;
1721
1722
245
                for (const Reference<XIdlClass>& rxIfaceClass : aClassSeq)
1723
245
                {
1724
245
                    if (!seen.insert(rxIfaceClass->getName()).second) {
1725
100
                        continue;
1726
100
                    }
1727
1728
                    // 2. Register fields as properties
1729
1730
                    // Get fields
1731
145
                    const Sequence< Reference<XIdlField> > fields = rxIfaceClass->getFields();
1732
1733
145
                    for( const Reference<XIdlField>& xField : fields )
1734
0
                    {
1735
0
                        Reference<XIdlClass> xPropType = xField->getType();
1736
1737
                        // Is the property sequence big enough?
1738
0
                        pAccess->checkPropertyArraysSize( rPropCount );
1739
1740
                        // Enter in own property array
1741
0
                        Property& rProp = rAllPropArray[ rPropCount ];
1742
0
                        rProp.Name = xField->getName();
1743
0
                        rProp.Handle = rPropCount;
1744
0
                        rProp.Type = Type(xPropType->getTypeClass(), xPropType->getName());
1745
0
                        FieldAccessMode eAccessMode = xField->getAccessMode();
1746
0
                        rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
1747
0
                                            eAccessMode == FieldAccessMode_CONST)
1748
0
                            ? READONLY : 0;
1749
1750
                        // Enter name in hash table
1751
0
                        OUString aPropName = rProp.Name;
1752
1753
                        // Do we have the name already?
1754
0
                        IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1755
0
                        if (aIt != rPropNameMap.end())
1756
0
                            continue;
1757
1758
                        // New entry in the hash table
1759
0
                        rPropNameMap[ aPropName ] = rPropCount;
1760
1761
                        // Maintain table for XExactName
1762
0
                        rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1763
1764
                        // Remember field
1765
0
                        IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
1766
0
                                                          rInterfaces1, rPropCount );
1767
0
                        rInterfaces1[ rPropCount ] = xField;
1768
1769
                        // Remember type of property
1770
0
                        rMapTypeArray[ rPropCount ] = MAP_FIELD;
1771
0
                        rPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
1772
0
                        pAccess->mnAttributePropCount++;
1773
1774
                        // Adjust count
1775
0
                        rPropCount++;
1776
0
                    }
1777
1778
1779
                    // 3. Methods
1780
1781
                    // Get and remember all methods
1782
145
                    Sequence< Reference<XIdlMethod> > methods = rxIfaceClass->getMethods();
1783
145
                    sal_Int32 nSourceMethodCount = methods.getLength();
1784
1785
                    // 3. a) Search get/set and listener methods
1786
1787
                    // Create field for information about the methods, so that methods which are not
1788
                    // related to properties or listeners can easily be found later.
1789
                    // New: initialise MethodConceptArray
1790
145
                    enum MethodType
1791
145
                    {
1792
145
                        STANDARD_METHOD,            // normal method, not related to properties or listeners
1793
145
                        GETSET_METHOD,                // belongs to a get/set property
1794
145
                        ADD_LISTENER_METHOD,        // add method of a listener interface
1795
145
                        REMOVE_LISTENER_METHOD,        // remove method of a listener interface
1796
145
                        INVALID_METHOD                // method whose class is not considered, e.g. XPropertySet
1797
145
                    };
1798
145
                    std::unique_ptr<MethodType[]> pMethodTypes( new MethodType[ nSourceMethodCount ] );
1799
145
                    std::unique_ptr<sal_Int32[]> pLocalMethodConcepts( new sal_Int32[ nSourceMethodCount ] );
1800
1.44k
                    for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
1801
1.30k
                    {
1802
1.30k
                        pMethodTypes[ i ] = STANDARD_METHOD;
1803
1.30k
                        pLocalMethodConcepts[ i ] = 0;
1804
1.30k
                    }
1805
1806
1.44k
                    for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
1807
1.30k
                    {
1808
                        // Address method
1809
1.30k
                        const Reference<XIdlMethod>& rxMethod_i = methods[i];
1810
1.30k
                        sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
1811
1812
                        // Fetch name
1813
1.30k
                        OUString aMethName = rxMethod_i->getName();
1814
1815
                        // Catalogue methods
1816
                        // Filter all (?) methods of XInterface so e.g. acquire and release
1817
                        // can not be called from scripting
1818
1.30k
                        OUString className(
1819
1.30k
                            rxMethod_i->getDeclaringClass()->getName());
1820
1.30k
                        if (className == "com.sun.star.uno.XInterface") {
1821
435
                            bFoundXInterface = true;
1822
1823
435
                            if( bXInterfaceIsInvalid )
1824
390
                            {
1825
390
                                pMethodTypes[ i ] = INVALID_METHOD;
1826
390
                                continue;
1827
390
                            }
1828
45
                            else
1829
45
                            {
1830
45
                                if( aMethName != "queryInterface" )
1831
30
                                {
1832
30
                                    rMethodConcept_i |= MethodConcept::DANGEROUS;
1833
30
                                    continue;
1834
30
                                }
1835
45
                            }
1836
865
                        } else if (className == "com.sun.star.uno.XAggregation")
1837
0
                        {
1838
0
                            if( aMethName == "setDelegator" )
1839
0
                            {
1840
0
                                rMethodConcept_i |= MethodConcept::DANGEROUS;
1841
0
                                continue;
1842
0
                            }
1843
865
                        } else if (className
1844
865
                                   == "com.sun.star.container.XElementAccess")
1845
0
                        {
1846
0
                            rMethodConcept_i |= ( NAMECONTAINER  |
1847
0
                                                  INDEXCONTAINER |
1848
0
                                                  ENUMERATION );
1849
0
                            pAccess->mbElementAccess = true;
1850
865
                        } else if (className
1851
865
                                    == "com.sun.star.container.XNameContainer")
1852
0
                        {
1853
0
                            rMethodConcept_i |= NAMECONTAINER;
1854
0
                            pAccess->mbNameContainer = true;
1855
0
                            pAccess->mbNameReplace = true;
1856
0
                            pAccess->mbNameAccess = true;
1857
0
                            pAccess->mbElementAccess = true;
1858
865
                        } else if (className
1859
865
                                    == "com.sun.star.container.XNameReplace")
1860
0
                        {
1861
0
                            rMethodConcept_i |= NAMECONTAINER;
1862
0
                            pAccess->mbNameReplace = true;
1863
0
                            pAccess->mbNameAccess = true;
1864
0
                            pAccess->mbElementAccess = true;
1865
865
                        } else if (className
1866
865
                                    == "com.sun.star.container.XNameAccess")
1867
0
                        {
1868
0
                            rMethodConcept_i |= NAMECONTAINER;
1869
0
                            pAccess->mbNameAccess = true;
1870
0
                            pAccess->mbElementAccess = true;
1871
865
                        } else if (className
1872
865
                                    == "com.sun.star.container.XIndexContainer")
1873
0
                        {
1874
0
                            rMethodConcept_i |= INDEXCONTAINER;
1875
0
                            pAccess->mbIndexContainer = true;
1876
0
                            pAccess->mbIndexReplace = true;
1877
0
                            pAccess->mbIndexAccess = true;
1878
0
                            pAccess->mbElementAccess = true;
1879
865
                        } else if (className
1880
865
                                    == "com.sun.star.container.XIndexReplace")
1881
0
                        {
1882
0
                            rMethodConcept_i |= INDEXCONTAINER;
1883
0
                            pAccess->mbIndexReplace = true;
1884
0
                            pAccess->mbIndexAccess = true;
1885
0
                            pAccess->mbElementAccess = true;
1886
865
                        } else if (className
1887
865
                                    == "com.sun.star.container.XIndexAccess")
1888
0
                        {
1889
0
                            rMethodConcept_i |= INDEXCONTAINER;
1890
0
                            pAccess->mbIndexAccess = true;
1891
0
                            pAccess->mbElementAccess = true;
1892
865
                        } else if (className
1893
865
                                   == "com.sun.star.container.XEnumerationAccess")
1894
0
                        {
1895
0
                            rMethodConcept_i |= ENUMERATION;
1896
0
                            pAccess->mbEnumerationAccess = true;
1897
0
                            pAccess->mbElementAccess = true;
1898
865
                        } else if (className
1899
865
                                   == "com.sun.star.reflection.XIdlArray")
1900
0
                        {
1901
0
                            pAccess->mbIdlArray = true;
1902
865
                        } else if (className
1903
865
                                   == "com.sun.star.lang.XUnoTunnel")
1904
0
                        {
1905
0
                            pAccess->mbUnoTunnel = true;
1906
0
                        }
1907
1908
                        // If the name is too short, it isn't anything
1909
880
                        if( aMethName.getLength() <= 3 )
1910
0
                            continue;
1911
1912
                        // Is it a get method?
1913
880
                        OUString aPropName;
1914
880
                        if( aMethName.startsWith("get", &aPropName) )
1915
790
                        {
1916
                            // Get methods must not have any parameters
1917
790
                            Sequence< Reference<XIdlClass> > getParams = rxMethod_i->getParameterTypes();
1918
790
                            if( getParams.hasElements() )
1919
685
                            {
1920
685
                                continue;
1921
685
                            }
1922
1923
                            // Do we have the name already?
1924
105
                            IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1925
105
                            if (aIt != rPropNameMap.end())
1926
15
                            {
1927
                                /* TODO
1928
                                   SAL_INFO("stoc",(
1929
                                   String( "Introspection: Property \"" ) +
1930
                                   OOUStringToString( aPropName, CHARSET_SYSTEM ) +
1931
                                   String( "\" found more than once" ) );
1932
                                */
1933
15
                                continue;
1934
15
                            }
1935
1936
                            // It is already at least a read-only property
1937
90
                            rMethodConcept_i |= PROPERTY;
1938
1939
90
                            pMethodTypes[i] = GETSET_METHOD;
1940
90
                            Reference<XIdlClass> xGetRetType = rxMethod_i->getReturnType();
1941
1942
                            // Is the property sequence big enough?
1943
90
                            pAccess->checkPropertyArraysSize( rPropCount );
1944
1945
                            // Write it in its property array
1946
90
                            Property& rProp = rAllPropArray[ rPropCount ];
1947
90
                            rProp.Name = aPropName;
1948
90
                            rProp.Handle = rPropCount;
1949
90
                            rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
1950
90
                            rProp.Attributes = READONLY;
1951
1952
                            // New entry in the hash table
1953
90
                            rPropNameMap[ aPropName ] = rPropCount;
1954
1955
                            // Maintain table for XExactName
1956
90
                            rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1957
1958
                            // Remember get method
1959
90
                            IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
1960
90
                                                              rInterfaces1, rPropCount );
1961
90
                            rInterfaces1[ rPropCount ] = rxMethod_i;
1962
1963
                            // Remember type of property
1964
90
                            rMapTypeArray[ rPropCount ] = MAP_GETSET;
1965
90
                            rPropertyConceptArray[ rPropCount ] = METHODS;
1966
90
                            pAccess->mnMethodPropCount++;
1967
1968
                            // Search for matching set method
1969
90
                            sal_Int32 k;
1970
660
                            for( k = 0 ; k < nSourceMethodCount ; k++ )
1971
570
                            {
1972
                                // Address method
1973
570
                                const Reference<XIdlMethod>& rxMethod_k = methods[k];
1974
1975
                                // Accept only methods that are not already assigned
1976
570
                                if( k == i || pMethodTypes[k] != STANDARD_METHOD )
1977
345
                                    continue;
1978
1979
                                // Get name and evaluate
1980
225
                                OUString aMethName2 = rxMethod_k->getName();
1981
225
                                std::u16string_view aPropName2;
1982
225
                                if (!(aMethName2.startsWith("set", &aPropName2)
1983
15
                                      && aPropName2 == aPropName))
1984
210
                                    continue;
1985
1986
                                // A set method must return void
1987
15
                                Reference<XIdlClass> xSetRetType = rxMethod_k->getReturnType();
1988
15
                                if( xSetRetType->getTypeClass() != TypeClass_VOID )
1989
0
                                {
1990
0
                                    continue;
1991
0
                                }
1992
1993
                                // A set method may only have one parameter
1994
15
                                Sequence< Reference<XIdlClass> > setParams = rxMethod_k->getParameterTypes();
1995
15
                                sal_Int32 nParamCount = setParams.getLength();
1996
15
                                if( nParamCount != 1 )
1997
0
                                {
1998
0
                                    continue;
1999
0
                                }
2000
2001
                                // Next, the return type must correspond to the parameter type
2002
15
                                Reference<XIdlClass> xParamType = setParams[0];
2003
15
                                if( xParamType->equals( xGetRetType ) )
2004
15
                                {
2005
15
                                    pLocalMethodConcepts[ k ] = PROPERTY;
2006
2007
15
                                    pMethodTypes[k] = GETSET_METHOD;
2008
2009
                                    // Delete read-only flag again
2010
15
                                    rProp.Attributes &= ~READONLY;
2011
2012
                                    // Remember set method
2013
15
                                    IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2014
15
                                                                      rInterfaces2, rPropCount );
2015
15
                                    rInterfaces2[ rPropCount ] = rxMethod_k;
2016
15
                                }
2017
15
                            }
2018
2019
                            // Adjust count
2020
90
                            rPropCount++;
2021
90
                        }
2022
2023
                        // Is it an add listener method?
2024
90
                        else if( aMethName.startsWith("add", &aPropName) )
2025
5
                        {
2026
                            // Does it end with "Listener"?
2027
5
                            std::u16string_view aListenerName;
2028
5
                            if( !aPropName.endsWith("Listener", &aListenerName) )
2029
0
                                continue;
2030
2031
                            // TODO: More accurate tests could still be carried out here
2032
                            // - Return type
2033
                            // - Number and type of parameters
2034
2035
2036
                            // Search for matching remove method, otherwise not applicable
2037
5
                            sal_Int32 k;
2038
35
                            for( k = 0 ; k < nSourceMethodCount ; k++ )
2039
30
                            {
2040
                                // Address method
2041
30
                                const Reference<XIdlMethod>& rxMethod_k = methods[k];
2042
2043
                                // Accept only methods that are not already assigned
2044
30
                                if( k == i || pMethodTypes[k] != STANDARD_METHOD )
2045
20
                                    continue;
2046
2047
                                // Get name and evaluate
2048
10
                                OUString aMethName2 = rxMethod_k->getName();
2049
10
                                std::u16string_view rest;
2050
10
                                std::u16string_view aListenerName2;
2051
10
                                if (!(aMethName2.startsWith(
2052
10
                                          "remove", &rest)
2053
5
                                      && o3tl::ends_with(rest,
2054
5
                                          u"Listener", &aListenerName2)
2055
5
                                      && aListenerName2 == aListenerName))
2056
5
                                    continue;
2057
2058
                                // TODO: More accurate tests could still be carried out here
2059
                                // - Return type
2060
                                // - Number and type of parameters
2061
2062
2063
                                // Methods are recognised as a listener interface
2064
5
                                rMethodConcept_i |= LISTENER;
2065
5
                                pLocalMethodConcepts[ k ] |= LISTENER;
2066
2067
5
                                pMethodTypes[i] = ADD_LISTENER_METHOD;
2068
5
                                pMethodTypes[k] = REMOVE_LISTENER_METHOD;
2069
5
                            }
2070
5
                        }
2071
880
                    }
2072
2073
2074
                    // A set method could still exist without a corresponding get method,
2075
                    // this must be a write-only property
2076
1.44k
                    for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
2077
1.30k
                    {
2078
                        // Address method
2079
1.30k
                        const Reference<XIdlMethod>& rxMethod_i = methods[i];
2080
2081
                        // Accept only methods that are not already assigned
2082
1.30k
                        if( pMethodTypes[i] != STANDARD_METHOD )
2083
505
                            continue;
2084
2085
                        // Get name
2086
795
                        OUString aMethName = rxMethod_i->getName();
2087
2088
                        // If the name is too short, it isn't anything
2089
795
                        if( aMethName.getLength() <= 3 )
2090
0
                            continue;
2091
2092
                        // Is it a set method without associated get method?
2093
795
                        OUString aPropName;
2094
795
                        if( aMethName.startsWith("set", &aPropName) )
2095
15
                        {
2096
                            // A set method must return void
2097
15
                            Reference<XIdlClass> xSetRetType = rxMethod_i->getReturnType();
2098
15
                            if( xSetRetType->getTypeClass() != TypeClass_VOID )
2099
0
                            {
2100
0
                                continue;
2101
0
                            }
2102
2103
                            // A set method may only have one parameter
2104
15
                            Sequence< Reference<XIdlClass> > setParams = rxMethod_i->getParameterTypes();
2105
15
                            sal_Int32 nParamCount = setParams.getLength();
2106
15
                            if( nParamCount != 1 )
2107
0
                            {
2108
0
                                continue;
2109
0
                            }
2110
2111
                            // Do we have the name already?
2112
15
                            IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2113
15
                            if (aIt != rPropNameMap.end())
2114
15
                            {
2115
                                /* TODO:
2116
                                   SAL_INFO("stoc",(
2117
                                   String( "Introspection: Property \"" ) +
2118
                                   OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2119
                                   String( "\" found more than once" ) );
2120
                                */
2121
15
                                continue;
2122
15
                            }
2123
2124
                            // Now we know it's a write only property
2125
0
                            pLocalMethodConcepts[ i ] = PROPERTY;
2126
2127
0
                            pMethodTypes[i] = GETSET_METHOD;
2128
0
                            Reference<XIdlClass> xGetRetType = setParams[0];
2129
2130
                            // Is the property sequence big enough?
2131
0
                            pAccess->checkPropertyArraysSize( rPropCount );
2132
2133
                            // Write it in its property array
2134
0
                            Property& rProp = rAllPropArray[ rPropCount ];
2135
0
                            rProp.Name = aPropName;
2136
0
                            rProp.Handle = rPropCount;
2137
0
                            rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
2138
0
                            rProp.Attributes = 0;    // PROPERTY_WRITEONLY ???
2139
2140
                            // New entry in the hash table
2141
0
                            rPropNameMap[ aPropName ] = rPropCount;
2142
2143
                            // Maintain table for XExactName
2144
0
                            rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2145
2146
                            // Remember set method
2147
0
                            IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2148
0
                                                              rInterfaces2, rPropCount );
2149
0
                            rInterfaces2[ rPropCount ] = rxMethod_i;
2150
2151
                            // Remember type of property
2152
0
                            rMapTypeArray[ rPropCount ] = MAP_SETONLY;
2153
0
                            rPropertyConceptArray[ rPropCount ] = METHODS;
2154
0
                            pAccess->mnMethodPropCount++;
2155
2156
                            // Adjust count
2157
0
                            rPropCount++;
2158
0
                        }
2159
795
                    }
2160
2161
2162
                    // 4. Place methods in overall sequence
2163
2164
                    // How many methods in the method sequence
2165
145
                    sal_Int32 nExportedMethodCount = 0;
2166
145
                    sal_Int32 nSupportedListenerCount = 0;
2167
1.44k
                    for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
2168
1.30k
                    {
2169
1.30k
                        if( pMethodTypes[ i ] != INVALID_METHOD )
2170
910
                        {
2171
910
                            nExportedMethodCount++;
2172
910
                        }
2173
1.30k
                        if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2174
5
                        {
2175
5
                            nSupportedListenerCount++;
2176
5
                        }
2177
1.30k
                    }
2178
2179
                    // Enlarge sequences in the access object accordingly
2180
145
                    pAccess->maAllMethodSeq.resize( nExportedMethodCount + iAllExportedMethod );
2181
145
                    pAccess->maMethodConceptSeq.resize( nExportedMethodCount + iAllExportedMethod );
2182
145
                    pAccess->maSupportedListenerSeq.resize( nSupportedListenerCount + iAllSupportedListener );
2183
2184
                    // Write in methods
2185
1.44k
                    for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
2186
1.30k
                    {
2187
1.30k
                        if( pMethodTypes[ i ] != INVALID_METHOD )
2188
910
                        {
2189
                            // Address method
2190
910
                            const Reference<XIdlMethod>& rxMethod = methods[i];
2191
2192
                            // Enter name in hash table if not already known
2193
910
                            OUString aMethName2 = rxMethod->getName();
2194
910
                            IntrospectionNameMap::iterator aIt = rMethodNameMap.find( aMethName2 );
2195
910
                            if( aIt == rMethodNameMap.end() )
2196
880
                            {
2197
                                // Enter
2198
880
                                rMethodNameMap[ aMethName2 ] = iAllExportedMethod;
2199
2200
                                // Maintain table for XExactName
2201
880
                                rLowerToExactNameMap[ aMethName2.toAsciiLowerCase() ] = aMethName2;
2202
880
                            }
2203
30
                            else
2204
30
                            {
2205
30
                                sal_Int32 iHashResult = aIt->second;
2206
2207
30
                                Reference<XIdlMethod> xExistingMethod = pAccess->maAllMethodSeq[iHashResult];
2208
2209
30
                                Reference< XIdlClass > xExistingMethClass =
2210
30
                                    xExistingMethod->getDeclaringClass();
2211
30
                                Reference< XIdlClass > xNewMethClass = rxMethod->getDeclaringClass();
2212
30
                                if( xExistingMethClass->equals( xNewMethClass ) )
2213
30
                                    continue;
2214
30
                            }
2215
2216
880
                            pAccess->maAllMethodSeq[iAllExportedMethod] = rxMethod;
2217
2218
                            // If a concept has been set, is the method "normal"?
2219
880
                            sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
2220
880
                            if( !rMethodConcept_i )
2221
735
                                rMethodConcept_i = MethodConcept_NORMAL_IMPL;
2222
880
                            pAccess->maMethodConceptSeq[ iAllExportedMethod ] = rMethodConcept_i;
2223
880
                            iAllExportedMethod++;
2224
880
                        }
2225
1.27k
                        if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2226
5
                        {
2227
                            // Determine class of listener
2228
5
                            const Reference<XIdlMethod>& rxMethod = methods[i];
2229
2230
                            // Enter void as default class
2231
5
                            css::uno::Reference<css::reflection::XIdlClass>
2232
5
                                xListenerClass(
2233
5
                                    reflection->forName(
2234
5
                                        cppu::UnoType<void>::get()
2235
5
                                        .getTypeName()));
2236
                            // Old: Reference<XIdlClass> xListenerClass = Void_getReflection()->getIdlClass();
2237
2238
                            // Option 1: Search for parameters for a listener class
2239
                            // Disadvantage: Superclasses should be searched recursively
2240
5
                            const Sequence< Reference<XIdlClass> > aParams = rxMethod->getParameterTypes();
2241
2242
5
                            css::uno::Reference<css::reflection::XIdlClass>
2243
5
                                xEventListenerClass(
2244
5
                                    reflection->forName(
2245
5
                                        cppu::UnoType<
2246
5
                                            css::lang::XEventListener>::get()
2247
5
                                        .getTypeName()));
2248
                            // Old: Reference<XIdlClass> xEventListenerClass = XEventListener_getReflection()->getIdlClass();
2249
5
                            auto pParam = std::find_if(aParams.begin(), aParams.end(),
2250
5
                                [&xEventListenerClass](const Reference<XIdlClass>& rxClass) {
2251
                                    // Are we derived from a listener?
2252
5
                                    return rxClass->equals( xEventListenerClass )
2253
0
                                        || isDerivedFrom( rxClass, xEventListenerClass );
2254
5
                                });
2255
5
                            if (pParam != aParams.end())
2256
5
                            {
2257
5
                                xListenerClass = *pParam;
2258
5
                            }
2259
2260
                            // Option 2: Unload the name of the method
2261
                            // Disadvantage: Does not work with test listeners, where it does not exist
2262
                            //aMethName = rxMethod->getName();
2263
                            //aListenerName = aMethName.Copy( 3, aMethName.Len()-8-3 );
2264
                            //Reference<XIdlClass> xListenerClass = reflection->forName( aListenerName );
2265
5
                            pAccess->maSupportedListenerSeq[ iAllSupportedListener ] =
2266
5
                                Type(TypeClass_INTERFACE, xListenerClass->getName());
2267
5
                            iAllSupportedListener++;
2268
5
                        }
2269
1.27k
                    }
2270
2271
                    // When there were XInterface methods in this run,
2272
                    // ignore them in the future
2273
145
                    if( bFoundXInterface )
2274
145
                        bXInterfaceIsInvalid = true;
2275
145
                }
2276
2277
                // Do superclasses exist? Then continue here
2278
245
                Sequence< Reference<XIdlClass> > aSuperClassSeq = xImplClass2->getSuperclasses();
2279
2280
                // Currently only one superclass is considered
2281
245
                if( aSuperClassSeq.getLength() >= 1 )
2282
130
                {
2283
130
                    xImplClass2 = aSuperClassSeq[0];
2284
130
                    OSL_ENSURE( xImplClass2.is(), "super class null" );
2285
130
                }
2286
115
                else
2287
115
                {
2288
115
                    xImplClass2 = nullptr;
2289
115
                }
2290
245
            }
2291
115
        }
2292
2293
        // Apply number of exported methods and adapt Sequences
2294
        // (can be different because duplicate methods are thrown
2295
        // out only after the determination of nExportedMethodCount)
2296
15
        sal_Int32& rMethCount = pAccess->mnMethCount;
2297
15
        rMethCount = iAllExportedMethod;
2298
15
        pAccess->maAllMethodSeq.resize( rMethCount );
2299
15
        pAccess->maMethodConceptSeq.resize( rMethCount );
2300
2301
        // Resize the property sequences
2302
15
        pAccess->maAllPropertySeq.resize( rPropCount );
2303
15
        pAccess->maPropertyConceptSeq.resize( rPropCount );
2304
15
        pAccess->maMapTypeSeq.resize( rPropCount );
2305
15
    }
2306
    // Register struct fields as properties
2307
0
    else //if( eType == TypeClass_STRUCT )
2308
0
    {
2309
        // Is it an interface or a struct?
2310
        //Reference<XIdlClass> xClassRef = aToInspectObj.getReflection()->getIdlClass();
2311
0
        css::uno::Reference<css::reflection::XIdlClass> xClassRef(
2312
0
            reflection->forName(aToInspectObj.getValueTypeName()));
2313
0
        if( !xClassRef.is() )
2314
0
        {
2315
0
            SAL_WARN( "stoc", "Can't get XIdlClass from Reflection" );
2316
0
            return new ImplIntrospectionAccess(aToInspectObj, pAccess);
2317
0
        }
2318
2319
        // Get fields
2320
0
        const Sequence< Reference<XIdlField> > fields = xClassRef->getFields();
2321
2322
0
        for( const Reference<XIdlField>& xField : fields )
2323
0
        {
2324
0
            Reference<XIdlClass> xPropType = xField->getType();
2325
0
            OUString aPropName = xField->getName();
2326
2327
            // Is the property sequence big enough?
2328
0
            pAccess->checkPropertyArraysSize( rPropCount );
2329
2330
            // Write it in its property array
2331
0
            Property& rProp = rAllPropArray[ rPropCount ];
2332
0
            rProp.Name = aPropName;
2333
0
            rProp.Handle = rPropCount;
2334
0
            rProp.Type = Type( xPropType->getTypeClass(), xPropType->getName() );
2335
0
            FieldAccessMode eAccessMode = xField->getAccessMode();
2336
0
            rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
2337
0
                                eAccessMode == FieldAccessMode_CONST)
2338
0
                                ? READONLY : 0;
2339
2340
            //FieldAccessMode eAccessMode = xField->getAccessMode();
2341
            //rProp.Attributes = (eAccessMode == FieldAccessMode::READONLY || eAccessMode == CONST)
2342
                //? PropertyAttribute::READONLY : 0;
2343
2344
            // Write name in hash table
2345
0
            rPropNameMap[ aPropName ] = rPropCount;
2346
2347
            // Maintain table for XExactName
2348
0
            rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2349
2350
            // Remember field
2351
0
            IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
2352
0
                rInterfaces1, rPropCount );
2353
0
            rInterfaces1[ rPropCount ] = xField;
2354
2355
            // Remember type of property
2356
0
            rMapTypeArray[ rPropCount ] = MAP_FIELD;
2357
0
            rPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
2358
0
            pAccess->mnAttributePropCount++;
2359
2360
            // Adjust count
2361
0
            rPropCount++;
2362
0
        }
2363
0
    }
2364
2365
    // Set property sequence to the correct length
2366
15
    pAccess->maAllPropertySeq.resize( pAccess->mnPropCount );
2367
2368
15
    return new ImplIntrospectionAccess(aToInspectObj, pAccess);
2369
15
}
2370
2371
}
2372
2373
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
2374
com_sun_star_comp_stoc_Introspection_get_implementation(
2375
    css::uno::XComponentContext * context,
2376
    css::uno::Sequence<css::uno::Any> const & arguments)
2377
5
{
2378
5
    SAL_WARN_IF(
2379
5
        arguments.hasElements(), "stoc", "unexpected singleton arguments");
2380
5
    return cppu::acquire(new Implementation(context));
2381
5
}
2382
2383
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */