1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
30 #include <o3tl/any.hxx>
31 #include <osl/diagnose.h>
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>
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>
64 #include <rtl/ref.hxx>
65 #include <rtl/ustrbuf.hxx>
66 #include <unordered_map>
69 using namespace css::uno
;
70 using namespace css::lang
;
71 using namespace css::reflection
;
72 using namespace css::container
;
73 using namespace css::beans
;
74 using namespace css::beans::PropertyAttribute
;
75 using namespace css::beans::PropertyConcept
;
76 using namespace css::beans::MethodConcept
;
83 typedef WeakImplHelper
< XIntrospectionAccess
, XMaterialHolder
, XExactName
,
84 XPropertySet
, XFastPropertySet
, XPropertySetInfo
,
85 XNameContainer
, XIndexContainer
, XEnumerationAccess
,
86 XIdlArray
, XUnoTunnel
> IntrospectionAccessHelper
;
89 // Special value for Method-Concept, to be able to mark "normal" functions
90 #define MethodConcept_NORMAL_IMPL 0x80000000
93 // Method to assert, if a class is derived from another class
94 bool isDerivedFrom( const Reference
<XIdlClass
>& xToTestClass
, const Reference
<XIdlClass
>& xDerivedFromClass
)
96 const Sequence
< Reference
<XIdlClass
> > aClassesSeq
= xToTestClass
->getSuperclasses();
98 return std::any_of(aClassesSeq
.begin(), aClassesSeq
.end(),
99 [&xDerivedFromClass
](const Reference
<XIdlClass
>& rxClass
) {
100 return xDerivedFromClass
->equals( rxClass
)
101 || isDerivedFrom( rxClass
, xDerivedFromClass
);
106 // *** Classification of Properties (no enum, to be able to use Sequence) ***
107 // Properties from a PropertySet-Interface
108 #define MAP_PROPERTY_SET 0
109 // Properties from Fields
111 // Properties that get described with get/set methods
113 // Properties with only a set method
114 #define MAP_SETONLY 3
117 // Increments by which the size of sequences get adjusted
118 #define ARRAY_SIZE_STEP 20
121 //*** IntrospectionAccessStatic_Impl ***
123 // Equals to the old IntrospectionAccessImpl, forms now a static
124 // part of the new Instance-related ImplIntrospectionAccess
126 // Hashtable for the search of names
127 typedef std::unordered_map
132 IntrospectionNameMap
;
135 // Hashtable to assign exact names to the Lower-Case
136 // converted names, for the support of XExactName
137 typedef std::unordered_map
145 class IntrospectionAccessStatic_Impl
: public salhelper::SimpleReferenceObject
147 friend class Implementation
;
148 friend class ImplIntrospectionAccess
;
150 // Holding CoreReflection
151 Reference
< XIdlReflection
> mxCoreReflection
;
153 // InterfaceSequences, to save additional information in a property
154 // for example the Field at MAP_FIELD, the get/set-Methods at MAP_GETSET, et cetera
155 std::vector
< Reference
<XInterface
> > aInterfaceSeq1
;
156 std::vector
< Reference
<XInterface
> > aInterfaceSeq2
;
158 // Hashtables for names
159 IntrospectionNameMap maPropertyNameMap
;
160 IntrospectionNameMap maMethodNameMap
;
161 LowerToExactNameMap maLowerToExactNameMap
;
163 // Vector of all Properties, also for delivering from getProperties()
164 std::vector
<Property
> maAllPropertySeq
;
166 // Mapping of properties to Access-Types
167 std::vector
<sal_Int16
> maMapTypeSeq
;
169 // Classification of found methods
170 std::vector
<sal_Int32
> maPropertyConceptSeq
;
172 // Number of Properties
173 sal_Int32 mnPropCount
;
175 // Number of Properties, which are assigned to particular concepts
176 //sal_Int32 mnDangerousPropCount;
177 sal_Int32 mnPropertySetPropCount
;
178 sal_Int32 mnAttributePropCount
;
179 sal_Int32 mnMethodPropCount
;
181 // Flags which indicate if various interfaces are present
183 bool mbElementAccess
;
186 bool mbNameContainer
;
189 bool mbIndexContainer
;
190 bool mbEnumerationAccess
;
194 // Original handles of FastPropertySets
195 std::unique_ptr
<sal_Int32
[]> mpOrgPropertyHandleArray
;
197 // MethodSequence, that accepts all methods
198 std::vector
< Reference
<XIdlMethod
> > maAllMethodSeq
;
200 // Classification of found methods
201 std::vector
<sal_Int32
> maMethodConceptSeq
;
204 sal_Int32 mnMethCount
;
206 // Sequence of Listener, that can be registered
207 std::vector
< Type
> maSupportedListenerSeq
;
209 // Helper-methods for adjusting sizes of Sequences
210 void checkPropertyArraysSize( sal_Int32 iNextIndex
);
211 static void checkInterfaceArraySize( std::vector
< Reference
<XInterface
> >& rSeq
, std::vector
<Reference
<XInterface
>>& rInterfaceVec
,
212 sal_Int32 iNextIndex
);
215 explicit IntrospectionAccessStatic_Impl( Reference
< XIdlReflection
> const & xCoreReflection_
);
216 sal_Int32
getPropertyIndex( const OUString
& aPropertyName
) const;
217 sal_Int32
getMethodIndex( const OUString
& aMethodName
) const;
219 // Methods of XIntrospectionAccess (OLD, now only Impl)
220 void setPropertyValue(const Any
& obj
, const OUString
& aPropertyName
, const Any
& aValue
) const;
221 // void setPropertyValue(Any& obj, const OUString& aPropertyName, const Any& aValue) const;
222 Any
getPropertyValue(const Any
& obj
, const OUString
& aPropertyName
) const;
223 void setPropertyValueByIndex(const Any
& obj
, sal_Int32 nIndex
, const Any
& aValue
) const;
224 // void setPropertyValueByIndex(Any& obj, sal_Int32 nIndex, const Any& aValue) const;
225 Any
getPropertyValueByIndex(const Any
& obj
, sal_Int32 nIndex
) const;
227 const std::vector
<Property
>& getProperties() const { return maAllPropertySeq
; }
228 const std::vector
< Reference
<XIdlMethod
> >& getMethods() const { return maAllMethodSeq
; }
229 const std::vector
< Type
>& getSupportedListeners() const { return maSupportedListenerSeq
; }
230 const std::vector
<sal_Int32
>& getPropertyConcepts() const { return maPropertyConceptSeq
; }
231 const std::vector
<sal_Int32
>& getMethodConcepts() const { return maMethodConceptSeq
; }
236 IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference
< XIdlReflection
> const & xCoreReflection_
)
237 : mxCoreReflection( xCoreReflection_
)
239 aInterfaceSeq1
.resize( ARRAY_SIZE_STEP
);
240 aInterfaceSeq2
.resize( ARRAY_SIZE_STEP
);
243 maAllPropertySeq
.resize( ARRAY_SIZE_STEP
);
244 maMapTypeSeq
.resize( ARRAY_SIZE_STEP
);
245 maPropertyConceptSeq
.resize( ARRAY_SIZE_STEP
);
247 mbFastPropSet
= false;
248 mbElementAccess
= false;
249 mbNameAccess
= false;
250 mbNameReplace
= false;
251 mbNameContainer
= false;
252 mbIndexAccess
= false;
253 mbIndexReplace
= false;
254 mbIndexContainer
= false;
255 mbEnumerationAccess
= false;
259 mpOrgPropertyHandleArray
= nullptr;
262 //mnDangerousPropCount = 0;
263 mnPropertySetPropCount
= 0;
264 mnAttributePropCount
= 0;
265 mnMethodPropCount
= 0;
271 sal_Int32
IntrospectionAccessStatic_Impl::getPropertyIndex( const OUString
& aPropertyName
) const
273 auto aIt
= maPropertyNameMap
.find(aPropertyName
);
274 if (aIt
!= maPropertyNameMap
.end())
280 sal_Int32
IntrospectionAccessStatic_Impl::getMethodIndex( const OUString
& aMethodName
) const
282 auto aIt
= maMethodNameMap
.find(aMethodName
);
283 if (aIt
!= maMethodNameMap
.end())
288 // #95159 Check if full qualified name matches
289 sal_Int32 nSearchFrom
= aMethodName
.getLength();
292 // Strategy: Search back until the first '_' is found
293 sal_Int32 nFound
= aMethodName
.lastIndexOf( '_', nSearchFrom
);
297 OUString aPureMethodName
= aMethodName
.copy( nFound
+ 1 );
299 aIt
= maMethodNameMap
.find( aPureMethodName
);
300 if (aIt
!= maMethodNameMap
.end())
302 // Check if it can be a type?
303 // Problem: Does not work if package names contain _ ?!
304 OUString aStr
= aMethodName
.copy( 0, nFound
);
305 OUString aTypeName
= aStr
.replace( '_', '.' );
306 Reference
< XIdlClass
> xClass
= mxCoreReflection
->forName( aTypeName
);
309 // If this is a valid class it could be the right method
311 // Could be the right method, type has to be checked
312 const sal_Int32 iHashResult
= aIt
->second
;
314 const Reference
<XIdlMethod
> xMethod
= maAllMethodSeq
[iHashResult
];
316 Reference
< XIdlClass
> xMethClass
= xMethod
->getDeclaringClass();
317 if( xClass
->equals( xMethClass
) )
323 // Could also be another method with the same name
324 // Iterate over all methods
325 size_t nLen
= maAllMethodSeq
.size();
326 for (size_t i
= 0; i
< nLen
; ++i
)
328 const Reference
<XIdlMethod
> xMethod2
= maAllMethodSeq
[ i
];
329 if( xMethod2
->getName() == aPureMethodName
)
331 Reference
< XIdlClass
> xMethClass2
= xMethod2
->getDeclaringClass();
333 if( xClass
->equals( xMethClass2
) )
343 nSearchFrom
= nFound
- 1;
344 if( nSearchFrom
< 0 )
350 void IntrospectionAccessStatic_Impl::setPropertyValue( const Any
& obj
, const OUString
& aPropertyName
, const Any
& aValue
) const
351 //void IntrospectionAccessStatic_Impl::setPropertyValue( Any& obj, const OUString& aPropertyName, const Any& aValue ) const
353 sal_Int32 i
= getPropertyIndex( aPropertyName
);
355 throw UnknownPropertyException(aPropertyName
);
356 setPropertyValueByIndex( obj
, i
, aValue
);
359 void IntrospectionAccessStatic_Impl::setPropertyValueByIndex(const Any
& obj
, sal_Int32 nSequenceIndex
, const Any
& aValue
) const
360 //void IntrospectionAccessStatic_Impl::setPropertyValueByIndex( Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
362 // Is the passed object something that fits?
363 Reference
<XInterface
> xInterface
;
364 if( !(obj
>>= xInterface
) )
366 TypeClass eObjType
= obj
.getValueType().getTypeClass();
367 if( nSequenceIndex
>= mnPropCount
)
368 throw IllegalArgumentException(
369 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), index > propertyCount, " +
370 OUString::number(nSequenceIndex
) + " > " + OUString::number(mnPropCount
),
371 Reference
<XInterface
>(), 0);
372 if( eObjType
!= TypeClass_STRUCT
&& eObjType
!= TypeClass_EXCEPTION
)
373 throw IllegalArgumentException(
374 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), expected struct or exception, got" +
375 obj
.getValueType().getTypeName(), Reference
<XInterface
>(), 0);
379 if( (maAllPropertySeq
[ nSequenceIndex
].Attributes
& READONLY
) != 0 )
381 throw UnknownPropertyException(
382 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), property at index " + OUString::number(nSequenceIndex
) + " is readonly");
385 switch( maMapTypeSeq
[ nSequenceIndex
] )
387 case MAP_PROPERTY_SET
:
390 const Property
& rProp
= maAllPropertySeq
[ nSequenceIndex
];
392 // Convert Interface-Parameter to the correct type
393 bool bUseCopy
= false;
396 if( auto valInterface
= o3tl::tryAccess
<
397 css::uno::Reference
<css::uno::XInterface
>>(aValue
) )
399 Type aPropType
= rProp
.Type
;
400 OUString
aTypeName( aPropType
.getTypeName() );
401 Reference
< XIdlClass
> xPropClass
= mxCoreReflection
->forName( aTypeName
);
402 //Reference<XIdlClass> xPropClass = rProp.Type;
403 if( xPropClass
.is() && xPropClass
->getTypeClass() == TypeClass_INTERFACE
)
405 if( valInterface
->is() )
407 //Any queryInterface( const Type& rType );
408 aRealValue
= (*valInterface
)->queryInterface( aPropType
);
409 if( aRealValue
.hasValue() )
415 // Do we have a FastPropertySet and a valid Handle?
416 // CAUTION: At this point we exploit that the PropertySet
417 // gets queried at the beginning of the Introspection-Process.
418 sal_Int32 nOrgHandle
;
419 if( mbFastPropSet
&& ( nOrgHandle
= mpOrgPropertyHandleArray
[ nSequenceIndex
] ) != -1 )
421 // Retrieve PropertySet-Interface
422 Reference
<XFastPropertySet
> xFastPropSet
=
423 Reference
<XFastPropertySet
>::query( xInterface
);
424 if( xFastPropSet
.is() )
426 xFastPropSet
->setFastPropertyValue( nOrgHandle
, bUseCopy
? aRealValue
: aValue
);
430 // throw UnknownPropertyException
433 // else take the normal one
436 // Retrieve PropertySet-Interface
437 Reference
<XPropertySet
> xPropSet
=
438 Reference
<XPropertySet
>::query( xInterface
);
441 xPropSet
->setPropertyValue( rProp
.Name
, bUseCopy
? aRealValue
: aValue
);
445 // throw UnknownPropertyException
453 Reference
<XIdlField
> xField
= static_cast<XIdlField
*>(aInterfaceSeq1
[ nSequenceIndex
].get());
454 Reference
<XIdlField2
> xField2(xField
, UNO_QUERY
);
457 xField2
->set( const_cast<Any
&>(obj
), aValue
);
458 // IllegalArgumentException
459 // NullPointerException
463 xField
->set( obj
, aValue
);
464 // IllegalArgumentException
465 // NullPointerException
469 // throw IllegalArgumentException();
478 Reference
<XIdlMethod
> xMethod
= static_cast<XIdlMethod
*>(aInterfaceSeq2
[ nSequenceIndex
].get());
481 Sequence
<Any
> args( 1 );
482 args
.getArray()[0] = aValue
;
483 xMethod
->invoke( obj
, args
);
487 // throw IllegalArgumentException();
494 Any
IntrospectionAccessStatic_Impl::getPropertyValue( const Any
& obj
, const OUString
& aPropertyName
) const
496 sal_Int32 i
= getPropertyIndex( aPropertyName
);
498 return getPropertyValueByIndex( obj
, i
);
500 throw UnknownPropertyException(aPropertyName
);
503 Any
IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any
& obj
, sal_Int32 nSequenceIndex
) const
507 // Is there anything suitable in the passed object?
508 Reference
<XInterface
> xInterface
;
509 if( !(obj
>>= xInterface
) )
511 TypeClass eObjType
= obj
.getValueType().getTypeClass();
512 if( nSequenceIndex
>= mnPropCount
|| ( eObjType
!= TypeClass_STRUCT
&& eObjType
!= TypeClass_EXCEPTION
) )
514 // throw IllegalArgumentException();
519 switch( maMapTypeSeq
[ nSequenceIndex
] )
521 case MAP_PROPERTY_SET
:
524 const Property
& rProp
= maAllPropertySeq
[ nSequenceIndex
];
526 // Do we have a FastPropertySet and a valid handle?
527 // NOTE: At this point is exploited that the PropertySet
528 // is queried at the beginning of introspection process.
529 sal_Int32 nOrgHandle
;
530 if( mbFastPropSet
&& ( nOrgHandle
= mpOrgPropertyHandleArray
[ nSequenceIndex
] ) != -1 )
532 // Fetch the PropertySet interface
533 Reference
<XFastPropertySet
> xFastPropSet
=
534 Reference
<XFastPropertySet
>::query( xInterface
);
535 if( xFastPropSet
.is() )
537 aRet
= xFastPropSet
->getFastPropertyValue( nOrgHandle
);
541 // throw UnknownPropertyException
545 // Otherwise use the normal one
548 // Fetch the PropertySet interface
549 Reference
<XPropertySet
> xPropSet
=
550 Reference
<XPropertySet
>::query( xInterface
);
553 aRet
= xPropSet
->getPropertyValue( rProp
.Name
);
557 // throw UnknownPropertyException
566 Reference
<XIdlField
> xField
= static_cast<XIdlField
*>(aInterfaceSeq1
[ nSequenceIndex
].get());
569 aRet
= xField
->get( obj
);
570 // IllegalArgumentException
571 // NullPointerException
575 // throw IllegalArgumentException();
584 Reference
<XIdlMethod
> xMethod
= static_cast<XIdlMethod
*>(aInterfaceSeq1
[ nSequenceIndex
].get());
588 aRet
= xMethod
->invoke( obj
, args
);
592 // throw IllegalArgumentException();
599 // Get method does not exist
600 // throw WriteOnlyPropertyException();
607 // Helper method to adjust the size of the vectors
608 void IntrospectionAccessStatic_Impl::checkPropertyArraysSize( sal_Int32 iNextIndex
)
610 sal_Int32 nLen
= static_cast<sal_Int32
>(maAllPropertySeq
.size());
611 if( iNextIndex
>= nLen
)
613 maAllPropertySeq
.resize( nLen
+ ARRAY_SIZE_STEP
);
614 maMapTypeSeq
.resize( nLen
+ ARRAY_SIZE_STEP
);
615 maPropertyConceptSeq
.resize( nLen
+ ARRAY_SIZE_STEP
);
619 void IntrospectionAccessStatic_Impl::checkInterfaceArraySize( std::vector
< Reference
<XInterface
> >& rSeq
,
620 std::vector
<Reference
<XInterface
>>& rInterfaceVec
, sal_Int32 iNextIndex
)
622 sal_Int32 nLen
= rSeq
.size();
623 if( iNextIndex
>= nLen
)
625 // Synchronize new size with ARRAY_SIZE_STEP
626 sal_Int32 nMissingSize
= iNextIndex
- nLen
+ 1;
627 sal_Int32 nSteps
= nMissingSize
/ ARRAY_SIZE_STEP
+ 1;
628 sal_Int32 nNewSize
= nLen
+ nSteps
* ARRAY_SIZE_STEP
;
630 rSeq
.resize( nNewSize
);
631 rInterfaceVec
= rSeq
;
636 //*** ImplIntrospectionAccess ***
639 // New Impl class as part of the introspection conversion to instance-bound
640 // Introspection with property access via XPropertySet. The old class
641 // ImplIntrospectionAccess lives on as IntrospectionAccessStatic_Impl
642 class ImplIntrospectionAccess
: public IntrospectionAccessHelper
644 friend class Implementation
;
646 // Object under examination
647 Any maInspectedObject
;
650 Reference
<XInterface
> mxIface
;
652 // Static introspection data
653 rtl::Reference
< IntrospectionAccessStatic_Impl
> mpStaticImpl
;
655 // Last Sequence that came with getProperties (optimization)
656 Sequence
<Property
> maLastPropertySeq
;
657 sal_Int32 mnLastPropertyConcept
;
659 // Last Sequence that came with getMethods (optimization)
660 Sequence
<Reference
<XIdlMethod
> > maLastMethodSeq
;
661 sal_Int32 mnLastMethodConcept
;
663 // Guards the caching of queried interfaces
666 // Original interfaces of the objects
667 Reference
<XElementAccess
> mxObjElementAccess
;
668 Reference
<XNameContainer
> mxObjNameContainer
;
669 Reference
<XNameReplace
> mxObjNameReplace
;
670 Reference
<XNameAccess
> mxObjNameAccess
;
671 Reference
<XIndexContainer
> mxObjIndexContainer
;
672 Reference
<XIndexReplace
> mxObjIndexReplace
;
673 Reference
<XIndexAccess
> mxObjIndexAccess
;
674 Reference
<XEnumerationAccess
> mxObjEnumerationAccess
;
675 Reference
<XIdlArray
> mxObjIdlArray
;
677 Reference
<XElementAccess
> getXElementAccess();
678 Reference
<XNameContainer
> getXNameContainer();
679 Reference
<XNameReplace
> getXNameReplace();
680 Reference
<XNameAccess
> getXNameAccess();
681 Reference
<XIndexContainer
> getXIndexContainer();
682 Reference
<XIndexReplace
> getXIndexReplace();
683 Reference
<XIndexAccess
> getXIndexAccess();
684 Reference
<XEnumerationAccess
> getXEnumerationAccess();
685 Reference
<XIdlArray
> getXIdlArray();
687 void cacheXNameContainer();
688 void cacheXIndexContainer();
691 ImplIntrospectionAccess( Any obj
, rtl::Reference
< IntrospectionAccessStatic_Impl
> pStaticImpl_
);
693 // Methods from XIntrospectionAccess
694 virtual sal_Int32 SAL_CALL
getSuppliedMethodConcepts() override
;
695 virtual sal_Int32 SAL_CALL
getSuppliedPropertyConcepts() override
;
696 virtual Property SAL_CALL
getProperty(const OUString
& Name
, sal_Int32 PropertyConcepts
) override
;
697 virtual sal_Bool SAL_CALL
hasProperty(const OUString
& Name
, sal_Int32 PropertyConcepts
) override
;
698 virtual Sequence
< Property
> SAL_CALL
getProperties(sal_Int32 PropertyConcepts
) override
;
699 virtual Reference
<XIdlMethod
> SAL_CALL
getMethod(const OUString
& Name
, sal_Int32 MethodConcepts
) override
;
700 virtual sal_Bool SAL_CALL
hasMethod(const OUString
& Name
, sal_Int32 MethodConcepts
) override
;
701 virtual Sequence
< Reference
<XIdlMethod
> > SAL_CALL
getMethods(sal_Int32 MethodConcepts
) override
;
702 virtual Sequence
< Type
> SAL_CALL
getSupportedListeners() override
;
703 using OWeakObject::queryAdapter
;
704 virtual Reference
<XInterface
> SAL_CALL
queryAdapter( const Type
& rType
) override
;
706 // Methods from XMaterialHolder
707 virtual Any SAL_CALL
getMaterial() override
;
709 // Methods from XExactName
710 virtual OUString SAL_CALL
getExactName( const OUString
& rApproximateName
) override
;
712 // Methods from XInterface
713 virtual Any SAL_CALL
queryInterface( const Type
& rType
) override
;
714 virtual void SAL_CALL
acquire() noexcept override
{ OWeakObject::acquire(); }
715 virtual void SAL_CALL
release() noexcept override
{ OWeakObject::release(); }
717 // Methods from XPropertySet
718 virtual Reference
<XPropertySetInfo
> SAL_CALL
getPropertySetInfo() override
;
719 virtual void SAL_CALL
setPropertyValue(const OUString
& aPropertyName
, const Any
& aValue
) override
;
720 virtual Any SAL_CALL
getPropertyValue(const OUString
& aPropertyName
) override
;
721 virtual void SAL_CALL
addPropertyChangeListener(const OUString
& aPropertyName
, const Reference
<XPropertyChangeListener
>& aListener
) override
;
722 virtual void SAL_CALL
removePropertyChangeListener(const OUString
& aPropertyName
, const Reference
<XPropertyChangeListener
>& aListener
) override
;
723 virtual void SAL_CALL
addVetoableChangeListener(const OUString
& aPropertyName
, const Reference
<XVetoableChangeListener
>& aListener
) override
;
724 virtual void SAL_CALL
removeVetoableChangeListener(const OUString
& aPropertyName
, const Reference
<XVetoableChangeListener
>& aListener
) override
;
726 // Methods from XFastPropertySet
727 virtual void SAL_CALL
setFastPropertyValue(sal_Int32 nHandle
, const Any
& aValue
) override
;
728 virtual Any SAL_CALL
getFastPropertyValue(sal_Int32 nHandle
) override
;
730 // Methods from XPropertySetInfo
731 virtual Sequence
< Property
> SAL_CALL
getProperties() override
;
732 virtual Property SAL_CALL
getPropertyByName(const OUString
& Name
) override
;
733 virtual sal_Bool SAL_CALL
hasPropertyByName(const OUString
& Name
) override
;
735 // Methods from XElementAccess
736 virtual Type SAL_CALL
getElementType() override
;
737 virtual sal_Bool SAL_CALL
hasElements() override
;
739 // Methods from XNameAccess
740 virtual Any SAL_CALL
getByName(const OUString
& Name
) override
;
741 virtual Sequence
< OUString
> SAL_CALL
getElementNames() override
;
742 virtual sal_Bool SAL_CALL
hasByName(const OUString
& Name
) override
;
744 // Methods from XNameReplace
745 virtual void SAL_CALL
replaceByName(const OUString
& Name
, const Any
& Element
) override
;
747 // Methods from XNameContainer
748 virtual void SAL_CALL
insertByName(const OUString
& Name
, const Any
& Element
) override
;
749 virtual void SAL_CALL
removeByName(const OUString
& Name
) override
;
751 // Methods from XIndexAccess
752 virtual sal_Int32 SAL_CALL
getCount() override
;
753 virtual Any SAL_CALL
getByIndex(sal_Int32 Index
) override
;
755 // Methods from XIndexReplace
756 virtual void SAL_CALL
replaceByIndex(sal_Int32 Index
, const Any
& Element
) override
;
758 // Methods from XIndexContainer
759 virtual void SAL_CALL
insertByIndex(sal_Int32 Index
, const Any
& Element
) override
;
760 virtual void SAL_CALL
removeByIndex(sal_Int32 Index
) override
;
762 // Methods from XEnumerationAccess
763 virtual Reference
<XEnumeration
> SAL_CALL
createEnumeration() override
;
765 // Methods from XIdlArray
766 virtual void SAL_CALL
realloc(Any
& array
, sal_Int32 length
) override
;
767 virtual sal_Int32 SAL_CALL
getLen(const Any
& array
) override
;
768 virtual Any SAL_CALL
get(const Any
& array
, sal_Int32 index
) override
;
769 virtual void SAL_CALL
set(Any
& array
, sal_Int32 index
, const Any
& value
) override
;
771 // Methods from XUnoTunnel
772 virtual sal_Int64 SAL_CALL
getSomething( const Sequence
< sal_Int8
>& aIdentifier
) override
;
775 ImplIntrospectionAccess::ImplIntrospectionAccess
776 ( Any obj
, rtl::Reference
< IntrospectionAccessStatic_Impl
> pStaticImpl_
)
777 : maInspectedObject(std::move( obj
)), mpStaticImpl(std::move( pStaticImpl_
)) ,
778 mnLastPropertyConcept(-1), mnLastMethodConcept(-1) //, maAdapter()
780 // Save object as an interface if possible
781 maInspectedObject
>>= mxIface
;
784 Reference
<XElementAccess
> ImplIntrospectionAccess::getXElementAccess()
786 std::unique_lock
aGuard( m_aMutex
);
788 if( !mxObjElementAccess
.is() )
791 Reference
<XElementAccess
> xElementAccess( mxIface
, UNO_QUERY
);
793 if( !mxObjElementAccess
.is() )
794 mxObjElementAccess
= xElementAccess
;
796 return mxObjElementAccess
;
799 void ImplIntrospectionAccess::cacheXNameContainer()
801 Reference
<XNameContainer
> xNameContainer
;
802 Reference
<XNameReplace
> xNameReplace
;
803 Reference
<XNameAccess
> xNameAccess
;
804 if (mpStaticImpl
->mbNameContainer
)
806 xNameContainer
.set( mxIface
, UNO_QUERY
);
807 xNameReplace
= xNameContainer
;
808 xNameAccess
= xNameContainer
;
810 else if (mpStaticImpl
->mbNameReplace
)
812 xNameReplace
.set( mxIface
, UNO_QUERY
);
813 xNameAccess
= xNameReplace
;
815 else if (mpStaticImpl
->mbNameAccess
)
817 xNameAccess
.set( mxIface
, UNO_QUERY
);
821 std::unique_lock
aGuard( m_aMutex
);
822 if( !mxObjNameContainer
.is() )
823 mxObjNameContainer
= xNameContainer
;
824 if( !mxObjNameReplace
.is() )
825 mxObjNameReplace
= xNameReplace
;
826 if( !mxObjNameAccess
.is() )
827 mxObjNameAccess
= xNameAccess
;
831 Reference
<XNameContainer
> ImplIntrospectionAccess::getXNameContainer()
833 std::unique_lock
aGuard( m_aMutex
);
835 if( !mxObjNameContainer
.is() )
838 cacheXNameContainer();
840 return mxObjNameContainer
;
843 Reference
<XNameReplace
> ImplIntrospectionAccess::getXNameReplace()
845 std::unique_lock
aGuard( m_aMutex
);
847 if( !mxObjNameReplace
.is() )
850 cacheXNameContainer();
852 return mxObjNameReplace
;
855 Reference
<XNameAccess
> ImplIntrospectionAccess::getXNameAccess()
857 std::unique_lock
aGuard( m_aMutex
);
859 if( !mxObjNameAccess
.is() )
862 cacheXNameContainer();
864 return mxObjNameAccess
;
867 void ImplIntrospectionAccess::cacheXIndexContainer()
869 Reference
<XIndexContainer
> xIndexContainer
;
870 Reference
<XIndexReplace
> xIndexReplace
;
871 Reference
<XIndexAccess
> xIndexAccess
;
872 if (mpStaticImpl
->mbIndexContainer
)
874 xIndexContainer
.set( mxIface
, UNO_QUERY
);
875 xIndexReplace
= xIndexContainer
;
876 xIndexAccess
= xIndexContainer
;
878 else if (mpStaticImpl
->mbIndexReplace
)
880 xIndexReplace
.set( mxIface
, UNO_QUERY
);
881 xIndexAccess
= xIndexReplace
;
883 else if (mpStaticImpl
->mbIndexAccess
)
885 xIndexAccess
.set( mxIface
, UNO_QUERY
);
889 std::unique_lock
aGuard( m_aMutex
);
890 if( !mxObjIndexContainer
.is() )
891 mxObjIndexContainer
= xIndexContainer
;
892 if( !mxObjIndexReplace
.is() )
893 mxObjIndexReplace
= xIndexReplace
;
894 if( !mxObjIndexAccess
.is() )
895 mxObjIndexAccess
= xIndexAccess
;
899 Reference
<XIndexContainer
> ImplIntrospectionAccess::getXIndexContainer()
901 std::unique_lock
aGuard( m_aMutex
);
903 if( !mxObjIndexContainer
.is() )
906 cacheXIndexContainer();
908 return mxObjIndexContainer
;
911 Reference
<XIndexReplace
> ImplIntrospectionAccess::getXIndexReplace()
913 std::unique_lock
aGuard( m_aMutex
);
915 if( !mxObjIndexReplace
.is() )
918 cacheXIndexContainer();
920 return mxObjIndexReplace
;
923 Reference
<XIndexAccess
> ImplIntrospectionAccess::getXIndexAccess()
925 std::unique_lock
aGuard( m_aMutex
);
927 if( !mxObjIndexAccess
.is() )
930 cacheXIndexContainer();
932 return mxObjIndexAccess
;
935 Reference
<XEnumerationAccess
> ImplIntrospectionAccess::getXEnumerationAccess()
937 std::unique_lock
aGuard( m_aMutex
);
939 if( !mxObjEnumerationAccess
.is() )
942 Reference
<XEnumerationAccess
> xEnumerationAccess( mxIface
, UNO_QUERY
);
944 if( !mxObjEnumerationAccess
.is() )
945 mxObjEnumerationAccess
= xEnumerationAccess
;
947 return mxObjEnumerationAccess
;
950 Reference
<XIdlArray
> ImplIntrospectionAccess::getXIdlArray()
952 std::unique_lock
aGuard( m_aMutex
);
954 if( !mxObjIdlArray
.is() )
957 Reference
<XIdlArray
> xIdlArray( mxIface
, UNO_QUERY
);
959 if( !mxObjIdlArray
.is() )
960 mxObjIdlArray
= xIdlArray
;
962 return mxObjIdlArray
;
965 // Methods from XInterface
966 Any SAL_CALL
ImplIntrospectionAccess::queryInterface( const Type
& rType
)
968 Any
aRet( ::cppu::queryInterface(
970 static_cast< XIntrospectionAccess
* >( this ),
971 static_cast< XMaterialHolder
* >( this ),
972 static_cast< XExactName
* >( this ),
973 static_cast< XPropertySet
* >( this ),
974 static_cast< XFastPropertySet
* >( this ),
975 static_cast< XPropertySetInfo
* >( this ) ) );
976 if( !aRet
.hasValue() )
977 aRet
= OWeakObject::queryInterface( rType
);
979 if( !aRet
.hasValue() )
981 // Wrapper for the object interfaces
982 ( mpStaticImpl
->mbElementAccess
&& (aRet
= ::cppu::queryInterface
983 ( rType
, static_cast< XElementAccess
* >( static_cast< XNameAccess
* >( this ) ) ) ).hasValue() )
984 || ( mpStaticImpl
->mbNameAccess
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XNameAccess
* >( this ) ) ).hasValue() )
985 || ( mpStaticImpl
->mbNameReplace
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XNameReplace
* >( this ) ) ).hasValue() )
986 || ( mpStaticImpl
->mbNameContainer
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XNameContainer
* >( this ) ) ).hasValue() )
987 || ( mpStaticImpl
->mbIndexAccess
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XIndexAccess
* >( this ) ) ).hasValue() )
988 || ( mpStaticImpl
->mbIndexReplace
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XIndexReplace
* >( this ) ) ).hasValue() )
989 || ( mpStaticImpl
->mbIndexContainer
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XIndexContainer
* >( this ) ) ).hasValue() )
990 || ( mpStaticImpl
->mbEnumerationAccess
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XEnumerationAccess
* >( this ) ) ).hasValue() )
991 || ( mpStaticImpl
->mbIdlArray
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XIdlArray
* >( this ) ) ).hasValue() )
992 || ( mpStaticImpl
->mbUnoTunnel
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XUnoTunnel
* >( this ) ) ).hasValue() );
998 //*** Implementation of ImplIntrospectionAdapter ***
1001 // Methods from XPropertySet
1002 Reference
<XPropertySetInfo
> ImplIntrospectionAccess::getPropertySetInfo()
1004 return static_cast<XPropertySetInfo
*>(this);
1007 void ImplIntrospectionAccess::setPropertyValue(const OUString
& aPropertyName
, const Any
& aValue
)
1009 mpStaticImpl
->setPropertyValue( maInspectedObject
, aPropertyName
, aValue
);
1012 Any
ImplIntrospectionAccess::getPropertyValue(const OUString
& aPropertyName
)
1014 return mpStaticImpl
->getPropertyValue( maInspectedObject
, aPropertyName
);
1017 void ImplIntrospectionAccess::addPropertyChangeListener(const OUString
& aPropertyName
, const Reference
<XPropertyChangeListener
>& aListener
)
1021 Reference
<XPropertySet
> xPropSet
=
1022 Reference
<XPropertySet
>::query( mxIface
);
1023 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1025 xPropSet
->addPropertyChangeListener(aPropertyName
, aListener
);
1029 void ImplIntrospectionAccess::removePropertyChangeListener(const OUString
& aPropertyName
, const Reference
<XPropertyChangeListener
>& aListener
)
1033 Reference
<XPropertySet
> xPropSet
=
1034 Reference
<XPropertySet
>::query( mxIface
);
1035 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1037 xPropSet
->removePropertyChangeListener(aPropertyName
, aListener
);
1041 void ImplIntrospectionAccess::addVetoableChangeListener(const OUString
& aPropertyName
, const Reference
<XVetoableChangeListener
>& aListener
)
1045 Reference
<XPropertySet
> xPropSet
=
1046 Reference
<XPropertySet
>::query( mxIface
);
1047 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1049 xPropSet
->addVetoableChangeListener(aPropertyName
, aListener
);
1053 void ImplIntrospectionAccess::removeVetoableChangeListener(const OUString
& aPropertyName
, const Reference
<XVetoableChangeListener
>& aListener
)
1057 Reference
<XPropertySet
> xPropSet
=
1058 Reference
<XPropertySet
>::query( mxIface
);
1060 xPropSet
->removeVetoableChangeListener(aPropertyName
, aListener
);
1065 // Methods from XFastPropertySet
1066 void ImplIntrospectionAccess::setFastPropertyValue(sal_Int32
, const Any
&)
1070 Any
ImplIntrospectionAccess::getFastPropertyValue(sal_Int32
)
1075 // Methods from XPropertySetInfo
1076 Sequence
< Property
> ImplIntrospectionAccess::getProperties()
1078 return comphelper::containerToSequence(mpStaticImpl
->getProperties());
1081 Property
ImplIntrospectionAccess::getPropertyByName(const OUString
& Name
)
1083 return getProperty( Name
, PropertyConcept::ALL
);
1086 sal_Bool
ImplIntrospectionAccess::hasPropertyByName(const OUString
& Name
)
1088 return hasProperty( Name
, PropertyConcept::ALL
);
1091 // Methods from XElementAccess
1092 Type
ImplIntrospectionAccess::getElementType()
1094 return getXElementAccess()->getElementType();
1097 sal_Bool
ImplIntrospectionAccess::hasElements()
1099 return getXElementAccess()->hasElements();
1102 // Methods from XNameAccess
1103 Any
ImplIntrospectionAccess::getByName(const OUString
& Name
)
1105 return getXNameAccess()->getByName( Name
);
1108 Sequence
< OUString
> ImplIntrospectionAccess::getElementNames()
1110 return getXNameAccess()->getElementNames();
1113 sal_Bool
ImplIntrospectionAccess::hasByName(const OUString
& Name
)
1115 return getXNameAccess()->hasByName( Name
);
1118 // Methods from XNameContainer
1119 void ImplIntrospectionAccess::insertByName(const OUString
& Name
, const Any
& Element
)
1121 getXNameContainer()->insertByName( Name
, Element
);
1124 void ImplIntrospectionAccess::replaceByName(const OUString
& Name
, const Any
& Element
)
1126 getXNameReplace()->replaceByName( Name
, Element
);
1129 void ImplIntrospectionAccess::removeByName(const OUString
& Name
)
1131 getXNameContainer()->removeByName( Name
);
1134 // Methods from XIndexAccess
1135 // Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const
1136 sal_Int32
ImplIntrospectionAccess::getCount()
1138 return getXIndexAccess()->getCount();
1141 Any
ImplIntrospectionAccess::getByIndex(sal_Int32 Index
)
1143 return getXIndexAccess()->getByIndex( Index
);
1146 // Methods from XIndexContainer
1147 void ImplIntrospectionAccess::insertByIndex(sal_Int32 Index
, const Any
& Element
)
1149 getXIndexContainer()->insertByIndex( Index
, Element
);
1152 void ImplIntrospectionAccess::replaceByIndex(sal_Int32 Index
, const Any
& Element
)
1154 getXIndexReplace()->replaceByIndex( Index
, Element
);
1157 void ImplIntrospectionAccess::removeByIndex(sal_Int32 Index
)
1159 getXIndexContainer()->removeByIndex( Index
);
1162 // Methods from XEnumerationAccess
1163 // Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const;
1164 Reference
<XEnumeration
> ImplIntrospectionAccess::createEnumeration()
1166 return getXEnumerationAccess()->createEnumeration();
1169 // Methods from XIdlArray
1170 void ImplIntrospectionAccess::realloc(Any
& array
, sal_Int32 length
)
1172 getXIdlArray()->realloc( array
, length
);
1175 sal_Int32
ImplIntrospectionAccess::getLen(const Any
& array
)
1177 return getXIdlArray()->getLen( array
);
1180 Any
ImplIntrospectionAccess::get(const Any
& array
, sal_Int32 index
)
1182 return getXIdlArray()->get( array
, index
);
1185 void ImplIntrospectionAccess::set(Any
& array
, sal_Int32 index
, const Any
& value
)
1187 getXIdlArray()->set( array
, index
, value
);
1190 // Methods from XUnoTunnel
1191 sal_Int64
ImplIntrospectionAccess::getSomething( const Sequence
< sal_Int8
>& aIdentifier
)
1193 if (Reference
<XUnoTunnel
> xUnoTunnel
{ mxIface
, css::uno::UNO_QUERY
})
1194 return xUnoTunnel
->getSomething(aIdentifier
);
1199 //*** Implementation of ImplIntrospectionAccess ***
1201 // Methods from XIntrospectionAccess
1202 sal_Int32
ImplIntrospectionAccess::getSuppliedMethodConcepts()
1204 return MethodConcept::DANGEROUS
|
1212 sal_Int32
ImplIntrospectionAccess::getSuppliedPropertyConcepts()
1214 return PropertyConcept::DANGEROUS
|
1220 Property
ImplIntrospectionAccess::getProperty(const OUString
& Name
, sal_Int32 PropertyConcepts
)
1223 sal_Int32 i
= mpStaticImpl
->getPropertyIndex( Name
);
1224 bool bFound
= false;
1227 sal_Int32 nConcept
= mpStaticImpl
->getPropertyConcepts()[ i
];
1228 if( (PropertyConcepts
& nConcept
) != 0 )
1230 aRet
= mpStaticImpl
->getProperties()[ i
];
1235 throw NoSuchElementException(Name
);
1239 sal_Bool
ImplIntrospectionAccess::hasProperty(const OUString
& Name
, sal_Int32 PropertyConcepts
)
1241 sal_Int32 i
= mpStaticImpl
->getPropertyIndex( Name
);
1245 sal_Int32 nConcept
= mpStaticImpl
->getPropertyConcepts()[ i
];
1246 if( (PropertyConcepts
& nConcept
) != 0 )
1252 Sequence
< Property
> ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts
)
1254 // If all supported concepts are required, simply pass through the sequence
1255 sal_Int32 nAllSupportedMask
= PROPERTYSET
|
1258 if( ( PropertyConcepts
& nAllSupportedMask
) == nAllSupportedMask
)
1260 return comphelper::containerToSequence(mpStaticImpl
->getProperties());
1263 // Same sequence as last time?
1264 if( mnLastPropertyConcept
== PropertyConcepts
)
1266 return maLastPropertySeq
;
1269 // Number of properties to be delivered
1270 sal_Int32 nCount
= 0;
1272 // There are currently no DANGEROUS properties
1273 // if( PropertyConcepts & DANGEROUS )
1274 // nCount += mpStaticImpl->mnDangerousPropCount;
1275 if( PropertyConcepts
& PROPERTYSET
)
1276 nCount
+= mpStaticImpl
->mnPropertySetPropCount
;
1277 if( PropertyConcepts
& ATTRIBUTES
)
1278 nCount
+= mpStaticImpl
->mnAttributePropCount
;
1279 if( PropertyConcepts
& METHODS
)
1280 nCount
+= mpStaticImpl
->mnMethodPropCount
;
1282 // Realloc sequence according to the required number
1283 maLastPropertySeq
.realloc( nCount
);
1284 Property
* pDestProps
= maLastPropertySeq
.getArray();
1286 // Go through all the properties and apply according to the concept
1287 const std::vector
<Property
>& rPropSeq
= mpStaticImpl
->getProperties();
1288 const std::vector
<sal_Int32
>& rConcepts
= mpStaticImpl
->getPropertyConcepts();
1289 sal_Int32 nLen
= static_cast<sal_Int32
>(rPropSeq
.size());
1291 sal_Int32 iDest
= 0;
1292 for( sal_Int32 i
= 0 ; i
< nLen
; i
++ )
1294 sal_Int32 nConcept
= rConcepts
[ i
];
1295 if( nConcept
& PropertyConcepts
)
1296 pDestProps
[ iDest
++ ] = rPropSeq
[ i
];
1299 // Remember PropertyConcept representing maLastPropertySeq
1300 mnLastPropertyConcept
= PropertyConcepts
;
1302 // Supply assembled Sequence
1303 return maLastPropertySeq
;
1306 Reference
<XIdlMethod
> ImplIntrospectionAccess::getMethod(const OUString
& Name
, sal_Int32 MethodConcepts
)
1308 Reference
<XIdlMethod
> xRet
;
1309 sal_Int32 i
= mpStaticImpl
->getMethodIndex( Name
);
1313 sal_Int32 nConcept
= mpStaticImpl
->getMethodConcepts()[ i
];
1314 if( (MethodConcepts
& nConcept
) != 0 )
1316 xRet
= mpStaticImpl
->getMethods()[i
];
1320 throw NoSuchMethodException(Name
);
1324 sal_Bool
ImplIntrospectionAccess::hasMethod(const OUString
& Name
, sal_Int32 MethodConcepts
)
1326 sal_Int32 i
= mpStaticImpl
->getMethodIndex( Name
);
1330 sal_Int32 nConcept
= mpStaticImpl
->getMethodConcepts()[ i
];
1331 if( (MethodConcepts
& nConcept
) != 0 )
1337 Sequence
< Reference
<XIdlMethod
> > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts
)
1339 // If all supported concepts are required, simply pass through the sequence
1340 sal_Int32 nAllSupportedMask
= MethodConcept::DANGEROUS
|
1346 MethodConcept_NORMAL_IMPL
;
1347 if( ( MethodConcepts
& nAllSupportedMask
) == nAllSupportedMask
)
1349 return comphelper::containerToSequence(mpStaticImpl
->getMethods());
1352 // Same sequence as last time?
1353 if( mnLastMethodConcept
== MethodConcepts
)
1355 return maLastMethodSeq
;
1358 // Get method sequences
1359 const std::vector
< Reference
<XIdlMethod
> >& aMethodSeq
= mpStaticImpl
->getMethods();
1360 sal_Int32 nLen
= static_cast<sal_Int32
>(aMethodSeq
.size());
1362 // Realloc sequence according to the required number
1363 // Unlike Properties, the number can not be determined by counters in
1364 // inspect() beforehand, since methods can belong to several concepts
1365 maLastMethodSeq
.realloc( nLen
);
1366 Reference
<XIdlMethod
>* pDestMethods
= maLastMethodSeq
.getArray();
1368 // Go through all the methods and apply according to the concept
1369 sal_Int32 iDest
= 0;
1370 for( sal_Int32 i
= 0 ; i
< nLen
; i
++ )
1372 sal_Int32 nConcept
= mpStaticImpl
->getMethodConcepts()[ i
];
1373 if( nConcept
& MethodConcepts
)
1374 pDestMethods
[ iDest
++ ] = aMethodSeq
[ i
];
1377 // Bring to the correct length
1378 maLastMethodSeq
.realloc( iDest
);
1380 // Remember MethodConcept representing maLastMethodSeq
1381 mnLastMethodConcept
= MethodConcepts
;
1383 // Supply assembled Sequence
1384 return maLastMethodSeq
;
1387 Sequence
< Type
> ImplIntrospectionAccess::getSupportedListeners()
1389 return comphelper::containerToSequence(mpStaticImpl
->getSupportedListeners());
1392 Reference
<XInterface
> SAL_CALL
ImplIntrospectionAccess::queryAdapter( const Type
& rType
)
1394 Reference
<XInterface
> xRet
;
1395 if( rType
== cppu::UnoType
<XInterface
>::get()
1396 || rType
== cppu::UnoType
<XPropertySet
>::get()
1397 || rType
== cppu::UnoType
<XFastPropertySet
>::get()
1398 || rType
== cppu::UnoType
<XPropertySetInfo
>::get()
1399 || rType
== cppu::UnoType
<XElementAccess
>::get()
1400 || rType
== cppu::UnoType
<XNameAccess
>::get()
1401 || rType
== cppu::UnoType
<XNameReplace
>::get()
1402 || rType
== cppu::UnoType
<XNameContainer
>::get()
1403 || rType
== cppu::UnoType
<XIndexAccess
>::get()
1404 || rType
== cppu::UnoType
<XIndexReplace
>::get()
1405 || rType
== cppu::UnoType
<XIndexContainer
>::get()
1406 || rType
== cppu::UnoType
<XEnumerationAccess
>::get()
1407 || rType
== cppu::UnoType
<XIdlArray
>::get()
1408 || rType
== cppu::UnoType
<XUnoTunnel
>::get() )
1410 queryInterface( rType
) >>= xRet
;
1415 // Methods from XMaterialHolder
1416 Any
ImplIntrospectionAccess::getMaterial()
1418 return maInspectedObject
;
1421 // Methods from XExactName
1422 OUString
ImplIntrospectionAccess::getExactName( const OUString
& rApproximateName
)
1425 LowerToExactNameMap::iterator aIt
=
1426 mpStaticImpl
->maLowerToExactNameMap
.find( rApproximateName
.toAsciiLowerCase() );
1427 if (aIt
!= mpStaticImpl
->maLowerToExactNameMap
.end())
1428 aRetStr
= (*aIt
).second
;
1434 css::uno::Reference
<css::beans::XPropertySetInfo
> theProperties
,
1435 std::vector
<css::uno::Type
> const & theTypes
):
1436 properties(std::move(theProperties
))
1438 //TODO: Could even sort the types lexicographically first, to increase
1439 // the chance of matches between different implementations' getTypes(),
1440 // but the old scheme of using getImplementationId() would have missed
1441 // those matches, too:
1442 OUStringBuffer
b(static_cast<int>(theTypes
.size() * 64));
1443 for (const css::uno::Type
& rType
: theTypes
) {
1444 b
.append(rType
.getTypeName()
1445 + "*"); // arbitrary delimiter not used by type grammar
1447 types
= b
.makeStringAndClear();
1450 css::uno::Reference
<css::beans::XPropertySetInfo
> properties
;
1454 struct TypeKeyLess
{
1455 bool operator ()(TypeKey
const & key1
, TypeKey
const & key2
) const {
1456 if (key1
.properties
.get() < key2
.properties
.get()) {
1459 if (key1
.properties
.get() > key2
.properties
.get()) {
1462 return key1
.types
< key2
.types
;
1466 template<typename Key
, typename Less
> class Cache
{
1468 rtl::Reference
<IntrospectionAccessStatic_Impl
> find(Key
const & key
) const {
1469 typename
Map::const_iterator
i(map_
.find(key
));
1470 if (i
== map_
.end()) {
1471 return rtl::Reference
<IntrospectionAccessStatic_Impl
>();
1473 if (i
->second
.hits
< std::numeric_limits
<unsigned>::max()) {
1476 assert(i
->second
.access
.is());
1477 return i
->second
.access
;
1483 rtl::Reference
<IntrospectionAccessStatic_Impl
> const & access
)
1485 assert(access
.is());
1486 typename
Map::size_type
const MAX
= 100;
1487 assert(map_
.size() <= MAX
);
1488 if (map_
.size() == MAX
) {
1489 typename
Map::iterator del
= std::min_element(map_
.begin(), map_
.end(),
1490 [](const typename
Map::value_type
& a
, const typename
Map::value_type
& b
) {
1491 return a
.second
.hits
< b
.second
.hits
;
1495 bool ins
= map_
.emplace(key
, Data(access
)).second
;
1496 assert(ins
); (void)ins
;
1499 void clear() { map_
.clear(); }
1504 rtl::Reference
<IntrospectionAccessStatic_Impl
> theAccess
):
1505 access(std::move(theAccess
)), hits(1)
1508 rtl::Reference
<IntrospectionAccessStatic_Impl
> access
;
1509 mutable unsigned hits
;
1512 typedef std::map
<Key
, Data
, Less
> Map
;
1518 cppu::WeakComponentImplHelper
<
1519 css::lang::XServiceInfo
, css::beans::XIntrospection
>
1520 Implementation_Base
;
1522 class Implementation
: private cppu::BaseMutex
, public Implementation_Base
{
1524 explicit Implementation(
1525 css::uno::Reference
<css::uno::XComponentContext
> const & context
):
1526 Implementation_Base(m_aMutex
),
1527 reflection_(css::reflection::theCoreReflection::get(context
))
1531 virtual void SAL_CALL
disposing() override
{
1532 osl::MutexGuard
g(m_aMutex
);
1533 reflection_
.clear();
1537 virtual OUString SAL_CALL
getImplementationName() override
1538 { return "com.sun.star.comp.stoc.Introspection"; }
1540 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
1541 { return cppu::supportsService(this, ServiceName
); }
1543 virtual css::uno::Sequence
<OUString
> SAL_CALL
1544 getSupportedServiceNames() override
1546 Sequence
<OUString
> s
{ "com.sun.star.beans.Introspection" };
1550 virtual css::uno::Reference
<css::beans::XIntrospectionAccess
> SAL_CALL
1551 inspect(css::uno::Any
const & aObject
) override
;
1553 css::uno::Reference
<css::reflection::XIdlReflection
> reflection_
;
1554 Cache
<TypeKey
, TypeKeyLess
> typeCache_
;
1557 css::uno::Reference
<css::beans::XIntrospectionAccess
> Implementation::inspect(
1558 css::uno::Any
const & aObject
)
1560 css::uno::Reference
<css::reflection::XIdlReflection
> reflection
;
1562 osl::MutexGuard
g(m_aMutex
);
1563 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
) {
1564 throw css::lang::DisposedException(
1565 getImplementationName(), static_cast<OWeakObject
*>(this));
1567 reflection
= reflection_
;
1569 css::uno::Any aToInspectObj
;
1571 if (aObject
>>= t
) {
1572 css::uno::Reference
<css::reflection::XIdlClass
> c(
1573 reflection
->forName(t
.getTypeName()));
1575 SAL_WARN("stoc", "cannot reflect type " << t
.getTypeName());
1576 return css::uno::Reference
<css::beans::XIntrospectionAccess
>();
1578 aToInspectObj
<<= c
;
1580 aToInspectObj
= aObject
;
1584 TypeClass eType
= aToInspectObj
.getValueType().getTypeClass();
1585 if( eType
!= TypeClass_INTERFACE
&& eType
!= TypeClass_STRUCT
&& eType
!= TypeClass_EXCEPTION
)
1586 return css::uno::Reference
<css::beans::XIntrospectionAccess
>();
1588 if( auto x
= o3tl::tryAccess
<Reference
<XInterface
>>(aToInspectObj
) )
1591 return css::uno::Reference
<css::beans::XIntrospectionAccess
>();
1594 // Pointer to possibly needed new IntrospectionAccessStatic_Impl instance
1595 rtl::Reference
< IntrospectionAccessStatic_Impl
> pAccess
;
1597 // Check: Is a matching access object already cached?
1598 std::vector
< Reference
<XIdlClass
> > SupportedClassSeq
;
1599 std::vector
< Type
> SupportedTypesSeq
;
1600 Reference
<XTypeProvider
> xTypeProvider
;
1601 Reference
<XPropertySetInfo
> xPropSetInfo
;
1602 Reference
<XPropertySet
> xPropSet
;
1604 // Look for interfaces XTypeProvider and PropertySet
1605 if( eType
== TypeClass_INTERFACE
)
1607 xTypeProvider
.set( aToInspectObj
, UNO_QUERY
);
1608 if( xTypeProvider
.is() )
1610 SupportedTypesSeq
= comphelper::sequenceToContainer
<std::vector
<Type
>>(xTypeProvider
->getTypes());
1614 "object of type \"" << aToInspectObj
.getValueTypeName()
1615 << "\" lacks XTypeProvider");
1616 SupportedTypesSeq
= { aToInspectObj
.getValueType() };
1618 // Now try to get the PropertySetInfo
1619 xPropSet
.set( aToInspectObj
, UNO_QUERY
);
1621 xPropSetInfo
= xPropSet
->getPropertySetInfo();
1624 SupportedTypesSeq
= { aToInspectObj
.getValueType() };
1628 osl::MutexGuard
g(m_aMutex
);
1629 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
) {
1630 throw css::lang::DisposedException(
1631 getImplementationName(), static_cast<OWeakObject
*>(this));
1633 TypeKey
key(xPropSetInfo
, SupportedTypesSeq
);
1634 pAccess
= typeCache_
.find(key
);
1636 return new ImplIntrospectionAccess(aToInspectObj
, pAccess
);
1638 pAccess
= new IntrospectionAccessStatic_Impl(reflection
);
1639 typeCache_
.insert(key
, pAccess
);
1642 // No access cached -> create new
1643 std::vector
<Property
>& rAllPropArray
= pAccess
->maAllPropertySeq
;
1644 std::vector
<Reference
<XInterface
>>& rInterfaces1
= pAccess
->aInterfaceSeq1
;
1645 std::vector
<Reference
<XInterface
>>& rInterfaces2
= pAccess
->aInterfaceSeq2
;
1646 std::vector
<sal_Int16
>& rMapTypeArray
= pAccess
->maMapTypeSeq
;
1647 std::vector
<sal_Int32
>& rPropertyConceptArray
= pAccess
->maPropertyConceptSeq
;
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
;
1656 //*** Perform analysis ***
1658 if( eType
== TypeClass_INTERFACE
)
1660 size_t nTypeCount
= SupportedTypesSeq
.size();
1663 SupportedClassSeq
.resize( nTypeCount
);
1665 for( size_t i
= 0 ; i
< nTypeCount
; i
++ )
1666 SupportedClassSeq
[i
] = reflection
->forName( SupportedTypesSeq
[i
].getTypeName() );
1669 // First look for particular interfaces that are of particular
1670 // importance to the introspection
1672 // Is XPropertySet present?
1673 if( xPropSet
.is() && xPropSetInfo
.is() )
1675 // Is there also a FastPropertySet?
1676 Reference
<XFastPropertySet
> xDummy( aToInspectObj
, UNO_QUERY
);
1677 bool bFast
= pAccess
->mbFastPropSet
= xDummy
.is();
1679 Sequence
<Property
> aPropSeq
= xPropSetInfo
->getProperties();
1680 const Property
* pProps
= aPropSeq
.getConstArray();
1681 sal_Int32 nLen
= aPropSeq
.getLength();
1683 // For a FastPropertySet we must remember the original handles
1685 pAccess
->mpOrgPropertyHandleArray
.reset( new sal_Int32
[ nLen
] );
1687 for( sal_Int32 i
= 0 ; i
< nLen
; i
++ )
1689 // Put property in its own list
1690 pAccess
->checkPropertyArraysSize( rPropCount
);
1691 Property
& rProp
= rAllPropArray
[ rPropCount
];
1692 rProp
= pProps
[ i
];
1695 pAccess
->mpOrgPropertyHandleArray
[ i
] = rProp
.Handle
;
1697 // Enter PropCount as a handle for its own FastPropertySet
1698 rProp
.Handle
= rPropCount
;
1700 // Remember type of property
1701 rMapTypeArray
[ rPropCount
] = MAP_PROPERTY_SET
;
1702 rPropertyConceptArray
[ rPropCount
] = PROPERTYSET
;
1703 pAccess
->mnPropertySetPropCount
++;
1705 // Enter name in hash table if not already known
1706 OUString aPropName
= rProp
.Name
;
1708 // Do we already have the name?
1709 IntrospectionNameMap::iterator aIt
= rPropNameMap
.find( aPropName
);
1710 if( aIt
== rPropNameMap
.end() )
1712 // New entry in the hash table
1713 rPropNameMap
[ aPropName
] = rPropCount
;
1715 // Maintain table for XExactName
1716 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
1720 SAL_WARN( "stoc", "Introspection: Property \"" <<
1721 aPropName
<< "\" found more than once in PropertySet" );
1729 // Indices in the export table
1730 sal_Int32 iAllExportedMethod
= 0;
1731 sal_Int32 iAllSupportedListener
= 0;
1733 std::set
<OUString
> seen
;
1735 // Flag, whether XInterface methods should be recorded
1736 // (this must be done only once, allowed initially)
1737 bool bXInterfaceIsInvalid
= false;
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;
1744 size_t nClassCount
= SupportedClassSeq
.size();
1745 for( size_t nIdx
= 0 ; nIdx
< nClassCount
; nIdx
++ )
1747 Reference
<XIdlClass
> xImplClass2
= SupportedClassSeq
[nIdx
];
1748 while( xImplClass2
.is() )
1750 // Fetch interfaces from the implementation
1751 Sequence
< Reference
<XIdlClass
> > aClassSeq
= xImplClass2
->getInterfaces();
1752 sal_Int32 nIfaceCount
= aClassSeq
.getLength();
1754 aClassSeq
.realloc( nIfaceCount
+ 1 );
1755 aClassSeq
.getArray()[ nIfaceCount
] = xImplClass2
;
1757 for( const Reference
<XIdlClass
>& rxIfaceClass
: std::as_const(aClassSeq
) )
1759 if (!seen
.insert(rxIfaceClass
->getName()).second
) {
1763 // 2. Register fields as properties
1766 const Sequence
< Reference
<XIdlField
> > fields
= rxIfaceClass
->getFields();
1768 for( const Reference
<XIdlField
>& xField
: fields
)
1770 Reference
<XIdlClass
> xPropType
= xField
->getType();
1772 // Is the property sequence big enough?
1773 pAccess
->checkPropertyArraysSize( rPropCount
);
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
)
1787 // Enter name in hash table
1788 OUString aPropName
= rProp
.Name
;
1790 // Do we have the name already?
1791 IntrospectionNameMap::iterator aIt
= rPropNameMap
.find( aPropName
);
1792 if (aIt
!= rPropNameMap
.end())
1795 // New entry in the hash table
1796 rPropNameMap
[ aPropName
] = rPropCount
;
1798 // Maintain table for XExactName
1799 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
1802 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq1
,
1803 rInterfaces1
, rPropCount
);
1804 rInterfaces1
[ rPropCount
] = xField
;
1806 // Remember type of property
1807 rMapTypeArray
[ rPropCount
] = MAP_FIELD
;
1808 rPropertyConceptArray
[ rPropCount
] = ATTRIBUTES
;
1809 pAccess
->mnAttributePropCount
++;
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();
1823 // 3. a) Search get/set and listener methods
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
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
1836 std::unique_ptr
<MethodType
[]> pMethodTypes( new MethodType
[ nSourceMethodCount
] );
1837 std::unique_ptr
<sal_Int32
[]> pLocalMethodConcepts( new sal_Int32
[ nSourceMethodCount
] );
1838 for( sal_Int32 i
= 0 ; i
< nSourceMethodCount
; i
++ )
1840 pMethodTypes
[ i
] = STANDARD_METHOD
;
1841 pLocalMethodConcepts
[ i
] = 0;
1844 for( sal_Int32 i
= 0 ; i
< nSourceMethodCount
; i
++ )
1847 const Reference
<XIdlMethod
>& rxMethod_i
= pSourceMethods
[i
];
1848 sal_Int32
& rMethodConcept_i
= pLocalMethodConcepts
[ i
];
1851 OUString aMethName
= rxMethod_i
->getName();
1853 // Catalogue methods
1854 // Filter all (?) methods of XInterface so e.g. acquire and release
1855 // can not be called from scripting
1857 rxMethod_i
->getDeclaringClass()->getName());
1858 if (className
== "com.sun.star.uno.XInterface") {
1859 bFoundXInterface
= true;
1861 if( bXInterfaceIsInvalid
)
1863 pMethodTypes
[ i
] = INVALID_METHOD
;
1868 if( aMethName
!= "queryInterface" )
1870 rMethodConcept_i
|= MethodConcept::DANGEROUS
;
1874 } else if (className
== "com.sun.star.uno.XAggregation")
1876 if( aMethName
== "setDelegator" )
1878 rMethodConcept_i
|= MethodConcept::DANGEROUS
;
1881 } else if (className
1882 == "com.sun.star.container.XElementAccess")
1884 rMethodConcept_i
|= ( NAMECONTAINER
|
1887 pAccess
->mbElementAccess
= true;
1888 } else if (className
1889 == "com.sun.star.container.XNameContainer")
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")
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")
1906 rMethodConcept_i
|= NAMECONTAINER
;
1907 pAccess
->mbNameAccess
= true;
1908 pAccess
->mbElementAccess
= true;
1909 } else if (className
1910 == "com.sun.star.container.XIndexContainer")
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")
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")
1927 rMethodConcept_i
|= INDEXCONTAINER
;
1928 pAccess
->mbIndexAccess
= true;
1929 pAccess
->mbElementAccess
= true;
1930 } else if (className
1931 == "com.sun.star.container.XEnumerationAccess")
1933 rMethodConcept_i
|= ENUMERATION
;
1934 pAccess
->mbEnumerationAccess
= true;
1935 pAccess
->mbElementAccess
= true;
1936 } else if (className
1937 == "com.sun.star.reflection.XIdlArray")
1939 pAccess
->mbIdlArray
= true;
1940 } else if (className
1941 == "com.sun.star.lang.XUnoTunnel")
1943 pAccess
->mbUnoTunnel
= true;
1946 // If the name is too short, it isn't anything
1947 if( aMethName
.getLength() <= 3 )
1950 // Is it a get method?
1952 if( aMethName
.startsWith("get", &aPropName
) )
1954 // Get methods must not have any parameters
1955 Sequence
< Reference
<XIdlClass
> > getParams
= rxMethod_i
->getParameterTypes();
1956 if( getParams
.hasElements() )
1961 // Do we have the name already?
1962 IntrospectionNameMap::iterator aIt
= rPropNameMap
.find( aPropName
);
1963 if (aIt
!= rPropNameMap
.end())
1967 String( "Introspection: Property \"" ) +
1968 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
1969 String( "\" found more than once" ) );
1974 // It is already at least a read-only property
1975 rMethodConcept_i
|= PROPERTY
;
1977 pMethodTypes
[i
] = GETSET_METHOD
;
1978 Reference
<XIdlClass
> xGetRetType
= rxMethod_i
->getReturnType();
1980 // Is the property sequence big enough?
1981 pAccess
->checkPropertyArraysSize( rPropCount
);
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
;
1990 // New entry in the hash table
1991 rPropNameMap
[ aPropName
] = rPropCount
;
1993 // Maintain table for XExactName
1994 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
1996 // Remember get method
1997 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq1
,
1998 rInterfaces1
, rPropCount
);
1999 rInterfaces1
[ rPropCount
] = rxMethod_i
;
2001 // Remember type of property
2002 rMapTypeArray
[ rPropCount
] = MAP_GETSET
;
2003 rPropertyConceptArray
[ rPropCount
] = METHODS
;
2004 pAccess
->mnMethodPropCount
++;
2006 // Search for matching set method
2008 for( k
= 0 ; k
< nSourceMethodCount
; k
++ )
2011 const Reference
<XIdlMethod
>& rxMethod_k
= pSourceMethods
[k
];
2013 // Accept only methods that are not already assigned
2014 if( k
== i
|| pMethodTypes
[k
] != STANDARD_METHOD
)
2017 // Get name and evaluate
2018 OUString aMethName2
= rxMethod_k
->getName();
2019 OUString aPropName2
;
2020 if (!(aMethName2
.startsWith("set", &aPropName2
)
2021 && aPropName2
== aPropName
))
2024 // A set method must return void
2025 Reference
<XIdlClass
> xSetRetType
= rxMethod_k
->getReturnType();
2026 if( xSetRetType
->getTypeClass() != TypeClass_VOID
)
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 )
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
) )
2044 pLocalMethodConcepts
[ k
] = PROPERTY
;
2046 pMethodTypes
[k
] = GETSET_METHOD
;
2048 // Delete read-only flag again
2049 rProp
.Attributes
&= ~READONLY
;
2051 // Remember set method
2052 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq2
,
2053 rInterfaces2
, rPropCount
);
2054 rInterfaces2
[ rPropCount
] = rxMethod_k
;
2062 // Is it an add listener method?
2063 else if( aMethName
.startsWith("add", &aPropName
) )
2065 // Does it end with "Listener"?
2066 OUString aListenerName
;
2067 if( !aPropName
.endsWith("Listener", &aListenerName
) )
2070 // TODO: More accurate tests could still be carried out here
2072 // - Number and type of parameters
2075 // Search for matching remove method, otherwise not applicable
2077 for( k
= 0 ; k
< nSourceMethodCount
; k
++ )
2080 const Reference
<XIdlMethod
>& rxMethod_k
= pSourceMethods
[k
];
2082 // Accept only methods that are not already assigned
2083 if( k
== i
|| pMethodTypes
[k
] != STANDARD_METHOD
)
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
))
2096 // TODO: More accurate tests could still be carried out here
2098 // - Number and type of parameters
2101 // Methods are recognised as a listener interface
2102 rMethodConcept_i
|= LISTENER
;
2103 pLocalMethodConcepts
[ k
] |= LISTENER
;
2105 pMethodTypes
[i
] = ADD_LISTENER_METHOD
;
2106 pMethodTypes
[k
] = REMOVE_LISTENER_METHOD
;
2112 // A set method could still exist without a corresponding get method,
2113 // this must be a write-only property
2114 for( sal_Int32 i
= 0 ; i
< nSourceMethodCount
; i
++ )
2117 const Reference
<XIdlMethod
>& rxMethod_i
= pSourceMethods
[i
];
2119 // Accept only methods that are not already assigned
2120 if( pMethodTypes
[i
] != STANDARD_METHOD
)
2124 OUString aMethName
= rxMethod_i
->getName();
2126 // If the name is too short, it isn't anything
2127 if( aMethName
.getLength() <= 3 )
2130 // Is it a set method without associated get method?
2132 if( aMethName
.startsWith("set", &aPropName
) )
2134 // A set method must return void
2135 Reference
<XIdlClass
> xSetRetType
= rxMethod_i
->getReturnType();
2136 if( xSetRetType
->getTypeClass() != TypeClass_VOID
)
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 )
2149 // Do we have the name already?
2150 IntrospectionNameMap::iterator aIt
= rPropNameMap
.find( aPropName
);
2151 if (aIt
!= rPropNameMap
.end())
2155 String( "Introspection: Property \"" ) +
2156 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2157 String( "\" found more than once" ) );
2162 // Now we know it's a write only property
2163 pLocalMethodConcepts
[ i
] = PROPERTY
;
2165 pMethodTypes
[i
] = GETSET_METHOD
;
2166 Reference
<XIdlClass
> xGetRetType
= setParams
.getConstArray()[0];
2168 // Is the property sequence big enough?
2169 pAccess
->checkPropertyArraysSize( rPropCount
);
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 ???
2178 // New entry in the hash table
2179 rPropNameMap
[ aPropName
] = rPropCount
;
2181 // Maintain table for XExactName
2182 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
2184 // Remember set method
2185 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq2
,
2186 rInterfaces2
, rPropCount
);
2187 rInterfaces2
[ rPropCount
] = rxMethod_i
;
2189 // Remember type of property
2190 rMapTypeArray
[ rPropCount
] = MAP_SETONLY
;
2191 rPropertyConceptArray
[ rPropCount
] = METHODS
;
2192 pAccess
->mnMethodPropCount
++;
2200 // 4. Place methods in overall sequence
2202 // How many methods in the method sequence
2203 sal_Int32 nExportedMethodCount
= 0;
2204 sal_Int32 nSupportedListenerCount
= 0;
2205 for( sal_Int32 i
= 0 ; i
< nSourceMethodCount
; i
++ )
2207 if( pMethodTypes
[ i
] != INVALID_METHOD
)
2209 nExportedMethodCount
++;
2211 if( pMethodTypes
[ i
] == ADD_LISTENER_METHOD
)
2213 nSupportedListenerCount
++;
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
);
2223 for( sal_Int32 i
= 0 ; i
< nSourceMethodCount
; i
++ )
2225 if( pMethodTypes
[ i
] != INVALID_METHOD
)
2228 const Reference
<XIdlMethod
>& rxMethod
= pSourceMethods
[i
];
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() )
2236 rMethodNameMap
[ aMethName2
] = iAllExportedMethod
;
2238 // Maintain table for XExactName
2239 rLowerToExactNameMap
[ aMethName2
.toAsciiLowerCase() ] = aMethName2
;
2243 sal_Int32 iHashResult
= aIt
->second
;
2245 Reference
<XIdlMethod
> xExistingMethod
= pAccess
->maAllMethodSeq
[iHashResult
];
2247 Reference
< XIdlClass
> xExistingMethClass
=
2248 xExistingMethod
->getDeclaringClass();
2249 Reference
< XIdlClass
> xNewMethClass
= rxMethod
->getDeclaringClass();
2250 if( xExistingMethClass
->equals( xNewMethClass
) )
2254 pAccess
->maAllMethodSeq
[iAllExportedMethod
] = rxMethod
;
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
++;
2263 if( pMethodTypes
[ i
] == ADD_LISTENER_METHOD
)
2265 // Determine class of listener
2266 const Reference
<XIdlMethod
>& rxMethod
= pSourceMethods
[i
];
2268 // Enter void as default class
2269 css::uno::Reference
<css::reflection::XIdlClass
>
2271 reflection
->forName(
2272 cppu::UnoType
<void>::get()
2274 // Old: Reference<XIdlClass> xListenerClass = Void_getReflection()->getIdlClass();
2276 // Option 1: Search for parameters for a listener class
2277 // Disadvantage: Superclasses should be searched recursively
2278 const Sequence
< Reference
<XIdlClass
> > aParams
= rxMethod
->getParameterTypes();
2280 css::uno::Reference
<css::reflection::XIdlClass
>
2281 xEventListenerClass(
2282 reflection
->forName(
2284 css::lang::XEventListener
>::get()
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
);
2293 if (pParam
!= aParams
.end())
2295 xListenerClass
= *pParam
;
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
++;
2309 // When there were XInterface methods in this run,
2310 // ignore them in the future
2311 if( bFoundXInterface
)
2312 bXInterfaceIsInvalid
= true;
2315 // Do superclasses exist? Then continue here
2316 Sequence
< Reference
<XIdlClass
> > aSuperClassSeq
= xImplClass2
->getSuperclasses();
2318 // Currently only one superclass is considered
2319 if( aSuperClassSeq
.getLength() >= 1 )
2321 xImplClass2
= aSuperClassSeq
.getConstArray()[0];
2322 OSL_ENSURE( xImplClass2
.is(), "super class null" );
2326 xImplClass2
= nullptr;
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
);
2339 // Resize the property sequences
2340 pAccess
->maAllPropertySeq
.resize( rPropCount
);
2341 pAccess
->maPropertyConceptSeq
.resize( rPropCount
);
2342 pAccess
->maMapTypeSeq
.resize( rPropCount
);
2344 // Register struct fields as properties
2345 else //if( eType == TypeClass_STRUCT )
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() )
2353 SAL_WARN( "stoc", "Can't get XIdlClass from Reflection" );
2354 return new ImplIntrospectionAccess(aToInspectObj
, pAccess
);
2358 const Sequence
< Reference
<XIdlField
> > fields
= xClassRef
->getFields();
2360 for( const Reference
<XIdlField
>& xField
: fields
)
2362 Reference
<XIdlClass
> xPropType
= xField
->getType();
2363 OUString aPropName
= xField
->getName();
2365 // Is the property sequence big enough?
2366 pAccess
->checkPropertyArraysSize( rPropCount
);
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
)
2378 //FieldAccessMode eAccessMode = xField->getAccessMode();
2379 //rProp.Attributes = (eAccessMode == FieldAccessMode::READONLY || eAccessMode == CONST)
2380 //? PropertyAttribute::READONLY : 0;
2382 // Write name in hash table
2383 rPropNameMap
[ aPropName
] = rPropCount
;
2385 // Maintain table for XExactName
2386 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
2389 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq1
,
2390 rInterfaces1
, rPropCount
);
2391 rInterfaces1
[ rPropCount
] = xField
;
2393 // Remember type of property
2394 rMapTypeArray
[ rPropCount
] = MAP_FIELD
;
2395 rPropertyConceptArray
[ rPropCount
] = ATTRIBUTES
;
2396 pAccess
->mnAttributePropCount
++;
2403 // Set property sequence to the correct length
2404 pAccess
->maAllPropertySeq
.resize( pAccess
->mnPropCount
);
2406 return new ImplIntrospectionAccess(aToInspectObj
, pAccess
);
2411 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
2412 com_sun_star_comp_stoc_Introspection_get_implementation(
2413 css::uno::XComponentContext
* context
,
2414 css::uno::Sequence
<css::uno::Any
> const & arguments
)
2417 arguments
.hasElements(), "stoc", "unexpected singleton arguments");
2418 return cppu::acquire(new Implementation(context
));
2421 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */