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