nss: upgrade to release 3.73
[LibreOffice.git] / stoc / source / inspect / introspection.cxx
blob9317a5c354932c5b2fe75efca7859ed7ca7909dc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <cassert>
23 #include <cstddef>
24 #include <limits>
25 #include <map>
26 #include <memory>
27 #include <set>
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;
76 using namespace cppu;
77 using namespace osl;
79 namespace
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
109 #define MAP_FIELD 1
110 // Properties that get described with get/set methods
111 #define MAP_GETSET 2
112 // Properties with only a set method
113 #define MAP_SETONLY 3
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
128 OUString,
129 sal_Int32
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
138 OUString,
139 OUString
141 LowerToExactNameMap;
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
181 bool mbFastPropSet;
182 bool mbElementAccess;
183 bool mbNameAccess;
184 bool mbNameReplace;
185 bool mbNameContainer;
186 bool mbIndexAccess;
187 bool mbIndexReplace;
188 bool mbIndexContainer;
189 bool mbEnumerationAccess;
190 bool mbIdlArray;
191 bool mbUnoTunnel;
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;
202 // Number of methods
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 );
213 public:
214 explicit IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ );
215 sal_Int32 getPropertyIndex( const OUString& aPropertyName ) const;
216 sal_Int32 getMethodIndex( const OUString& aMethodName ) const;
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; }
234 // Ctor
235 IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ )
236 : mxCoreReflection( xCoreReflection_ )
238 aInterfaceSeq1.resize( ARRAY_SIZE_STEP );
239 aInterfaceSeq2.resize( ARRAY_SIZE_STEP );
241 // Property-Data
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;
255 mbIdlArray = false;
256 mbUnoTunnel = false;
258 mpOrgPropertyHandleArray = nullptr;
260 mnPropCount = 0;
261 //mnDangerousPropCount = 0;
262 mnPropertySetPropCount = 0;
263 mnAttributePropCount = 0;
264 mnMethodPropCount = 0;
266 // Method-Data
267 mnMethCount = 0;
270 sal_Int32 IntrospectionAccessStatic_Impl::getPropertyIndex( const OUString& aPropertyName ) const
272 auto aIt = maPropertyNameMap.find(aPropertyName);
273 if (aIt != maPropertyNameMap.end())
274 return aIt->second;
276 return -1;
279 sal_Int32 IntrospectionAccessStatic_Impl::getMethodIndex( const OUString& aMethodName ) const
281 auto aIt = maMethodNameMap.find(aMethodName);
282 if (aIt != maMethodNameMap.end())
284 return aIt->second;
287 // #95159 Check if full qualified name matches
288 sal_Int32 nSearchFrom = aMethodName.getLength();
289 while( true )
291 // Strategy: Search back until the first '_' is found
292 sal_Int32 nFound = aMethodName.lastIndexOf( '_', nSearchFrom );
293 if( nFound == -1 )
294 break;
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 );
306 if( xClass.is() )
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 ) )
318 return iHashResult;
320 else
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 ) )
334 return i;
342 nSearchFrom = nFound - 1;
343 if( nSearchFrom < 0 )
344 break;
346 return -1;
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 );
353 if( i == -1 )
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);
377 // Test flags
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:
388 // Get Property
389 const Property& rProp = maAllPropertySeq[ nSequenceIndex ];
391 // Convert Interface-Parameter to the correct type
392 bool bUseCopy = false;
393 Any aRealValue;
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() )
409 bUseCopy = true;
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 );
427 else
429 // throw UnknownPropertyException
432 // else take the normal one
433 else
435 // Retrieve PropertySet-Interface
436 Reference<XPropertySet> xPropSet =
437 Reference<XPropertySet>::query( xInterface );
438 if( xPropSet.is() )
440 xPropSet->setPropertyValue( rProp.Name, bUseCopy ? aRealValue : aValue );
442 else
444 // throw UnknownPropertyException
448 break;
450 case MAP_FIELD:
452 Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
453 Reference<XIdlField2> xField2(xField, UNO_QUERY);
454 if( xField2.is() )
456 xField2->set( const_cast<Any&>(obj), aValue );
457 // IllegalArgumentException
458 // NullPointerException
459 } else
460 if( xField.is() )
462 xField->set( obj, aValue );
463 // IllegalArgumentException
464 // NullPointerException
466 else
468 // throw IllegalArgumentException();
471 break;
473 case MAP_GETSET:
474 case MAP_SETONLY:
476 // Fetch set method
477 Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq2[ nSequenceIndex ].get());
478 if( xMethod.is() )
480 Sequence<Any> args( 1 );
481 args.getArray()[0] = aValue;
482 xMethod->invoke( obj, args );
484 else
486 // throw IllegalArgumentException();
489 break;
493 Any IntrospectionAccessStatic_Impl::getPropertyValue( const Any& obj, const OUString& aPropertyName ) const
495 sal_Int32 i = getPropertyIndex( aPropertyName );
496 if( i != -1 )
497 return getPropertyValueByIndex( obj, i );
499 throw UnknownPropertyException(aPropertyName);
502 Any IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex) const
504 Any aRet;
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();
514 return aRet;
518 switch( maMapTypeSeq[ nSequenceIndex ] )
520 case MAP_PROPERTY_SET:
522 // Acquire property
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);
538 else
540 // throw UnknownPropertyException
541 return aRet;
544 // Otherwise use the normal one
545 else
547 // Fetch the PropertySet interface
548 Reference<XPropertySet> xPropSet =
549 Reference<XPropertySet>::query( xInterface );
550 if( xPropSet.is() )
552 aRet = xPropSet->getPropertyValue( rProp.Name );
554 else
556 // throw UnknownPropertyException
557 return aRet;
561 break;
563 case MAP_FIELD:
565 Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
566 if( xField.is() )
568 aRet = xField->get( obj );
569 // IllegalArgumentException
570 // NullPointerException
572 else
574 // throw IllegalArgumentException();
575 return aRet;
578 break;
580 case MAP_GETSET:
582 // Fetch get method
583 Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq1[ nSequenceIndex ].get());
584 if( xMethod.is() )
586 Sequence<Any> args;
587 aRet = xMethod->invoke( obj, args );
589 else
591 // throw IllegalArgumentException();
592 return aRet;
595 break;
597 case MAP_SETONLY:
598 // Get method does not exist
599 // throw WriteOnlyPropertyException();
600 return aRet;
602 return aRet;
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;
648 // As interface
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
663 osl::Mutex m_aMutex;
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();
689 public:
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() )
789 aGuard.clear();
790 Reference<XElementAccess> xElementAccess( mxIface, UNO_QUERY );
791 aGuard.reset();
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() )
836 aGuard.clear();
837 cacheXNameContainer();
839 return mxObjNameContainer;
842 Reference<XNameReplace> ImplIntrospectionAccess::getXNameReplace()
844 ClearableGuard< Mutex > aGuard( m_aMutex );
846 if( !mxObjNameReplace.is() )
848 aGuard.clear();
849 cacheXNameContainer();
851 return mxObjNameReplace;
854 Reference<XNameAccess> ImplIntrospectionAccess::getXNameAccess()
856 ClearableGuard< Mutex > aGuard( m_aMutex );
858 if( !mxObjNameAccess.is() )
860 aGuard.clear();
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() )
904 aGuard.clear();
905 cacheXIndexContainer();
907 return mxObjIndexContainer;
910 Reference<XIndexReplace> ImplIntrospectionAccess::getXIndexReplace()
912 ClearableGuard< Mutex > aGuard( m_aMutex );
914 if( !mxObjIndexReplace.is() )
916 aGuard.clear();
917 cacheXIndexContainer();
919 return mxObjIndexReplace;
922 Reference<XIndexAccess> ImplIntrospectionAccess::getXIndexAccess()
924 ClearableGuard< Mutex > aGuard( m_aMutex );
926 if( !mxObjIndexAccess.is() )
928 aGuard.clear();
929 cacheXIndexContainer();
931 return mxObjIndexAccess;
934 Reference<XEnumerationAccess> ImplIntrospectionAccess::getXEnumerationAccess()
936 ResettableGuard< Mutex > aGuard( m_aMutex );
938 if( !mxObjEnumerationAccess.is() )
940 aGuard.clear();
941 Reference<XEnumerationAccess> xEnumerationAccess( mxIface, UNO_QUERY );
942 aGuard.reset();
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() )
955 aGuard.clear();
956 Reference<XIdlArray> xIdlArray( mxIface, UNO_QUERY );
957 aGuard.reset();
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(
968 rType,
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() );
993 return aRet;
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)
1018 if( mxIface.is() )
1020 Reference<XPropertySet> xPropSet =
1021 Reference<XPropertySet>::query( mxIface );
1022 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1023 if( xPropSet.is() )
1024 xPropSet->addPropertyChangeListener(aPropertyName, aListener);
1028 void ImplIntrospectionAccess::removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
1030 if( mxIface.is() )
1032 Reference<XPropertySet> xPropSet =
1033 Reference<XPropertySet>::query( mxIface );
1034 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1035 if( xPropSet.is() )
1036 xPropSet->removePropertyChangeListener(aPropertyName, aListener);
1040 void ImplIntrospectionAccess::addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1042 if( mxIface.is() )
1044 Reference<XPropertySet> xPropSet =
1045 Reference<XPropertySet>::query( mxIface );
1046 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1047 if( xPropSet.is() )
1048 xPropSet->addVetoableChangeListener(aPropertyName, aListener);
1052 void ImplIntrospectionAccess::removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1054 if( mxIface.is() )
1056 Reference<XPropertySet> xPropSet =
1057 Reference<XPropertySet>::query( mxIface );
1058 if( xPropSet.is() )
1059 xPropSet->removeVetoableChangeListener(aPropertyName, aListener);
1064 // Methods from XFastPropertySet
1065 void ImplIntrospectionAccess::setFastPropertyValue(sal_Int32, const Any&)
1069 Any ImplIntrospectionAccess::getFastPropertyValue(sal_Int32)
1071 return Any();
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 |
1202 PROPERTY |
1203 LISTENER |
1204 ENUMERATION |
1205 NAMECONTAINER |
1206 INDEXCONTAINER;
1209 sal_Int32 ImplIntrospectionAccess::getSuppliedPropertyConcepts()
1211 return PropertyConcept::DANGEROUS |
1212 PROPERTYSET |
1213 ATTRIBUTES |
1214 METHODS;
1217 Property ImplIntrospectionAccess::getProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1219 Property aRet;
1220 sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1221 bool bFound = false;
1222 if( i != -1 )
1224 sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1225 if( (PropertyConcepts & nConcept) != 0 )
1227 aRet = mpStaticImpl->getProperties()[ i ];
1228 bFound = true;
1231 if( !bFound )
1232 throw NoSuchElementException(Name);
1233 return aRet;
1236 sal_Bool ImplIntrospectionAccess::hasProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1238 sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1239 bool bRet = false;
1240 if( i != -1 )
1242 sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1243 if( (PropertyConcepts & nConcept) != 0 )
1244 bRet = true;
1246 return bRet;
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 |
1253 ATTRIBUTES |
1254 METHODS;
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 );
1307 if( i != -1 )
1310 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1311 if( (MethodConcepts & nConcept) != 0 )
1313 xRet = mpStaticImpl->getMethods()[i];
1316 if( !xRet.is() )
1317 throw NoSuchMethodException(Name);
1318 return xRet;
1321 sal_Bool ImplIntrospectionAccess::hasMethod(const OUString& Name, sal_Int32 MethodConcepts)
1323 sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1324 bool bRet = false;
1325 if( i != -1 )
1327 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1328 if( (MethodConcepts & nConcept) != 0 )
1329 bRet = true;
1331 return bRet;
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 |
1338 PROPERTY |
1339 LISTENER |
1340 ENUMERATION |
1341 NAMECONTAINER |
1342 INDEXCONTAINER |
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;
1409 return xRet;
1412 // Methods from XMaterialHolder
1413 Any ImplIntrospectionAccess::getMaterial()
1415 return maInspectedObject;
1418 // Methods from XExactName
1419 OUString ImplIntrospectionAccess::getExactName( const OUString& rApproximateName )
1421 OUString aRetStr;
1422 LowerToExactNameMap::iterator aIt =
1423 mpStaticImpl->maLowerToExactNameMap.find( rApproximateName.toAsciiLowerCase() );
1424 if (aIt != mpStaticImpl->maLowerToExactNameMap.end())
1425 aRetStr = (*aIt).second;
1426 return aRetStr;
1429 struct TypeKey {
1430 TypeKey(
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;
1448 OUString types;
1451 struct TypeKeyLess {
1452 bool operator ()(TypeKey const & key1, TypeKey const & key2) const {
1453 if (key1.properties.get() < key2.properties.get()) {
1454 return true;
1456 if (key1.properties.get() > key2.properties.get()) {
1457 return false;
1459 return key1.types < key2.types;
1463 template<typename Key, typename Less> class Cache {
1464 public:
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>();
1469 } else {
1470 if (i->second.hits < std::numeric_limits<unsigned>::max()) {
1471 ++i->second.hits;
1473 assert(i->second.access.is());
1474 return i->second.access;
1478 void insert(
1479 Key const & key,
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;
1490 map_.erase(del);
1492 bool ins = map_.emplace(key, Data(access)).second;
1493 assert(ins); (void)ins;
1496 void clear() { map_.clear(); }
1498 private:
1499 struct Data {
1500 explicit Data(
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;
1511 Map map_;
1514 typedef
1515 cppu::WeakComponentImplHelper<
1516 css::lang::XServiceInfo, css::beans::XIntrospection>
1517 Implementation_Base;
1519 class Implementation: private cppu::BaseMutex, public Implementation_Base {
1520 public:
1521 explicit Implementation(
1522 css::uno::Reference<css::uno::XComponentContext> const & context):
1523 Implementation_Base(m_aMutex),
1524 reflection_(css::reflection::theCoreReflection::get(context))
1527 private:
1528 virtual void SAL_CALL disposing() override {
1529 osl::MutexGuard g(m_aMutex);
1530 reflection_.clear();
1531 typeCache_.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" };
1544 return s;
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;
1567 css::uno::Type t;
1568 if (aObject >>= t) {
1569 css::uno::Reference<css::reflection::XIdlClass> c(
1570 reflection->forName(t.getTypeName()));
1571 if (!c.is()) {
1572 SAL_WARN("stoc", "cannot reflect type " << t.getTypeName());
1573 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1575 aToInspectObj <<= c;
1576 } else {
1577 aToInspectObj = aObject;
1580 // Examine object
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) )
1587 if( !x->is() )
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());
1608 } else {
1609 SAL_WARN(
1610 "stoc",
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 );
1617 if( xPropSet.is() )
1618 xPropSetInfo = xPropSet->getPropertySetInfo();
1620 } else {
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);
1632 if (pAccess.is()) {
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;
1645 sal_Int32 i;
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();
1659 if( nTypeCount )
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
1682 if( bFast )
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 ];
1692 if( bFast )
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;
1716 else
1718 SAL_WARN( "stoc", "Introspection: Property \"" <<
1719 aPropName << "\" found more than once in PropertySet" );
1722 // Adjust count
1723 rPropCount++;
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) {
1758 continue;
1761 // 2. Register fields as properties
1763 // Get fields
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)
1783 ? READONLY : 0;
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())
1791 continue;
1793 // New entry in the hash table
1794 rPropNameMap[ aPropName ] = rPropCount;
1796 // Maintain table for XExactName
1797 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1799 // Remember field
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++;
1809 // Adjust count
1810 rPropCount++;
1814 // 3. Methods
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
1826 enum MethodType
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++ )
1844 // Address method
1845 const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
1846 sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
1848 // Fetch name
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
1854 OUString className(
1855 rxMethod_i->getDeclaringClass()->getName());
1856 if (className == "com.sun.star.uno.XInterface") {
1857 bFoundXInterface = true;
1859 if( bXInterfaceIsInvalid )
1861 pMethodTypes[ i ] = INVALID_METHOD;
1862 continue;
1864 else
1866 if( aMethName != "queryInterface" )
1868 rMethodConcept_i |= MethodConcept::DANGEROUS;
1869 continue;
1872 } else if (className == "com.sun.star.uno.XAggregation")
1874 if( aMethName == "setDelegator" )
1876 rMethodConcept_i |= MethodConcept::DANGEROUS;
1877 continue;
1879 } else if (className
1880 == "com.sun.star.container.XElementAccess")
1882 rMethodConcept_i |= ( NAMECONTAINER |
1883 INDEXCONTAINER |
1884 ENUMERATION );
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 )
1946 continue;
1948 // Is it a get method?
1949 OUString aPropName;
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() )
1956 continue;
1959 // Do we have the name already?
1960 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1961 if (aIt != rPropNameMap.end())
1963 /* TODO
1964 SAL_INFO("stoc",(
1965 String( "Introspection: Property \"" ) +
1966 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
1967 String( "\" found more than once" ) );
1969 continue;
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
2005 sal_Int32 k;
2006 for( k = 0 ; k < nSourceMethodCount ; k++ )
2008 // Address method
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 )
2013 continue;
2015 // Get name and evaluate
2016 OUString aMethName2 = rxMethod_k->getName();
2017 OUString aPropName2;
2018 if (!(aMethName2.startsWith("set", &aPropName2)
2019 && aPropName2 == aPropName))
2020 continue;
2022 // A set method must return void
2023 Reference<XIdlClass> xSetRetType = rxMethod_k->getReturnType();
2024 if( xSetRetType->getTypeClass() != TypeClass_VOID )
2026 continue;
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 )
2034 continue;
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;
2056 // Adjust count
2057 rPropCount++;
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) )
2066 continue;
2068 // TODO: More accurate tests could still be carried out here
2069 // - Return type
2070 // - Number and type of parameters
2073 // Search for matching remove method, otherwise not applicable
2074 sal_Int32 k;
2075 for( k = 0 ; k < nSourceMethodCount ; k++ )
2077 // Address method
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 )
2082 continue;
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))
2092 continue;
2094 // TODO: More accurate tests could still be carried out here
2095 // - Return type
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++ )
2114 // Address method
2115 const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
2117 // Accept only methods that are not already assigned
2118 if( pMethodTypes[i] != STANDARD_METHOD )
2119 continue;
2121 // Get name
2122 OUString aMethName = rxMethod_i->getName();
2124 // If the name is too short, it isn't anything
2125 if( aMethName.getLength() <= 3 )
2126 continue;
2128 // Is it a set method without associated get method?
2129 OUString aPropName;
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 )
2136 continue;
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 )
2144 continue;
2147 // Do we have the name already?
2148 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2149 if (aIt != rPropNameMap.end())
2151 /* TODO:
2152 SAL_INFO("stoc",(
2153 String( "Introspection: Property \"" ) +
2154 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2155 String( "\" found more than once" ) );
2157 continue;
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++;
2192 // Adjust count
2193 rPropCount++;
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 );
2220 // Write in methods
2221 for( i = 0 ; i < nSourceMethodCount ; i++ )
2223 if( pMethodTypes[ i ] != INVALID_METHOD )
2225 // Address 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() )
2233 // Enter
2234 rMethodNameMap[ aMethName2 ] = iAllExportedMethod;
2236 // Maintain table for XExactName
2237 rLowerToExactNameMap[ aMethName2.toAsciiLowerCase() ] = aMethName2;
2239 else
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 ) )
2249 continue;
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>
2268 xListenerClass(
2269 reflection->forName(
2270 cppu::UnoType<void>::get()
2271 .getTypeName()));
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(
2281 cppu::UnoType<
2282 css::lang::XEventListener>::get()
2283 .getTypeName()));
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" );
2322 else
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);
2355 // Get fields
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)
2374 ? READONLY : 0;
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;
2386 // Remember field
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++;
2396 // Adjust count
2397 rPropCount++;
2401 // Set property sequence to the correct length
2402 pAccess->maAllPropertySeq.resize( pAccess->mnPropCount );
2404 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
2407 struct Instance {
2408 explicit Instance(
2409 css::uno::Reference<css::uno::XComponentContext> const & context):
2410 instance(new Implementation(context))
2413 rtl::Reference<cppu::OWeakObject> instance;
2416 struct Singleton:
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)
2428 SAL_WARN_IF(
2429 arguments.hasElements(), "stoc", "unexpected singleton arguments");
2430 return cppu::acquire(Singleton::get(context).instance.get());
2433 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */