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>
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>
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>
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
;
82 typedef WeakImplHelper
< XIntrospectionAccess
, XMaterialHolder
, XExactName
,
83 XPropertySet
, XFastPropertySet
, XPropertySetInfo
,
84 XNameContainer
, XIndexContainer
, XEnumerationAccess
,
85 XIdlArray
, XUnoTunnel
> IntrospectionAccessHelper
;
88 // Special value for Method-Concept, to be able to mark "normal" functions
89 #define MethodConcept_NORMAL_IMPL 0x80000000
92 // Method to assert, if a class is derived from another class
93 bool isDerivedFrom( const Reference
<XIdlClass
>& xToTestClass
, const Reference
<XIdlClass
>& xDerivedFromClass
)
95 Sequence
< Reference
<XIdlClass
> > aClassesSeq
= xToTestClass
->getSuperclasses();
97 return std::any_of(aClassesSeq
.begin(), aClassesSeq
.end(),
98 [&xDerivedFromClass
](const Reference
<XIdlClass
>& rxClass
) {
99 return xDerivedFromClass
->equals( rxClass
)
100 || isDerivedFrom( rxClass
, xDerivedFromClass
);
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
110 // Properties that get described with get/set methods
112 // Properties with only a set method
113 #define MAP_SETONLY 3
116 // Increments by which the size of sequences get adjusted
117 #define ARRAY_SIZE_STEP 20
120 //*** IntrospectionAccessStatic_Impl ***
122 // Equals to the old IntrospectionAccessImpl, forms now a static
123 // part of the new Instance-related ImplIntrospectionAccess
125 // Hashtable for the search of names
126 typedef std::unordered_map
131 IntrospectionNameMap
;
134 // Hashtable to assign exact names to the Lower-Case
135 // converted names, for the support of XExactName
136 typedef std::unordered_map
144 class IntrospectionAccessStatic_Impl
: public salhelper::SimpleReferenceObject
146 friend class Implementation
;
147 friend class ImplIntrospectionAccess
;
149 // Holding CoreReflection
150 Reference
< XIdlReflection
> mxCoreReflection
;
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
;
157 // Hashtables for names
158 IntrospectionNameMap maPropertyNameMap
;
159 IntrospectionNameMap maMethodNameMap
;
160 LowerToExactNameMap maLowerToExactNameMap
;
162 // Vector of all Properties, also for delivering from getProperties()
163 std::vector
<Property
> maAllPropertySeq
;
165 // Mapping of properties to Access-Types
166 std::vector
<sal_Int16
> maMapTypeSeq
;
168 // Classification of found methods
169 std::vector
<sal_Int32
> maPropertyConceptSeq
;
171 // Number of Properties
172 sal_Int32 mnPropCount
;
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
;
180 // Flags which indicate if various interfaces are present
182 bool mbElementAccess
;
185 bool mbNameContainer
;
188 bool mbIndexContainer
;
189 bool mbEnumerationAccess
;
193 // Original handles of FastPropertySets
194 std::unique_ptr
<sal_Int32
[]> mpOrgPropertyHandleArray
;
196 // MethodSequence, that accepts all methods
197 std::vector
< Reference
<XIdlMethod
> > maAllMethodSeq
;
199 // Classification of found methods
200 std::vector
<sal_Int32
> maMethodConceptSeq
;
203 sal_Int32 mnMethCount
;
205 // Sequence of Listener, that can be registered
206 std::vector
< Type
> maSupportedListenerSeq
;
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
);
214 explicit IntrospectionAccessStatic_Impl( Reference
< XIdlReflection
> const & xCoreReflection_
);
215 sal_Int32
getPropertyIndex( const OUString
& aPropertyName
) const;
216 sal_Int32
getMethodIndex( const OUString
& aMethodName
) const;
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;
226 const std::vector
<Property
>& getProperties() const { return maAllPropertySeq
; }
227 const std::vector
< Reference
<XIdlMethod
> >& getMethods() const { return maAllMethodSeq
; }
228 const std::vector
< Type
>& getSupportedListeners() const { return maSupportedListenerSeq
; }
229 const std::vector
<sal_Int32
>& getPropertyConcepts() const { return maPropertyConceptSeq
; }
230 const std::vector
<sal_Int32
>& getMethodConcepts() const { return maMethodConceptSeq
; }
235 IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference
< XIdlReflection
> const & xCoreReflection_
)
236 : mxCoreReflection( xCoreReflection_
)
238 aInterfaceSeq1
.resize( ARRAY_SIZE_STEP
);
239 aInterfaceSeq2
.resize( ARRAY_SIZE_STEP
);
242 maAllPropertySeq
.resize( ARRAY_SIZE_STEP
);
243 maMapTypeSeq
.resize( ARRAY_SIZE_STEP
);
244 maPropertyConceptSeq
.resize( ARRAY_SIZE_STEP
);
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;
258 mpOrgPropertyHandleArray
= nullptr;
261 //mnDangerousPropCount = 0;
262 mnPropertySetPropCount
= 0;
263 mnAttributePropCount
= 0;
264 mnMethodPropCount
= 0;
270 sal_Int32
IntrospectionAccessStatic_Impl::getPropertyIndex( const OUString
& aPropertyName
) const
272 auto aIt
= maPropertyNameMap
.find(aPropertyName
);
273 if (aIt
!= maPropertyNameMap
.end())
279 sal_Int32
IntrospectionAccessStatic_Impl::getMethodIndex( const OUString
& aMethodName
) const
281 auto aIt
= maMethodNameMap
.find(aMethodName
);
282 if (aIt
!= maMethodNameMap
.end())
287 // #95159 Check if full qualified name matches
288 sal_Int32 nSearchFrom
= aMethodName
.getLength();
291 // Strategy: Search back until the first '_' is found
292 sal_Int32 nFound
= aMethodName
.lastIndexOf( '_', nSearchFrom
);
296 OUString aPureMethodName
= aMethodName
.copy( nFound
+ 1 );
298 aIt
= maMethodNameMap
.find( aPureMethodName
);
299 if (aIt
!= maMethodNameMap
.end())
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
);
308 // If this is a valid class it could be the right method
310 // Could be the right method, type has to be checked
311 const sal_Int32 iHashResult
= aIt
->second
;
313 const Reference
<XIdlMethod
> xMethod
= maAllMethodSeq
[iHashResult
];
315 Reference
< XIdlClass
> xMethClass
= xMethod
->getDeclaringClass();
316 if( xClass
->equals( xMethClass
) )
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
)
327 const Reference
<XIdlMethod
> xMethod2
= maAllMethodSeq
[ i
];
328 if( xMethod2
->getName() == aPureMethodName
)
330 Reference
< XIdlClass
> xMethClass2
= xMethod2
->getDeclaringClass();
332 if( xClass
->equals( xMethClass2
) )
342 nSearchFrom
= nFound
- 1;
343 if( nSearchFrom
< 0 )
349 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
352 sal_Int32 i
= getPropertyIndex( aPropertyName
);
354 throw UnknownPropertyException(aPropertyName
);
355 setPropertyValueByIndex( obj
, i
, aValue
);
358 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
361 // Is the passed object something that fits?
362 Reference
<XInterface
> xInterface
;
363 if( !(obj
>>= xInterface
) )
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);
378 if( (maAllPropertySeq
[ nSequenceIndex
].Attributes
& READONLY
) != 0 )
380 throw UnknownPropertyException(
381 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), property at index " + OUString::number(nSequenceIndex
) + " is readonly");
384 switch( maMapTypeSeq
[ nSequenceIndex
] )
386 case MAP_PROPERTY_SET
:
389 const Property
& rProp
= maAllPropertySeq
[ nSequenceIndex
];
391 // Convert Interface-Parameter to the correct type
392 bool bUseCopy
= false;
395 if( auto valInterface
= o3tl::tryAccess
<
396 css::uno::Reference
<css::uno::XInterface
>>(aValue
) )
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
)
404 if( valInterface
->is() )
406 //Any queryInterface( const Type& rType );
407 aRealValue
= (*valInterface
)->queryInterface( aPropType
);
408 if( aRealValue
.hasValue() )
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 )
420 // Retrieve PropertySet-Interface
421 Reference
<XFastPropertySet
> xFastPropSet
=
422 Reference
<XFastPropertySet
>::query( xInterface
);
423 if( xFastPropSet
.is() )
425 xFastPropSet
->setFastPropertyValue( nOrgHandle
, bUseCopy
? aRealValue
: aValue
);
429 // throw UnknownPropertyException
432 // else take the normal one
435 // Retrieve PropertySet-Interface
436 Reference
<XPropertySet
> xPropSet
=
437 Reference
<XPropertySet
>::query( xInterface
);
440 xPropSet
->setPropertyValue( rProp
.Name
, bUseCopy
? aRealValue
: aValue
);
444 // throw UnknownPropertyException
452 Reference
<XIdlField
> xField
= static_cast<XIdlField
*>(aInterfaceSeq1
[ nSequenceIndex
].get());
453 Reference
<XIdlField2
> xField2(xField
, UNO_QUERY
);
456 xField2
->set( const_cast<Any
&>(obj
), aValue
);
457 // IllegalArgumentException
458 // NullPointerException
462 xField
->set( obj
, aValue
);
463 // IllegalArgumentException
464 // NullPointerException
468 // throw IllegalArgumentException();
477 Reference
<XIdlMethod
> xMethod
= static_cast<XIdlMethod
*>(aInterfaceSeq2
[ nSequenceIndex
].get());
480 Sequence
<Any
> args( 1 );
481 args
.getArray()[0] = aValue
;
482 xMethod
->invoke( obj
, args
);
486 // throw IllegalArgumentException();
493 Any
IntrospectionAccessStatic_Impl::getPropertyValue( const Any
& obj
, const OUString
& aPropertyName
) const
495 sal_Int32 i
= getPropertyIndex( aPropertyName
);
497 return getPropertyValueByIndex( obj
, i
);
499 throw UnknownPropertyException(aPropertyName
);
502 Any
IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any
& obj
, sal_Int32 nSequenceIndex
) const
506 // Is there anything suitable in the passed object?
507 Reference
<XInterface
> xInterface
;
508 if( !(obj
>>= xInterface
) )
510 TypeClass eObjType
= obj
.getValueType().getTypeClass();
511 if( nSequenceIndex
>= mnPropCount
|| ( eObjType
!= TypeClass_STRUCT
&& eObjType
!= TypeClass_EXCEPTION
) )
513 // throw IllegalArgumentException();
518 switch( maMapTypeSeq
[ nSequenceIndex
] )
520 case MAP_PROPERTY_SET
:
523 const Property
& rProp
= maAllPropertySeq
[ nSequenceIndex
];
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 )
531 // Fetch the PropertySet interface
532 Reference
<XFastPropertySet
> xFastPropSet
=
533 Reference
<XFastPropertySet
>::query( xInterface
);
534 if( xFastPropSet
.is() )
536 aRet
= xFastPropSet
->getFastPropertyValue( nOrgHandle
);
540 // throw UnknownPropertyException
544 // Otherwise use the normal one
547 // Fetch the PropertySet interface
548 Reference
<XPropertySet
> xPropSet
=
549 Reference
<XPropertySet
>::query( xInterface
);
552 aRet
= xPropSet
->getPropertyValue( rProp
.Name
);
556 // throw UnknownPropertyException
565 Reference
<XIdlField
> xField
= static_cast<XIdlField
*>(aInterfaceSeq1
[ nSequenceIndex
].get());
568 aRet
= xField
->get( obj
);
569 // IllegalArgumentException
570 // NullPointerException
574 // throw IllegalArgumentException();
583 Reference
<XIdlMethod
> xMethod
= static_cast<XIdlMethod
*>(aInterfaceSeq1
[ nSequenceIndex
].get());
587 aRet
= xMethod
->invoke( obj
, args
);
591 // throw IllegalArgumentException();
598 // Get method does not exist
599 // throw WriteOnlyPropertyException();
606 // Helper method to adjust the size of the vectors
607 void IntrospectionAccessStatic_Impl::checkPropertyArraysSize( sal_Int32 iNextIndex
)
609 sal_Int32 nLen
= static_cast<sal_Int32
>(maAllPropertySeq
.size());
610 if( iNextIndex
>= nLen
)
612 maAllPropertySeq
.resize( nLen
+ ARRAY_SIZE_STEP
);
613 maMapTypeSeq
.resize( nLen
+ ARRAY_SIZE_STEP
);
614 maPropertyConceptSeq
.resize( nLen
+ ARRAY_SIZE_STEP
);
618 void IntrospectionAccessStatic_Impl::checkInterfaceArraySize( std::vector
< Reference
<XInterface
> >& rSeq
,
619 std::vector
<Reference
<XInterface
>>& rInterfaceVec
, sal_Int32 iNextIndex
)
621 sal_Int32 nLen
= rSeq
.size();
622 if( iNextIndex
>= nLen
)
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
;
629 rSeq
.resize( nNewSize
);
630 rInterfaceVec
= rSeq
;
635 //*** ImplIntrospectionAccess ***
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
643 friend class Implementation
;
645 // Object under examination
646 Any maInspectedObject
;
649 Reference
<XInterface
> mxIface
;
651 // Static introspection data
652 rtl::Reference
< IntrospectionAccessStatic_Impl
> mpStaticImpl
;
654 // Last Sequence that came with getProperties (optimization)
655 Sequence
<Property
> maLastPropertySeq
;
656 sal_Int32 mnLastPropertyConcept
;
658 // Last Sequence that came with getMethods (optimization)
659 Sequence
<Reference
<XIdlMethod
> > maLastMethodSeq
;
660 sal_Int32 mnLastMethodConcept
;
662 // Guards the caching of queried interfaces
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
;
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();
686 void cacheXNameContainer();
687 void cacheXIndexContainer();
690 ImplIntrospectionAccess( const Any
& obj
, rtl::Reference
< IntrospectionAccessStatic_Impl
> const & pStaticImpl_
);
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
;
705 // Methods from XMaterialHolder
706 virtual Any SAL_CALL
getMaterial() override
;
708 // Methods from XExactName
709 virtual OUString SAL_CALL
getExactName( const OUString
& rApproximateName
) override
;
711 // Methods from XInterface
712 virtual Any SAL_CALL
queryInterface( const Type
& rType
) override
;
713 virtual void SAL_CALL
acquire() throw() override
{ OWeakObject::acquire(); }
714 virtual void SAL_CALL
release() throw() override
{ OWeakObject::release(); }
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
;
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
;
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
;
734 // Methods from XElementAccess
735 virtual Type SAL_CALL
getElementType() override
;
736 virtual sal_Bool SAL_CALL
hasElements() override
;
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
;
743 // Methods from XNameReplace
744 virtual void SAL_CALL
replaceByName(const OUString
& Name
, const Any
& Element
) override
;
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
;
750 // Methods from XIndexAccess
751 virtual sal_Int32 SAL_CALL
getCount() override
;
752 virtual Any SAL_CALL
getByIndex(sal_Int32 Index
) override
;
754 // Methods from XIndexReplace
755 virtual void SAL_CALL
replaceByIndex(sal_Int32 Index
, const Any
& Element
) override
;
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
;
761 // Methods from XEnumerationAccess
762 virtual Reference
<XEnumeration
> SAL_CALL
createEnumeration() override
;
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
;
770 // Methods from XUnoTunnel
771 virtual sal_Int64 SAL_CALL
getSomething( const Sequence
< sal_Int8
>& aIdentifier
) override
;
774 ImplIntrospectionAccess::ImplIntrospectionAccess
775 ( const Any
& obj
, rtl::Reference
< IntrospectionAccessStatic_Impl
> const & pStaticImpl_
)
776 : maInspectedObject( obj
), mpStaticImpl( pStaticImpl_
) ,
777 mnLastPropertyConcept(-1), mnLastMethodConcept(-1) //, maAdapter()
779 // Save object as an interface if possible
780 maInspectedObject
>>= mxIface
;
783 Reference
<XElementAccess
> ImplIntrospectionAccess::getXElementAccess()
785 ResettableGuard
< Mutex
> aGuard( m_aMutex
);
787 if( !mxObjElementAccess
.is() )
790 Reference
<XElementAccess
> xElementAccess( mxIface
, UNO_QUERY
);
792 if( !mxObjElementAccess
.is() )
793 mxObjElementAccess
= xElementAccess
;
795 return mxObjElementAccess
;
798 void ImplIntrospectionAccess::cacheXNameContainer()
800 Reference
<XNameContainer
> xNameContainer
;
801 Reference
<XNameReplace
> xNameReplace
;
802 Reference
<XNameAccess
> xNameAccess
;
803 if (mpStaticImpl
->mbNameContainer
)
805 xNameContainer
.set( mxIface
, UNO_QUERY
);
806 xNameReplace
= xNameContainer
;
807 xNameAccess
= xNameContainer
;
809 else if (mpStaticImpl
->mbNameReplace
)
811 xNameReplace
.set( mxIface
, UNO_QUERY
);
812 xNameAccess
= xNameReplace
;
814 else if (mpStaticImpl
->mbNameAccess
)
816 xNameAccess
.set( mxIface
, UNO_QUERY
);
820 MutexGuard
aGuard( m_aMutex
);
821 if( !mxObjNameContainer
.is() )
822 mxObjNameContainer
= xNameContainer
;
823 if( !mxObjNameReplace
.is() )
824 mxObjNameReplace
= xNameReplace
;
825 if( !mxObjNameAccess
.is() )
826 mxObjNameAccess
= xNameAccess
;
830 Reference
<XNameContainer
> ImplIntrospectionAccess::getXNameContainer()
832 ClearableGuard
< Mutex
> aGuard( m_aMutex
);
834 if( !mxObjNameContainer
.is() )
837 cacheXNameContainer();
839 return mxObjNameContainer
;
842 Reference
<XNameReplace
> ImplIntrospectionAccess::getXNameReplace()
844 ClearableGuard
< Mutex
> aGuard( m_aMutex
);
846 if( !mxObjNameReplace
.is() )
849 cacheXNameContainer();
851 return mxObjNameReplace
;
854 Reference
<XNameAccess
> ImplIntrospectionAccess::getXNameAccess()
856 ClearableGuard
< Mutex
> aGuard( m_aMutex
);
858 if( !mxObjNameAccess
.is() )
861 cacheXNameContainer();
863 return mxObjNameAccess
;
866 void ImplIntrospectionAccess::cacheXIndexContainer()
868 Reference
<XIndexContainer
> xIndexContainer
;
869 Reference
<XIndexReplace
> xIndexReplace
;
870 Reference
<XIndexAccess
> xIndexAccess
;
871 if (mpStaticImpl
->mbIndexContainer
)
873 xIndexContainer
.set( mxIface
, UNO_QUERY
);
874 xIndexReplace
= xIndexContainer
;
875 xIndexAccess
= xIndexContainer
;
877 else if (mpStaticImpl
->mbIndexReplace
)
879 xIndexReplace
.set( mxIface
, UNO_QUERY
);
880 xIndexAccess
= xIndexReplace
;
882 else if (mpStaticImpl
->mbIndexAccess
)
884 xIndexAccess
.set( mxIface
, UNO_QUERY
);
888 MutexGuard
aGuard( m_aMutex
);
889 if( !mxObjIndexContainer
.is() )
890 mxObjIndexContainer
= xIndexContainer
;
891 if( !mxObjIndexReplace
.is() )
892 mxObjIndexReplace
= xIndexReplace
;
893 if( !mxObjIndexAccess
.is() )
894 mxObjIndexAccess
= xIndexAccess
;
898 Reference
<XIndexContainer
> ImplIntrospectionAccess::getXIndexContainer()
900 ClearableGuard
< Mutex
> aGuard( m_aMutex
);
902 if( !mxObjIndexContainer
.is() )
905 cacheXIndexContainer();
907 return mxObjIndexContainer
;
910 Reference
<XIndexReplace
> ImplIntrospectionAccess::getXIndexReplace()
912 ClearableGuard
< Mutex
> aGuard( m_aMutex
);
914 if( !mxObjIndexReplace
.is() )
917 cacheXIndexContainer();
919 return mxObjIndexReplace
;
922 Reference
<XIndexAccess
> ImplIntrospectionAccess::getXIndexAccess()
924 ClearableGuard
< Mutex
> aGuard( m_aMutex
);
926 if( !mxObjIndexAccess
.is() )
929 cacheXIndexContainer();
931 return mxObjIndexAccess
;
934 Reference
<XEnumerationAccess
> ImplIntrospectionAccess::getXEnumerationAccess()
936 ResettableGuard
< Mutex
> aGuard( m_aMutex
);
938 if( !mxObjEnumerationAccess
.is() )
941 Reference
<XEnumerationAccess
> xEnumerationAccess( mxIface
, UNO_QUERY
);
943 if( !mxObjEnumerationAccess
.is() )
944 mxObjEnumerationAccess
= xEnumerationAccess
;
946 return mxObjEnumerationAccess
;
949 Reference
<XIdlArray
> ImplIntrospectionAccess::getXIdlArray()
951 ResettableGuard
< Mutex
> aGuard( m_aMutex
);
953 if( !mxObjIdlArray
.is() )
956 Reference
<XIdlArray
> xIdlArray( mxIface
, UNO_QUERY
);
958 if( !mxObjIdlArray
.is() )
959 mxObjIdlArray
= xIdlArray
;
961 return mxObjIdlArray
;
964 // Methods from XInterface
965 Any SAL_CALL
ImplIntrospectionAccess::queryInterface( const Type
& rType
)
967 Any
aRet( ::cppu::queryInterface(
969 static_cast< XIntrospectionAccess
* >( this ),
970 static_cast< XMaterialHolder
* >( this ),
971 static_cast< XExactName
* >( this ),
972 static_cast< XPropertySet
* >( this ),
973 static_cast< XFastPropertySet
* >( this ),
974 static_cast< XPropertySetInfo
* >( this ) ) );
975 if( !aRet
.hasValue() )
976 aRet
= OWeakObject::queryInterface( rType
);
978 if( !aRet
.hasValue() )
980 // Wrapper for the object interfaces
981 ( mpStaticImpl
->mbElementAccess
&& (aRet
= ::cppu::queryInterface
982 ( rType
, static_cast< XElementAccess
* >( static_cast< XNameAccess
* >( this ) ) ) ).hasValue() )
983 || ( mpStaticImpl
->mbNameAccess
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XNameAccess
* >( this ) ) ).hasValue() )
984 || ( mpStaticImpl
->mbNameReplace
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XNameReplace
* >( this ) ) ).hasValue() )
985 || ( mpStaticImpl
->mbNameContainer
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XNameContainer
* >( this ) ) ).hasValue() )
986 || ( mpStaticImpl
->mbIndexAccess
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XIndexAccess
* >( this ) ) ).hasValue() )
987 || ( mpStaticImpl
->mbIndexReplace
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XIndexReplace
* >( this ) ) ).hasValue() )
988 || ( mpStaticImpl
->mbIndexContainer
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XIndexContainer
* >( this ) ) ).hasValue() )
989 || ( mpStaticImpl
->mbEnumerationAccess
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XEnumerationAccess
* >( this ) ) ).hasValue() )
990 || ( mpStaticImpl
->mbIdlArray
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XIdlArray
* >( this ) ) ).hasValue() )
991 || ( mpStaticImpl
->mbUnoTunnel
&& (aRet
= ::cppu::queryInterface( rType
, static_cast< XUnoTunnel
* >( this ) ) ).hasValue() );
997 //*** Implementation of ImplIntrospectionAdapter ***
1000 // Methods from XPropertySet
1001 Reference
<XPropertySetInfo
> ImplIntrospectionAccess::getPropertySetInfo()
1003 return static_cast<XPropertySetInfo
*>(this);
1006 void ImplIntrospectionAccess::setPropertyValue(const OUString
& aPropertyName
, const Any
& aValue
)
1008 mpStaticImpl
->setPropertyValue( maInspectedObject
, aPropertyName
, aValue
);
1011 Any
ImplIntrospectionAccess::getPropertyValue(const OUString
& aPropertyName
)
1013 return mpStaticImpl
->getPropertyValue( maInspectedObject
, aPropertyName
);
1016 void ImplIntrospectionAccess::addPropertyChangeListener(const OUString
& aPropertyName
, const Reference
<XPropertyChangeListener
>& aListener
)
1020 Reference
<XPropertySet
> xPropSet
=
1021 Reference
<XPropertySet
>::query( mxIface
);
1022 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1024 xPropSet
->addPropertyChangeListener(aPropertyName
, aListener
);
1028 void ImplIntrospectionAccess::removePropertyChangeListener(const OUString
& aPropertyName
, const Reference
<XPropertyChangeListener
>& aListener
)
1032 Reference
<XPropertySet
> xPropSet
=
1033 Reference
<XPropertySet
>::query( mxIface
);
1034 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1036 xPropSet
->removePropertyChangeListener(aPropertyName
, aListener
);
1040 void ImplIntrospectionAccess::addVetoableChangeListener(const OUString
& aPropertyName
, const Reference
<XVetoableChangeListener
>& aListener
)
1044 Reference
<XPropertySet
> xPropSet
=
1045 Reference
<XPropertySet
>::query( mxIface
);
1046 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1048 xPropSet
->addVetoableChangeListener(aPropertyName
, aListener
);
1052 void ImplIntrospectionAccess::removeVetoableChangeListener(const OUString
& aPropertyName
, const Reference
<XVetoableChangeListener
>& aListener
)
1056 Reference
<XPropertySet
> xPropSet
=
1057 Reference
<XPropertySet
>::query( mxIface
);
1059 xPropSet
->removeVetoableChangeListener(aPropertyName
, aListener
);
1064 // Methods from XFastPropertySet
1065 void ImplIntrospectionAccess::setFastPropertyValue(sal_Int32
, const Any
&)
1069 Any
ImplIntrospectionAccess::getFastPropertyValue(sal_Int32
)
1074 // Methods from XPropertySetInfo
1075 Sequence
< Property
> ImplIntrospectionAccess::getProperties()
1077 return comphelper::containerToSequence(mpStaticImpl
->getProperties());
1080 Property
ImplIntrospectionAccess::getPropertyByName(const OUString
& Name
)
1082 return getProperty( Name
, PropertyConcept::ALL
);
1085 sal_Bool
ImplIntrospectionAccess::hasPropertyByName(const OUString
& Name
)
1087 return hasProperty( Name
, PropertyConcept::ALL
);
1090 // Methods from XElementAccess
1091 Type
ImplIntrospectionAccess::getElementType()
1093 return getXElementAccess()->getElementType();
1096 sal_Bool
ImplIntrospectionAccess::hasElements()
1098 return getXElementAccess()->hasElements();
1101 // Methods from XNameAccess
1102 Any
ImplIntrospectionAccess::getByName(const OUString
& Name
)
1104 return getXNameAccess()->getByName( Name
);
1107 Sequence
< OUString
> ImplIntrospectionAccess::getElementNames()
1109 return getXNameAccess()->getElementNames();
1112 sal_Bool
ImplIntrospectionAccess::hasByName(const OUString
& Name
)
1114 return getXNameAccess()->hasByName( Name
);
1117 // Methods from XNameContainer
1118 void ImplIntrospectionAccess::insertByName(const OUString
& Name
, const Any
& Element
)
1120 getXNameContainer()->insertByName( Name
, Element
);
1123 void ImplIntrospectionAccess::replaceByName(const OUString
& Name
, const Any
& Element
)
1125 getXNameReplace()->replaceByName( Name
, Element
);
1128 void ImplIntrospectionAccess::removeByName(const OUString
& Name
)
1130 getXNameContainer()->removeByName( Name
);
1133 // Methods from XIndexAccess
1134 // Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const
1135 sal_Int32
ImplIntrospectionAccess::getCount()
1137 return getXIndexAccess()->getCount();
1140 Any
ImplIntrospectionAccess::getByIndex(sal_Int32 Index
)
1142 return getXIndexAccess()->getByIndex( Index
);
1145 // Methods from XIndexContainer
1146 void ImplIntrospectionAccess::insertByIndex(sal_Int32 Index
, const Any
& Element
)
1148 getXIndexContainer()->insertByIndex( Index
, Element
);
1151 void ImplIntrospectionAccess::replaceByIndex(sal_Int32 Index
, const Any
& Element
)
1153 getXIndexReplace()->replaceByIndex( Index
, Element
);
1156 void ImplIntrospectionAccess::removeByIndex(sal_Int32 Index
)
1158 getXIndexContainer()->removeByIndex( Index
);
1161 // Methods from XEnumerationAccess
1162 // Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const;
1163 Reference
<XEnumeration
> ImplIntrospectionAccess::createEnumeration()
1165 return getXEnumerationAccess()->createEnumeration();
1168 // Methods from XIdlArray
1169 void ImplIntrospectionAccess::realloc(Any
& array
, sal_Int32 length
)
1171 getXIdlArray()->realloc( array
, length
);
1174 sal_Int32
ImplIntrospectionAccess::getLen(const Any
& array
)
1176 return getXIdlArray()->getLen( array
);
1179 Any
ImplIntrospectionAccess::get(const Any
& array
, sal_Int32 index
)
1181 return getXIdlArray()->get( array
, index
);
1184 void ImplIntrospectionAccess::set(Any
& array
, sal_Int32 index
, const Any
& value
)
1186 getXIdlArray()->set( array
, index
, value
);
1189 // Methods from XUnoTunnel
1190 sal_Int64
ImplIntrospectionAccess::getSomething( const Sequence
< sal_Int8
>& aIdentifier
)
1192 return Reference
<XUnoTunnel
>::query( mxIface
)->getSomething( aIdentifier
);
1196 //*** Implementation of ImplIntrospectionAccess ***
1198 // Methods from XIntrospectionAccess
1199 sal_Int32
ImplIntrospectionAccess::getSuppliedMethodConcepts()
1201 return MethodConcept::DANGEROUS
|
1209 sal_Int32
ImplIntrospectionAccess::getSuppliedPropertyConcepts()
1211 return PropertyConcept::DANGEROUS
|
1217 Property
ImplIntrospectionAccess::getProperty(const OUString
& Name
, sal_Int32 PropertyConcepts
)
1220 sal_Int32 i
= mpStaticImpl
->getPropertyIndex( Name
);
1221 bool bFound
= false;
1224 sal_Int32 nConcept
= mpStaticImpl
->getPropertyConcepts()[ i
];
1225 if( (PropertyConcepts
& nConcept
) != 0 )
1227 aRet
= mpStaticImpl
->getProperties()[ i
];
1232 throw NoSuchElementException(Name
);
1236 sal_Bool
ImplIntrospectionAccess::hasProperty(const OUString
& Name
, sal_Int32 PropertyConcepts
)
1238 sal_Int32 i
= mpStaticImpl
->getPropertyIndex( Name
);
1242 sal_Int32 nConcept
= mpStaticImpl
->getPropertyConcepts()[ i
];
1243 if( (PropertyConcepts
& nConcept
) != 0 )
1249 Sequence
< Property
> ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts
)
1251 // If all supported concepts are required, simply pass through the sequence
1252 sal_Int32 nAllSupportedMask
= PROPERTYSET
|
1255 if( ( PropertyConcepts
& nAllSupportedMask
) == nAllSupportedMask
)
1257 return comphelper::containerToSequence(mpStaticImpl
->getProperties());
1260 // Same sequence as last time?
1261 if( mnLastPropertyConcept
== PropertyConcepts
)
1263 return maLastPropertySeq
;
1266 // Number of properties to be delivered
1267 sal_Int32 nCount
= 0;
1269 // There are currently no DANGEROUS properties
1270 // if( PropertyConcepts & DANGEROUS )
1271 // nCount += mpStaticImpl->mnDangerousPropCount;
1272 if( PropertyConcepts
& PROPERTYSET
)
1273 nCount
+= mpStaticImpl
->mnPropertySetPropCount
;
1274 if( PropertyConcepts
& ATTRIBUTES
)
1275 nCount
+= mpStaticImpl
->mnAttributePropCount
;
1276 if( PropertyConcepts
& METHODS
)
1277 nCount
+= mpStaticImpl
->mnMethodPropCount
;
1279 // Realloc sequence according to the required number
1280 maLastPropertySeq
.realloc( nCount
);
1281 Property
* pDestProps
= maLastPropertySeq
.getArray();
1283 // Go through all the properties and apply according to the concept
1284 const std::vector
<Property
>& rPropSeq
= mpStaticImpl
->getProperties();
1285 const std::vector
<sal_Int32
>& rConcepts
= mpStaticImpl
->getPropertyConcepts();
1286 sal_Int32 nLen
= static_cast<sal_Int32
>(rPropSeq
.size());
1288 sal_Int32 iDest
= 0;
1289 for( sal_Int32 i
= 0 ; i
< nLen
; i
++ )
1291 sal_Int32 nConcept
= rConcepts
[ i
];
1292 if( nConcept
& PropertyConcepts
)
1293 pDestProps
[ iDest
++ ] = rPropSeq
[ i
];
1296 // Remember PropertyConcept representing maLastPropertySeq
1297 mnLastPropertyConcept
= PropertyConcepts
;
1299 // Supply assembled Sequence
1300 return maLastPropertySeq
;
1303 Reference
<XIdlMethod
> ImplIntrospectionAccess::getMethod(const OUString
& Name
, sal_Int32 MethodConcepts
)
1305 Reference
<XIdlMethod
> xRet
;
1306 sal_Int32 i
= mpStaticImpl
->getMethodIndex( Name
);
1310 sal_Int32 nConcept
= mpStaticImpl
->getMethodConcepts()[ i
];
1311 if( (MethodConcepts
& nConcept
) != 0 )
1313 xRet
= mpStaticImpl
->getMethods()[i
];
1317 throw NoSuchMethodException(Name
);
1321 sal_Bool
ImplIntrospectionAccess::hasMethod(const OUString
& Name
, sal_Int32 MethodConcepts
)
1323 sal_Int32 i
= mpStaticImpl
->getMethodIndex( Name
);
1327 sal_Int32 nConcept
= mpStaticImpl
->getMethodConcepts()[ i
];
1328 if( (MethodConcepts
& nConcept
) != 0 )
1334 Sequence
< Reference
<XIdlMethod
> > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts
)
1336 // If all supported concepts are required, simply pass through the sequence
1337 sal_Int32 nAllSupportedMask
= MethodConcept::DANGEROUS
|
1343 MethodConcept_NORMAL_IMPL
;
1344 if( ( MethodConcepts
& nAllSupportedMask
) == nAllSupportedMask
)
1346 return comphelper::containerToSequence(mpStaticImpl
->getMethods());
1349 // Same sequence as last time?
1350 if( mnLastMethodConcept
== MethodConcepts
)
1352 return maLastMethodSeq
;
1355 // Get method sequences
1356 const std::vector
< Reference
<XIdlMethod
> >& aMethodSeq
= mpStaticImpl
->getMethods();
1357 sal_Int32 nLen
= static_cast<sal_Int32
>(aMethodSeq
.size());
1359 // Realloc sequence according to the required number
1360 // Unlike Properties, the number can not be determined by counters in
1361 // inspect() beforehand, since methods can belong to several concepts
1362 maLastMethodSeq
.realloc( nLen
);
1363 Reference
<XIdlMethod
>* pDestMethods
= maLastMethodSeq
.getArray();
1365 // Go through all the methods and apply according to the concept
1366 sal_Int32 iDest
= 0;
1367 for( sal_Int32 i
= 0 ; i
< nLen
; i
++ )
1369 sal_Int32 nConcept
= mpStaticImpl
->getMethodConcepts()[ i
];
1370 if( nConcept
& MethodConcepts
)
1371 pDestMethods
[ iDest
++ ] = aMethodSeq
[ i
];
1374 // Bring to the correct length
1375 maLastMethodSeq
.realloc( iDest
);
1377 // Remember MethodConcept representing maLastMethodSeq
1378 mnLastMethodConcept
= MethodConcepts
;
1380 // Supply assembled Sequence
1381 return maLastMethodSeq
;
1384 Sequence
< Type
> ImplIntrospectionAccess::getSupportedListeners()
1386 return comphelper::containerToSequence(mpStaticImpl
->getSupportedListeners());
1389 Reference
<XInterface
> SAL_CALL
ImplIntrospectionAccess::queryAdapter( const Type
& rType
)
1391 Reference
<XInterface
> xRet
;
1392 if( rType
== cppu::UnoType
<XInterface
>::get()
1393 || rType
== cppu::UnoType
<XPropertySet
>::get()
1394 || rType
== cppu::UnoType
<XFastPropertySet
>::get()
1395 || rType
== cppu::UnoType
<XPropertySetInfo
>::get()
1396 || rType
== cppu::UnoType
<XElementAccess
>::get()
1397 || rType
== cppu::UnoType
<XNameAccess
>::get()
1398 || rType
== cppu::UnoType
<XNameReplace
>::get()
1399 || rType
== cppu::UnoType
<XNameContainer
>::get()
1400 || rType
== cppu::UnoType
<XIndexAccess
>::get()
1401 || rType
== cppu::UnoType
<XIndexReplace
>::get()
1402 || rType
== cppu::UnoType
<XIndexContainer
>::get()
1403 || rType
== cppu::UnoType
<XEnumerationAccess
>::get()
1404 || rType
== cppu::UnoType
<XIdlArray
>::get()
1405 || rType
== cppu::UnoType
<XUnoTunnel
>::get() )
1407 queryInterface( rType
) >>= xRet
;
1412 // Methods from XMaterialHolder
1413 Any
ImplIntrospectionAccess::getMaterial()
1415 return maInspectedObject
;
1418 // Methods from XExactName
1419 OUString
ImplIntrospectionAccess::getExactName( const OUString
& rApproximateName
)
1422 LowerToExactNameMap::iterator aIt
=
1423 mpStaticImpl
->maLowerToExactNameMap
.find( rApproximateName
.toAsciiLowerCase() );
1424 if (aIt
!= mpStaticImpl
->maLowerToExactNameMap
.end())
1425 aRetStr
= (*aIt
).second
;
1431 css::uno::Reference
<css::beans::XPropertySetInfo
> const & theProperties
,
1432 std::vector
<css::uno::Type
> const & theTypes
):
1433 properties(theProperties
)
1435 //TODO: Could even sort the types lexicographically first, to increase
1436 // the chance of matches between different implementations' getTypes(),
1437 // but the old scheme of using getImplementationId() would have missed
1438 // those matches, too:
1439 OUStringBuffer
b(static_cast<int>(theTypes
.size() * 64));
1440 for (const css::uno::Type
& rType
: theTypes
) {
1441 b
.append(rType
.getTypeName());
1442 b
.append('*'); // arbitrary delimiter not used by type grammar
1444 types
= b
.makeStringAndClear();
1447 css::uno::Reference
<css::beans::XPropertySetInfo
> properties
;
1451 struct TypeKeyLess
{
1452 bool operator ()(TypeKey
const & key1
, TypeKey
const & key2
) const {
1453 if (key1
.properties
.get() < key2
.properties
.get()) {
1456 if (key1
.properties
.get() > key2
.properties
.get()) {
1459 return key1
.types
< key2
.types
;
1463 template<typename Key
, typename Less
> class Cache
{
1465 rtl::Reference
<IntrospectionAccessStatic_Impl
> find(Key
const & key
) const {
1466 typename
Map::const_iterator
i(map_
.find(key
));
1467 if (i
== map_
.end()) {
1468 return rtl::Reference
<IntrospectionAccessStatic_Impl
>();
1470 if (i
->second
.hits
< std::numeric_limits
<unsigned>::max()) {
1473 assert(i
->second
.access
.is());
1474 return i
->second
.access
;
1480 rtl::Reference
<IntrospectionAccessStatic_Impl
> const & access
)
1482 assert(access
.is());
1483 typename
Map::size_type
const MAX
= 100;
1484 assert(map_
.size() <= MAX
);
1485 if (map_
.size() == MAX
) {
1486 typename
Map::iterator del
= std::min_element(map_
.begin(), map_
.end(),
1487 [](const typename
Map::value_type
& a
, const typename
Map::value_type
& b
) {
1488 return a
.second
.hits
< b
.second
.hits
;
1492 bool ins
= map_
.emplace(key
, Data(access
)).second
;
1493 assert(ins
); (void)ins
;
1496 void clear() { map_
.clear(); }
1501 rtl::Reference
<IntrospectionAccessStatic_Impl
> const & theAccess
):
1502 access(theAccess
), hits(1)
1505 rtl::Reference
<IntrospectionAccessStatic_Impl
> access
;
1506 mutable unsigned hits
;
1509 typedef std::map
<Key
, Data
, Less
> Map
;
1515 cppu::WeakComponentImplHelper
<
1516 css::lang::XServiceInfo
, css::beans::XIntrospection
>
1517 Implementation_Base
;
1519 class Implementation
: private cppu::BaseMutex
, public Implementation_Base
{
1521 explicit Implementation(
1522 css::uno::Reference
<css::uno::XComponentContext
> const & context
):
1523 Implementation_Base(m_aMutex
),
1524 reflection_(css::reflection::theCoreReflection::get(context
))
1528 virtual void SAL_CALL
disposing() override
{
1529 osl::MutexGuard
g(m_aMutex
);
1530 reflection_
.clear();
1534 virtual OUString SAL_CALL
getImplementationName() override
1535 { return "com.sun.star.comp.stoc.Introspection"; }
1537 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
1538 { return cppu::supportsService(this, ServiceName
); }
1540 virtual css::uno::Sequence
<OUString
> SAL_CALL
1541 getSupportedServiceNames() override
1543 Sequence
<OUString
> s
{ "com.sun.star.beans.Introspection" };
1547 virtual css::uno::Reference
<css::beans::XIntrospectionAccess
> SAL_CALL
1548 inspect(css::uno::Any
const & aObject
) override
;
1550 css::uno::Reference
<css::reflection::XIdlReflection
> reflection_
;
1551 Cache
<TypeKey
, TypeKeyLess
> typeCache_
;
1554 css::uno::Reference
<css::beans::XIntrospectionAccess
> Implementation::inspect(
1555 css::uno::Any
const & aObject
)
1557 css::uno::Reference
<css::reflection::XIdlReflection
> reflection
;
1559 osl::MutexGuard
g(m_aMutex
);
1560 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
) {
1561 throw css::lang::DisposedException(
1562 getImplementationName(), static_cast<OWeakObject
*>(this));
1564 reflection
= reflection_
;
1566 css::uno::Any aToInspectObj
;
1568 if (aObject
>>= t
) {
1569 css::uno::Reference
<css::reflection::XIdlClass
> c(
1570 reflection
->forName(t
.getTypeName()));
1572 SAL_WARN("stoc", "cannot reflect type " << t
.getTypeName());
1573 return css::uno::Reference
<css::beans::XIntrospectionAccess
>();
1575 aToInspectObj
<<= c
;
1577 aToInspectObj
= aObject
;
1581 TypeClass eType
= aToInspectObj
.getValueType().getTypeClass();
1582 if( eType
!= TypeClass_INTERFACE
&& eType
!= TypeClass_STRUCT
&& eType
!= TypeClass_EXCEPTION
)
1583 return css::uno::Reference
<css::beans::XIntrospectionAccess
>();
1585 if( auto x
= o3tl::tryAccess
<Reference
<XInterface
>>(aToInspectObj
) )
1588 return css::uno::Reference
<css::beans::XIntrospectionAccess
>();
1591 // Pointer to possibly needed new IntrospectionAccessStatic_Impl instance
1592 rtl::Reference
< IntrospectionAccessStatic_Impl
> pAccess
;
1594 // Check: Is a matching access object already cached?
1595 std::vector
< Reference
<XIdlClass
> > SupportedClassSeq
;
1596 std::vector
< Type
> SupportedTypesSeq
;
1597 Reference
<XTypeProvider
> xTypeProvider
;
1598 Reference
<XPropertySetInfo
> xPropSetInfo
;
1599 Reference
<XPropertySet
> xPropSet
;
1601 // Look for interfaces XTypeProvider and PropertySet
1602 if( eType
== TypeClass_INTERFACE
)
1604 xTypeProvider
.set( aToInspectObj
, UNO_QUERY
);
1605 if( xTypeProvider
.is() )
1607 SupportedTypesSeq
= comphelper::sequenceToContainer
<std::vector
<Type
>>(xTypeProvider
->getTypes());
1611 "object of type \"" << aToInspectObj
.getValueTypeName()
1612 << "\" lacks XTypeProvider");
1613 SupportedTypesSeq
= { aToInspectObj
.getValueType() };
1615 // Now try to get the PropertySetInfo
1616 xPropSet
.set( aToInspectObj
, UNO_QUERY
);
1618 xPropSetInfo
= xPropSet
->getPropertySetInfo();
1621 SupportedTypesSeq
= { aToInspectObj
.getValueType() };
1625 osl::MutexGuard
g(m_aMutex
);
1626 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
) {
1627 throw css::lang::DisposedException(
1628 getImplementationName(), static_cast<OWeakObject
*>(this));
1630 TypeKey
key(xPropSetInfo
, SupportedTypesSeq
);
1631 pAccess
= typeCache_
.find(key
);
1633 return new ImplIntrospectionAccess(aToInspectObj
, pAccess
);
1635 pAccess
= new IntrospectionAccessStatic_Impl(reflection
);
1636 typeCache_
.insert(key
, pAccess
);
1639 // No access cached -> create new
1640 std::vector
<Property
>& rAllPropArray
= pAccess
->maAllPropertySeq
;
1641 std::vector
<Reference
<XInterface
>>& rInterfaces1
= pAccess
->aInterfaceSeq1
;
1642 std::vector
<Reference
<XInterface
>>& rInterfaces2
= pAccess
->aInterfaceSeq2
;
1643 std::vector
<sal_Int16
>& rMapTypeArray
= pAccess
->maMapTypeSeq
;
1644 std::vector
<sal_Int32
>& rPropertyConceptArray
= pAccess
->maPropertyConceptSeq
;
1647 // References to important data from pAccess
1648 sal_Int32
& rPropCount
= pAccess
->mnPropCount
;
1649 IntrospectionNameMap
& rPropNameMap
= pAccess
->maPropertyNameMap
;
1650 IntrospectionNameMap
& rMethodNameMap
= pAccess
->maMethodNameMap
;
1651 LowerToExactNameMap
& rLowerToExactNameMap
= pAccess
->maLowerToExactNameMap
;
1654 //*** Perform analysis ***
1656 if( eType
== TypeClass_INTERFACE
)
1658 size_t nTypeCount
= SupportedTypesSeq
.size();
1661 SupportedClassSeq
.resize( nTypeCount
);
1663 for( i
= 0 ; i
< static_cast<sal_Int32
>(nTypeCount
) ; i
++ )
1664 SupportedClassSeq
[i
] = reflection
->forName( SupportedTypesSeq
[i
].getTypeName() );
1667 // First look for particular interfaces that are of particular
1668 // importance to the introspection
1670 // Is XPropertySet present?
1671 if( xPropSet
.is() && xPropSetInfo
.is() )
1673 // Is there also a FastPropertySet?
1674 Reference
<XFastPropertySet
> xDummy( aToInspectObj
, UNO_QUERY
);
1675 bool bFast
= pAccess
->mbFastPropSet
= xDummy
.is();
1677 Sequence
<Property
> aPropSeq
= xPropSetInfo
->getProperties();
1678 const Property
* pProps
= aPropSeq
.getConstArray();
1679 sal_Int32 nLen
= aPropSeq
.getLength();
1681 // For a FastPropertySet we must remember the original handles
1683 pAccess
->mpOrgPropertyHandleArray
.reset( new sal_Int32
[ nLen
] );
1685 for( i
= 0 ; i
< nLen
; i
++ )
1687 // Put property in its own list
1688 pAccess
->checkPropertyArraysSize( rPropCount
);
1689 Property
& rProp
= rAllPropArray
[ rPropCount
];
1690 rProp
= pProps
[ i
];
1693 pAccess
->mpOrgPropertyHandleArray
[ i
] = rProp
.Handle
;
1695 // Enter PropCount as a handle for its own FastPropertySet
1696 rProp
.Handle
= rPropCount
;
1698 // Remember type of property
1699 rMapTypeArray
[ rPropCount
] = MAP_PROPERTY_SET
;
1700 rPropertyConceptArray
[ rPropCount
] = PROPERTYSET
;
1701 pAccess
->mnPropertySetPropCount
++;
1703 // Enter name in hash table if not already known
1704 OUString aPropName
= rProp
.Name
;
1706 // Do we already have the name?
1707 IntrospectionNameMap::iterator aIt
= rPropNameMap
.find( aPropName
);
1708 if( aIt
== rPropNameMap
.end() )
1710 // New entry in the hash table
1711 rPropNameMap
[ aPropName
] = rPropCount
;
1713 // Maintain table for XExactName
1714 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
1718 SAL_WARN( "stoc", "Introspection: Property \"" <<
1719 aPropName
<< "\" found more than once in PropertySet" );
1727 // Indices in the export table
1728 sal_Int32 iAllExportedMethod
= 0;
1729 sal_Int32 iAllSupportedListener
= 0;
1731 std::set
<OUString
> seen
;
1733 // Flag, whether XInterface methods should be recorded
1734 // (this must be done only once, allowed initially)
1735 bool bXInterfaceIsInvalid
= false;
1737 // Flag whether the XInterface methods have already been recorded. If
1738 // sal_True, bXInterfaceIsInvalid is activated at the end of the interface
1739 // loop, and XInterface methods are cut off thereafter.
1740 bool bFoundXInterface
= false;
1742 size_t nClassCount
= SupportedClassSeq
.size();
1743 for( sal_Int32 nIdx
= 0 ; nIdx
< static_cast<sal_Int32
>(nClassCount
); nIdx
++ )
1745 Reference
<XIdlClass
> xImplClass2
= SupportedClassSeq
[nIdx
];
1746 while( xImplClass2
.is() )
1748 // Fetch interfaces from the implementation
1749 Sequence
< Reference
<XIdlClass
> > aClassSeq
= xImplClass2
->getInterfaces();
1750 sal_Int32 nIfaceCount
= aClassSeq
.getLength();
1752 aClassSeq
.realloc( nIfaceCount
+ 1 );
1753 aClassSeq
.getArray()[ nIfaceCount
] = xImplClass2
;
1755 for( const Reference
<XIdlClass
>& rxIfaceClass
: std::as_const(aClassSeq
) )
1757 if (!seen
.insert(rxIfaceClass
->getName()).second
) {
1761 // 2. Register fields as properties
1764 const Sequence
< Reference
<XIdlField
> > fields
= rxIfaceClass
->getFields();
1766 for( const Reference
<XIdlField
>& xField
: fields
)
1768 Reference
<XIdlClass
> xPropType
= xField
->getType();
1770 // Is the property sequence big enough?
1771 pAccess
->checkPropertyArraysSize( rPropCount
);
1773 // Enter in own property array
1774 Property
& rProp
= rAllPropArray
[ rPropCount
];
1775 OUString aFieldName
= xField
->getName();
1776 rProp
.Name
= aFieldName
;
1777 rProp
.Handle
= rPropCount
;
1778 Type
aFieldType( xPropType
->getTypeClass(), xPropType
->getName() );
1779 rProp
.Type
= aFieldType
;
1780 FieldAccessMode eAccessMode
= xField
->getAccessMode();
1781 rProp
.Attributes
= (eAccessMode
== FieldAccessMode_READONLY
||
1782 eAccessMode
== FieldAccessMode_CONST
)
1785 // Enter name in hash table
1786 OUString aPropName
= rProp
.Name
;
1788 // Do we have the name already?
1789 IntrospectionNameMap::iterator aIt
= rPropNameMap
.find( aPropName
);
1790 if (aIt
!= rPropNameMap
.end())
1793 // New entry in the hash table
1794 rPropNameMap
[ aPropName
] = rPropCount
;
1796 // Maintain table for XExactName
1797 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
1800 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq1
,
1801 rInterfaces1
, rPropCount
);
1802 rInterfaces1
[ rPropCount
] = xField
;
1804 // Remember type of property
1805 rMapTypeArray
[ rPropCount
] = MAP_FIELD
;
1806 rPropertyConceptArray
[ rPropCount
] = ATTRIBUTES
;
1807 pAccess
->mnAttributePropCount
++;
1816 // Get and remember all methods
1817 Sequence
< Reference
<XIdlMethod
> > methods
= rxIfaceClass
->getMethods();
1818 const Reference
<XIdlMethod
>* pSourceMethods
= methods
.getConstArray();
1819 sal_Int32 nSourceMethodCount
= methods
.getLength();
1821 // 3. a) Search get/set and listener methods
1823 // Create field for information about the methods, so that methods which are not
1824 // related to properties or listeners can easily be found later.
1825 // New: initialise MethodConceptArray
1828 STANDARD_METHOD
, // normal method, not related to properties or listeners
1829 GETSET_METHOD
, // belongs to a get/set property
1830 ADD_LISTENER_METHOD
, // add method of a listener interface
1831 REMOVE_LISTENER_METHOD
, // remove method of a listener interface
1832 INVALID_METHOD
// method whose class is not considered, e.g. XPropertySet
1834 std::unique_ptr
<MethodType
[]> pMethodTypes( new MethodType
[ nSourceMethodCount
] );
1835 std::unique_ptr
<sal_Int32
[]> pLocalMethodConcepts( new sal_Int32
[ nSourceMethodCount
] );
1836 for( i
= 0 ; i
< nSourceMethodCount
; i
++ )
1838 pMethodTypes
[ i
] = STANDARD_METHOD
;
1839 pLocalMethodConcepts
[ i
] = 0;
1842 for( i
= 0 ; i
< nSourceMethodCount
; i
++ )
1845 const Reference
<XIdlMethod
>& rxMethod_i
= pSourceMethods
[i
];
1846 sal_Int32
& rMethodConcept_i
= pLocalMethodConcepts
[ i
];
1849 OUString aMethName
= rxMethod_i
->getName();
1851 // Catalogue methods
1852 // Filter all (?) methods of XInterface so e.g. acquire and release
1853 // can not be called from scripting
1855 rxMethod_i
->getDeclaringClass()->getName());
1856 if (className
== "com.sun.star.uno.XInterface") {
1857 bFoundXInterface
= true;
1859 if( bXInterfaceIsInvalid
)
1861 pMethodTypes
[ i
] = INVALID_METHOD
;
1866 if( aMethName
!= "queryInterface" )
1868 rMethodConcept_i
|= MethodConcept::DANGEROUS
;
1872 } else if (className
== "com.sun.star.uno.XAggregation")
1874 if( aMethName
== "setDelegator" )
1876 rMethodConcept_i
|= MethodConcept::DANGEROUS
;
1879 } else if (className
1880 == "com.sun.star.container.XElementAccess")
1882 rMethodConcept_i
|= ( NAMECONTAINER
|
1885 pAccess
->mbElementAccess
= true;
1886 } else if (className
1887 == "com.sun.star.container.XNameContainer")
1889 rMethodConcept_i
|= NAMECONTAINER
;
1890 pAccess
->mbNameContainer
= true;
1891 pAccess
->mbNameReplace
= true;
1892 pAccess
->mbNameAccess
= true;
1893 pAccess
->mbElementAccess
= true;
1894 } else if (className
1895 == "com.sun.star.container.XNameReplace")
1897 rMethodConcept_i
|= NAMECONTAINER
;
1898 pAccess
->mbNameReplace
= true;
1899 pAccess
->mbNameAccess
= true;
1900 pAccess
->mbElementAccess
= true;
1901 } else if (className
1902 == "com.sun.star.container.XNameAccess")
1904 rMethodConcept_i
|= NAMECONTAINER
;
1905 pAccess
->mbNameAccess
= true;
1906 pAccess
->mbElementAccess
= true;
1907 } else if (className
1908 == "com.sun.star.container.XIndexContainer")
1910 rMethodConcept_i
|= INDEXCONTAINER
;
1911 pAccess
->mbIndexContainer
= true;
1912 pAccess
->mbIndexReplace
= true;
1913 pAccess
->mbIndexAccess
= true;
1914 pAccess
->mbElementAccess
= true;
1915 } else if (className
1916 == "com.sun.star.container.XIndexReplace")
1918 rMethodConcept_i
|= INDEXCONTAINER
;
1919 pAccess
->mbIndexReplace
= true;
1920 pAccess
->mbIndexAccess
= true;
1921 pAccess
->mbElementAccess
= true;
1922 } else if (className
1923 == "com.sun.star.container.XIndexAccess")
1925 rMethodConcept_i
|= INDEXCONTAINER
;
1926 pAccess
->mbIndexAccess
= true;
1927 pAccess
->mbElementAccess
= true;
1928 } else if (className
1929 == "com.sun.star.container.XEnumerationAccess")
1931 rMethodConcept_i
|= ENUMERATION
;
1932 pAccess
->mbEnumerationAccess
= true;
1933 pAccess
->mbElementAccess
= true;
1934 } else if (className
1935 == "com.sun.star.reflection.XIdlArray")
1937 pAccess
->mbIdlArray
= true;
1938 } else if (className
1939 == "com.sun.star.lang.XUnoTunnel")
1941 pAccess
->mbUnoTunnel
= true;
1944 // If the name is too short, it isn't anything
1945 if( aMethName
.getLength() <= 3 )
1948 // Is it a get method?
1950 if( aMethName
.startsWith("get", &aPropName
) )
1952 // Get methods must not have any parameters
1953 Sequence
< Reference
<XIdlClass
> > getParams
= rxMethod_i
->getParameterTypes();
1954 if( getParams
.hasElements() )
1959 // Do we have the name already?
1960 IntrospectionNameMap::iterator aIt
= rPropNameMap
.find( aPropName
);
1961 if (aIt
!= rPropNameMap
.end())
1965 String( "Introspection: Property \"" ) +
1966 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
1967 String( "\" found more than once" ) );
1972 // It is already at least a read-only property
1973 rMethodConcept_i
|= PROPERTY
;
1975 pMethodTypes
[i
] = GETSET_METHOD
;
1976 Reference
<XIdlClass
> xGetRetType
= rxMethod_i
->getReturnType();
1978 // Is the property sequence big enough?
1979 pAccess
->checkPropertyArraysSize( rPropCount
);
1981 // Write it in its property array
1982 Property
& rProp
= rAllPropArray
[ rPropCount
];
1983 rProp
.Name
= aPropName
;
1984 rProp
.Handle
= rPropCount
;
1985 rProp
.Type
= Type( xGetRetType
->getTypeClass(), xGetRetType
->getName() );
1986 rProp
.Attributes
= READONLY
;
1988 // New entry in the hash table
1989 rPropNameMap
[ aPropName
] = rPropCount
;
1991 // Maintain table for XExactName
1992 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
1994 // Remember get method
1995 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq1
,
1996 rInterfaces1
, rPropCount
);
1997 rInterfaces1
[ rPropCount
] = rxMethod_i
;
1999 // Remember type of property
2000 rMapTypeArray
[ rPropCount
] = MAP_GETSET
;
2001 rPropertyConceptArray
[ rPropCount
] = METHODS
;
2002 pAccess
->mnMethodPropCount
++;
2004 // Search for matching set method
2006 for( k
= 0 ; k
< nSourceMethodCount
; k
++ )
2009 const Reference
<XIdlMethod
>& rxMethod_k
= pSourceMethods
[k
];
2011 // Accept only methods that are not already assigned
2012 if( k
== i
|| pMethodTypes
[k
] != STANDARD_METHOD
)
2015 // Get name and evaluate
2016 OUString aMethName2
= rxMethod_k
->getName();
2017 OUString aPropName2
;
2018 if (!(aMethName2
.startsWith("set", &aPropName2
)
2019 && aPropName2
== aPropName
))
2022 // A set method must return void
2023 Reference
<XIdlClass
> xSetRetType
= rxMethod_k
->getReturnType();
2024 if( xSetRetType
->getTypeClass() != TypeClass_VOID
)
2029 // A set method may only have one parameter
2030 Sequence
< Reference
<XIdlClass
> > setParams
= rxMethod_k
->getParameterTypes();
2031 sal_Int32 nParamCount
= setParams
.getLength();
2032 if( nParamCount
!= 1 )
2037 // Next, the return type must correspond to the parameter type
2038 const Reference
<XIdlClass
>* pParamArray2
= setParams
.getConstArray();
2039 Reference
<XIdlClass
> xParamType
= pParamArray2
[ 0 ];
2040 if( xParamType
->equals( xGetRetType
) )
2042 pLocalMethodConcepts
[ k
] = PROPERTY
;
2044 pMethodTypes
[k
] = GETSET_METHOD
;
2046 // Delete read-only flag again
2047 rProp
.Attributes
&= ~READONLY
;
2049 // Remember set method
2050 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq2
,
2051 rInterfaces2
, rPropCount
);
2052 rInterfaces2
[ rPropCount
] = rxMethod_k
;
2060 // Is it an add listener method?
2061 else if( aMethName
.startsWith("add", &aPropName
) )
2063 // Does it end with "Listener"?
2064 OUString aListenerName
;
2065 if( !aPropName
.endsWith("Listener", &aListenerName
) )
2068 // TODO: More accurate tests could still be carried out here
2070 // - Number and type of parameters
2073 // Search for matching remove method, otherwise not applicable
2075 for( k
= 0 ; k
< nSourceMethodCount
; k
++ )
2078 const Reference
<XIdlMethod
>& rxMethod_k
= pSourceMethods
[k
];
2080 // Accept only methods that are not already assigned
2081 if( k
== i
|| pMethodTypes
[k
] != STANDARD_METHOD
)
2084 // Get name and evaluate
2085 OUString aMethName2
= rxMethod_k
->getName();
2086 OUString aListenerName2
;
2087 if (!(aMethName2
.startsWith(
2088 "remove", &aPropName
)
2089 && aPropName
.endsWith(
2090 "Listener", &aListenerName2
)
2091 && aListenerName2
== aListenerName
))
2094 // TODO: More accurate tests could still be carried out here
2096 // - Number and type of parameters
2099 // Methods are recognised as a listener interface
2100 rMethodConcept_i
|= LISTENER
;
2101 pLocalMethodConcepts
[ k
] |= LISTENER
;
2103 pMethodTypes
[i
] = ADD_LISTENER_METHOD
;
2104 pMethodTypes
[k
] = REMOVE_LISTENER_METHOD
;
2110 // A set method could still exist without a corresponding get method,
2111 // this must be a write-only property
2112 for( i
= 0 ; i
< nSourceMethodCount
; i
++ )
2115 const Reference
<XIdlMethod
>& rxMethod_i
= pSourceMethods
[i
];
2117 // Accept only methods that are not already assigned
2118 if( pMethodTypes
[i
] != STANDARD_METHOD
)
2122 OUString aMethName
= rxMethod_i
->getName();
2124 // If the name is too short, it isn't anything
2125 if( aMethName
.getLength() <= 3 )
2128 // Is it a set method without associated get method?
2130 if( aMethName
.startsWith("set", &aPropName
) )
2132 // A set method must return void
2133 Reference
<XIdlClass
> xSetRetType
= rxMethod_i
->getReturnType();
2134 if( xSetRetType
->getTypeClass() != TypeClass_VOID
)
2139 // A set method may only have one parameter
2140 Sequence
< Reference
<XIdlClass
> > setParams
= rxMethod_i
->getParameterTypes();
2141 sal_Int32 nParamCount
= setParams
.getLength();
2142 if( nParamCount
!= 1 )
2147 // Do we have the name already?
2148 IntrospectionNameMap::iterator aIt
= rPropNameMap
.find( aPropName
);
2149 if (aIt
!= rPropNameMap
.end())
2153 String( "Introspection: Property \"" ) +
2154 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2155 String( "\" found more than once" ) );
2160 // Now we know it's a write only property
2161 pLocalMethodConcepts
[ i
] = PROPERTY
;
2163 pMethodTypes
[i
] = GETSET_METHOD
;
2164 Reference
<XIdlClass
> xGetRetType
= setParams
.getConstArray()[0];
2166 // Is the property sequence big enough?
2167 pAccess
->checkPropertyArraysSize( rPropCount
);
2169 // Write it in its property array
2170 Property
& rProp
= rAllPropArray
[ rPropCount
];
2171 rProp
.Name
= aPropName
;
2172 rProp
.Handle
= rPropCount
;
2173 rProp
.Type
= Type( xGetRetType
->getTypeClass(), xGetRetType
->getName() );
2174 rProp
.Attributes
= 0; // PROPERTY_WRITEONLY ???
2176 // New entry in the hash table
2177 rPropNameMap
[ aPropName
] = rPropCount
;
2179 // Maintain table for XExactName
2180 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
2182 // Remember set method
2183 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq2
,
2184 rInterfaces2
, rPropCount
);
2185 rInterfaces2
[ rPropCount
] = rxMethod_i
;
2187 // Remember type of property
2188 rMapTypeArray
[ rPropCount
] = MAP_SETONLY
;
2189 rPropertyConceptArray
[ rPropCount
] = METHODS
;
2190 pAccess
->mnMethodPropCount
++;
2198 // 4. Place methods in overall sequence
2200 // How many methods in the method sequence
2201 sal_Int32 nExportedMethodCount
= 0;
2202 sal_Int32 nSupportedListenerCount
= 0;
2203 for( i
= 0 ; i
< nSourceMethodCount
; i
++ )
2205 if( pMethodTypes
[ i
] != INVALID_METHOD
)
2207 nExportedMethodCount
++;
2209 if( pMethodTypes
[ i
] == ADD_LISTENER_METHOD
)
2211 nSupportedListenerCount
++;
2215 // Enlarge sequences in the access object accordingly
2216 pAccess
->maAllMethodSeq
.resize( nExportedMethodCount
+ iAllExportedMethod
);
2217 pAccess
->maMethodConceptSeq
.resize( nExportedMethodCount
+ iAllExportedMethod
);
2218 pAccess
->maSupportedListenerSeq
.resize( nSupportedListenerCount
+ iAllSupportedListener
);
2221 for( i
= 0 ; i
< nSourceMethodCount
; i
++ )
2223 if( pMethodTypes
[ i
] != INVALID_METHOD
)
2226 const Reference
<XIdlMethod
>& rxMethod
= pSourceMethods
[i
];
2228 // Enter name in hash table if not already known
2229 OUString aMethName2
= rxMethod
->getName();
2230 IntrospectionNameMap::iterator aIt
= rMethodNameMap
.find( aMethName2
);
2231 if( aIt
== rMethodNameMap
.end() )
2234 rMethodNameMap
[ aMethName2
] = iAllExportedMethod
;
2236 // Maintain table for XExactName
2237 rLowerToExactNameMap
[ aMethName2
.toAsciiLowerCase() ] = aMethName2
;
2241 sal_Int32 iHashResult
= aIt
->second
;
2243 Reference
<XIdlMethod
> xExistingMethod
= pAccess
->maAllMethodSeq
[iHashResult
];
2245 Reference
< XIdlClass
> xExistingMethClass
=
2246 xExistingMethod
->getDeclaringClass();
2247 Reference
< XIdlClass
> xNewMethClass
= rxMethod
->getDeclaringClass();
2248 if( xExistingMethClass
->equals( xNewMethClass
) )
2252 pAccess
->maAllMethodSeq
[iAllExportedMethod
] = rxMethod
;
2254 // If a concept has been set, is the method "normal"?
2255 sal_Int32
& rMethodConcept_i
= pLocalMethodConcepts
[ i
];
2256 if( !rMethodConcept_i
)
2257 rMethodConcept_i
= MethodConcept_NORMAL_IMPL
;
2258 pAccess
->maMethodConceptSeq
[ iAllExportedMethod
] = rMethodConcept_i
;
2259 iAllExportedMethod
++;
2261 if( pMethodTypes
[ i
] == ADD_LISTENER_METHOD
)
2263 // Determine class of listener
2264 const Reference
<XIdlMethod
>& rxMethod
= pSourceMethods
[i
];
2266 // Enter void as default class
2267 css::uno::Reference
<css::reflection::XIdlClass
>
2269 reflection
->forName(
2270 cppu::UnoType
<void>::get()
2272 // Old: Reference<XIdlClass> xListenerClass = Void_getReflection()->getIdlClass();
2274 // Option 1: Search for parameters for a listener class
2275 // Disadvantage: Superclasses should be searched recursively
2276 Sequence
< Reference
<XIdlClass
> > aParams
= rxMethod
->getParameterTypes();
2278 css::uno::Reference
<css::reflection::XIdlClass
>
2279 xEventListenerClass(
2280 reflection
->forName(
2282 css::lang::XEventListener
>::get()
2284 // Old: Reference<XIdlClass> xEventListenerClass = XEventListener_getReflection()->getIdlClass();
2285 auto pParam
= std::find_if(aParams
.begin(), aParams
.end(),
2286 [&xEventListenerClass
](const Reference
<XIdlClass
>& rxClass
) {
2287 // Are we derived from a listener?
2288 return rxClass
->equals( xEventListenerClass
)
2289 || isDerivedFrom( rxClass
, xEventListenerClass
);
2291 if (pParam
!= aParams
.end())
2293 xListenerClass
= *pParam
;
2296 // Option 2: Unload the name of the method
2297 // Disadvantage: Does not work with test listeners, where it does not exist
2298 //aMethName = rxMethod->getName();
2299 //aListenerName = aMethName.Copy( 3, aMethName.Len()-8-3 );
2300 //Reference<XIdlClass> xListenerClass = reflection->forName( aListenerName );
2301 Type
aListenerType( TypeClass_INTERFACE
, xListenerClass
->getName() );
2302 pAccess
->maSupportedListenerSeq
[ iAllSupportedListener
] = aListenerType
;
2303 iAllSupportedListener
++;
2307 // When there were XInterface methods in this run,
2308 // ignore them in the future
2309 if( bFoundXInterface
)
2310 bXInterfaceIsInvalid
= true;
2313 // Do superclasses exist? Then continue here
2314 Sequence
< Reference
<XIdlClass
> > aSuperClassSeq
= xImplClass2
->getSuperclasses();
2316 // Currently only one superclass is considered
2317 if( aSuperClassSeq
.getLength() >= 1 )
2319 xImplClass2
= aSuperClassSeq
.getConstArray()[0];
2320 OSL_ENSURE( xImplClass2
.is(), "super class null" );
2324 xImplClass2
= nullptr;
2329 // Apply number of exported methods and adapt Sequences
2330 // (can be different because duplicate methods are thrown
2331 // out only after the determination of nExportedMethodCount)
2332 sal_Int32
& rMethCount
= pAccess
->mnMethCount
;
2333 rMethCount
= iAllExportedMethod
;
2334 pAccess
->maAllMethodSeq
.resize( rMethCount
);
2335 pAccess
->maMethodConceptSeq
.resize( rMethCount
);
2337 // Resize the property sequences
2338 pAccess
->maAllPropertySeq
.resize( rPropCount
);
2339 pAccess
->maPropertyConceptSeq
.resize( rPropCount
);
2340 pAccess
->maMapTypeSeq
.resize( rPropCount
);
2342 // Register struct fields as properties
2343 else //if( eType == TypeClass_STRUCT )
2345 // Is it an interface or a struct?
2346 //Reference<XIdlClass> xClassRef = aToInspectObj.getReflection()->getIdlClass();
2347 css::uno::Reference
<css::reflection::XIdlClass
> xClassRef(
2348 reflection
->forName(aToInspectObj
.getValueTypeName()));
2349 if( !xClassRef
.is() )
2351 SAL_WARN( "stoc", "Can't get XIdlClass from Reflection" );
2352 return new ImplIntrospectionAccess(aToInspectObj
, pAccess
);
2356 const Sequence
< Reference
<XIdlField
> > fields
= xClassRef
->getFields();
2358 for( const Reference
<XIdlField
>& xField
: fields
)
2360 Reference
<XIdlClass
> xPropType
= xField
->getType();
2361 OUString aPropName
= xField
->getName();
2363 // Is the property sequence big enough?
2364 pAccess
->checkPropertyArraysSize( rPropCount
);
2366 // Write it in its property array
2367 Property
& rProp
= rAllPropArray
[ rPropCount
];
2368 rProp
.Name
= aPropName
;
2369 rProp
.Handle
= rPropCount
;
2370 rProp
.Type
= Type( xPropType
->getTypeClass(), xPropType
->getName() );
2371 FieldAccessMode eAccessMode
= xField
->getAccessMode();
2372 rProp
.Attributes
= (eAccessMode
== FieldAccessMode_READONLY
||
2373 eAccessMode
== FieldAccessMode_CONST
)
2376 //FieldAccessMode eAccessMode = xField->getAccessMode();
2377 //rProp.Attributes = (eAccessMode == FieldAccessMode::READONLY || eAccessMode == CONST)
2378 //? PropertyAttribute::READONLY : 0;
2380 // Write name in hash table
2381 rPropNameMap
[ aPropName
] = rPropCount
;
2383 // Maintain table for XExactName
2384 rLowerToExactNameMap
[ aPropName
.toAsciiLowerCase() ] = aPropName
;
2387 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess
->aInterfaceSeq1
,
2388 rInterfaces1
, rPropCount
);
2389 rInterfaces1
[ rPropCount
] = xField
;
2391 // Remember type of property
2392 rMapTypeArray
[ rPropCount
] = MAP_FIELD
;
2393 rPropertyConceptArray
[ rPropCount
] = ATTRIBUTES
;
2394 pAccess
->mnAttributePropCount
++;
2401 // Set property sequence to the correct length
2402 pAccess
->maAllPropertySeq
.resize( pAccess
->mnPropCount
);
2404 return new ImplIntrospectionAccess(aToInspectObj
, pAccess
);
2409 css::uno::Reference
<css::uno::XComponentContext
> const & context
):
2410 instance(new Implementation(context
))
2413 rtl::Reference
<cppu::OWeakObject
> instance
;
2417 public rtl::StaticWithArg
<
2418 Instance
, css::uno::Reference
<css::uno::XComponentContext
>, Singleton
>
2423 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
2424 com_sun_star_comp_stoc_Introspection_get_implementation(
2425 css::uno::XComponentContext
* context
,
2426 css::uno::Sequence
<css::uno::Any
> const & arguments
)
2429 arguments
.hasElements(), "stoc", "unexpected singleton arguments");
2430 return cppu::acquire(Singleton::get(context
).instance
.get());
2433 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */