Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / stoc / source / inspect / introspection.cxx
blob551687c6f4ab4f5545adcc869dbaa6e208380444
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 <osl/thread.h>
33 #include <sal/log.hxx>
34 #include <cppuhelper/basemutex.hxx>
35 #include <cppuhelper/compbase.hxx>
36 #include <cppuhelper/queryinterface.hxx>
37 #include <cppuhelper/weak.hxx>
38 #include <cppuhelper/component.hxx>
39 #include <cppuhelper/factory.hxx>
40 #include <cppuhelper/implbase.hxx>
41 #include <cppuhelper/supportsservice.hxx>
42 #include <cppuhelper/typeprovider.hxx>
43 #include <comphelper/sequence.hxx>
44 #include <salhelper/simplereferenceobject.hxx>
46 #include <com/sun/star/uno/DeploymentException.hpp>
47 #include <com/sun/star/lang/NoSuchMethodException.hpp>
48 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
49 #include <com/sun/star/lang/XServiceInfo.hpp>
50 #include <com/sun/star/lang/XEventListener.hpp>
51 #include <com/sun/star/lang/XUnoTunnel.hpp>
52 #include <com/sun/star/reflection/XIdlReflection.hpp>
53 #include <com/sun/star/reflection/XIdlClass.hpp>
54 #include <com/sun/star/reflection/XIdlField2.hpp>
55 #include <com/sun/star/reflection/theCoreReflection.hpp>
56 #include <com/sun/star/beans/UnknownPropertyException.hpp>
57 #include <com/sun/star/beans/Property.hpp>
58 #include <com/sun/star/beans/XPropertySet.hpp>
59 #include <com/sun/star/beans/XFastPropertySet.hpp>
60 #include <com/sun/star/beans/XIntrospection.hpp>
61 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
62 #include <com/sun/star/beans/XMaterialHolder.hpp>
63 #include <com/sun/star/beans/XExactName.hpp>
64 #include <com/sun/star/beans/PropertyAttribute.hpp>
65 #include <com/sun/star/beans/PropertyConcept.hpp>
66 #include <com/sun/star/beans/MethodConcept.hpp>
67 #include <com/sun/star/container/XNameContainer.hpp>
68 #include <com/sun/star/container/XIndexContainer.hpp>
69 #include <com/sun/star/container/XEnumerationAccess.hpp>
71 #include <rtl/ref.hxx>
72 #include <rtl/ustrbuf.hxx>
73 #include <rtl/strbuf.hxx>
74 #include <unordered_map>
76 using namespace css::uno;
77 using namespace css::lang;
78 using namespace css::reflection;
79 using namespace css::container;
80 using namespace css::registry;
81 using namespace css::beans;
82 using namespace css::beans::PropertyAttribute;
83 using namespace css::beans::PropertyConcept;
84 using namespace css::beans::MethodConcept;
85 using namespace cppu;
86 using namespace osl;
88 namespace
91 typedef WeakImplHelper< XIntrospectionAccess, XMaterialHolder, XExactName,
92 XPropertySet, XFastPropertySet, XPropertySetInfo,
93 XNameContainer, XIndexContainer, XEnumerationAccess,
94 XIdlArray, XUnoTunnel > IntrospectionAccessHelper;
97 // Special value for Method-Concept, to be able to mark "normal" functions
98 #define MethodConcept_NORMAL_IMPL 0x80000000
101 // Method to assert, if a class is derived from another class
102 bool isDerivedFrom( const Reference<XIdlClass>& xToTestClass, const Reference<XIdlClass>& xDerivedFromClass )
104 Sequence< Reference<XIdlClass> > aClassesSeq = xToTestClass->getSuperclasses();
105 const Reference<XIdlClass>* pClassesArray = aClassesSeq.getConstArray();
107 sal_Int32 nSuperClassCount = aClassesSeq.getLength();
108 for ( sal_Int32 i = 0; i < nSuperClassCount; ++i )
110 const Reference<XIdlClass>& rxClass = pClassesArray[i];
112 if ( xDerivedFromClass->equals( rxClass ) ||
113 isDerivedFrom( rxClass, xDerivedFromClass )
115 return true;
118 return false;
122 // *** Classification of Properties (no enum, to be able to use Sequence) ***
123 // Properties from a PropertySet-Interface
124 #define MAP_PROPERTY_SET 0
125 // Properties from Fields
126 #define MAP_FIELD 1
127 // Properties that get described with get/set methods
128 #define MAP_GETSET 2
129 // Properties with only a set method
130 #define MAP_SETONLY 3
133 // Increments by which the size of sequences get adjusted
134 #define ARRAY_SIZE_STEP 20
137 //*** IntrospectionAccessStatic_Impl ***
139 // Equals to the old IntrospectionAccessImpl, forms now a static
140 // part of the new Instance-related ImplIntrospectionAccess
142 // Hashtable for the search of names
143 typedef std::unordered_map
145 OUString,
146 sal_Int32
148 IntrospectionNameMap;
151 // Hashtable to assign exact names to the Lower-Case
152 // converted names, for the support of XExactName
153 typedef std::unordered_map
155 OUString,
156 OUString
158 LowerToExactNameMap;
161 class ImplIntrospectionAccess;
162 class IntrospectionAccessStatic_Impl: public salhelper::SimpleReferenceObject
164 friend class Implementation;
165 friend class ImplIntrospectionAccess;
167 // Holding CoreReflection
168 Reference< XIdlReflection > mxCoreReflection;
170 // InterfaceSequences, to save additional information in a property
171 // for example the Field at MAP_FIELD, the get/set-Methods at MAP_GETSET, et cetera
172 std::vector< Reference<XInterface> > aInterfaceSeq1;
173 std::vector< Reference<XInterface> > aInterfaceSeq2;
175 // Hashtables for names
176 IntrospectionNameMap maPropertyNameMap;
177 IntrospectionNameMap maMethodNameMap;
178 LowerToExactNameMap maLowerToExactNameMap;
180 // Vector of all Properties, also for delivering from getProperties()
181 std::vector<Property> maAllPropertySeq;
183 // Mapping of properties to Access-Types
184 std::vector<sal_Int16> maMapTypeSeq;
186 // Classification of found methods
187 std::vector<sal_Int32> maPropertyConceptSeq;
189 // Number of Properties
190 sal_Int32 mnPropCount;
192 // Number of Properties, which are assigned to particular concepts
193 //sal_Int32 mnDangerousPropCount;
194 sal_Int32 mnPropertySetPropCount;
195 sal_Int32 mnAttributePropCount;
196 sal_Int32 mnMethodPropCount;
198 // Flags which indicate if various interfaces are present
199 bool mbFastPropSet;
200 bool mbElementAccess;
201 bool mbNameAccess;
202 bool mbNameReplace;
203 bool mbNameContainer;
204 bool mbIndexAccess;
205 bool mbIndexReplace;
206 bool mbIndexContainer;
207 bool mbEnumerationAccess;
208 bool mbIdlArray;
209 bool mbUnoTunnel;
211 // Original handles of FastPropertySets
212 std::unique_ptr<sal_Int32[]> mpOrgPropertyHandleArray;
214 // MethodSequence, that accepts all methods
215 std::vector< Reference<XIdlMethod> > maAllMethodSeq;
217 // Classification of found methods
218 std::vector<sal_Int32> maMethodConceptSeq;
220 // Number of methods
221 sal_Int32 mnMethCount;
223 // Sequence of Listener, that can be registered
224 std::vector< Type > maSupportedListenerSeq;
226 // Helper-methods for adjusting sizes of Sequences
227 void checkPropertyArraysSize( sal_Int32 iNextIndex );
228 static void checkInterfaceArraySize( std::vector< Reference<XInterface> >& rSeq, std::vector<Reference<XInterface>>& rInterfaceVec,
229 sal_Int32 iNextIndex );
231 public:
232 explicit IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ );
233 sal_Int32 getPropertyIndex( const OUString& aPropertyName ) const;
234 sal_Int32 getMethodIndex( const OUString& aMethodName ) const;
236 // Methods of XIntrospectionAccess (OLD, now only Impl)
237 void setPropertyValue(const Any& obj, const OUString& aPropertyName, const Any& aValue) const;
238 // void setPropertyValue(Any& obj, const OUString& aPropertyName, const Any& aValue) const;
239 Any getPropertyValue(const Any& obj, const OUString& aPropertyName) const;
240 void setPropertyValueByIndex(const Any& obj, sal_Int32 nIndex, const Any& aValue) const;
241 // void setPropertyValueByIndex(Any& obj, sal_Int32 nIndex, const Any& aValue) const;
242 Any getPropertyValueByIndex(const Any& obj, sal_Int32 nIndex) const;
244 const std::vector<Property>& getProperties() const { return maAllPropertySeq; }
245 const std::vector< Reference<XIdlMethod> >& getMethods() const { return maAllMethodSeq; }
246 const std::vector< Type >& getSupportedListeners() const { return maSupportedListenerSeq; }
247 const std::vector<sal_Int32>& getPropertyConcepts() const { return maPropertyConceptSeq; }
248 const std::vector<sal_Int32>& getMethodConcepts() const { return maMethodConceptSeq; }
252 // Ctor
253 IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ )
254 : mxCoreReflection( xCoreReflection_ )
256 aInterfaceSeq1.resize( ARRAY_SIZE_STEP );
257 aInterfaceSeq2.resize( ARRAY_SIZE_STEP );
259 // Property-Data
260 maAllPropertySeq.resize( ARRAY_SIZE_STEP );
261 maMapTypeSeq.resize( ARRAY_SIZE_STEP );
262 maPropertyConceptSeq.resize( ARRAY_SIZE_STEP );
264 mbFastPropSet = false;
265 mbElementAccess = false;
266 mbNameAccess = false;
267 mbNameReplace = false;
268 mbNameContainer = false;
269 mbIndexAccess = false;
270 mbIndexReplace = false;
271 mbIndexContainer = false;
272 mbEnumerationAccess = false;
273 mbIdlArray = false;
274 mbUnoTunnel = false;
276 mpOrgPropertyHandleArray = nullptr;
278 mnPropCount = 0;
279 //mnDangerousPropCount = 0;
280 mnPropertySetPropCount = 0;
281 mnAttributePropCount = 0;
282 mnMethodPropCount = 0;
284 // Method-Data
285 mnMethCount = 0;
288 sal_Int32 IntrospectionAccessStatic_Impl::getPropertyIndex( const OUString& aPropertyName ) const
290 IntrospectionAccessStatic_Impl* pThis = const_cast<IntrospectionAccessStatic_Impl*>(this);
291 IntrospectionNameMap::iterator aIt = pThis->maPropertyNameMap.find( aPropertyName );
292 if (aIt != pThis->maPropertyNameMap.end())
293 return aIt->second;
295 return -1;
298 sal_Int32 IntrospectionAccessStatic_Impl::getMethodIndex( const OUString& aMethodName ) const
300 IntrospectionAccessStatic_Impl* pThis = const_cast<IntrospectionAccessStatic_Impl*>(this);
301 IntrospectionNameMap::iterator aIt = pThis->maMethodNameMap.find( aMethodName );
302 if (aIt != pThis->maMethodNameMap.end())
304 return aIt->second;
307 // #95159 Check if full qualified name matches
308 sal_Int32 nSearchFrom = aMethodName.getLength();
309 while( true )
311 // Strategy: Search back until the first '_' is found
312 sal_Int32 nFound = aMethodName.lastIndexOf( '_', nSearchFrom );
313 if( nFound == -1 )
314 break;
316 OUString aPureMethodName = aMethodName.copy( nFound + 1 );
318 aIt = pThis->maMethodNameMap.find( aPureMethodName );
319 if (aIt != pThis->maMethodNameMap.end())
321 // Check if it can be a type?
322 // Problem: Does not work if package names contain _ ?!
323 OUString aStr = aMethodName.copy( 0, nFound );
324 OUString aTypeName = aStr.replace( '_', '.' );
325 Reference< XIdlClass > xClass = mxCoreReflection->forName( aTypeName );
326 if( xClass.is() )
328 // If this is a valid class it could be the right method
330 // Could be the right method, type has to be checked
331 const sal_Int32 iHashResult = aIt->second;
333 const Reference<XIdlMethod> xMethod = maAllMethodSeq[iHashResult];
335 Reference< XIdlClass > xMethClass = xMethod->getDeclaringClass();
336 if( xClass->equals( xMethClass ) )
338 return iHashResult;
340 else
342 // Could also be another method with the same name
343 // Iterate over all methods
344 size_t nLen = maAllMethodSeq.size();
345 for (size_t i = 0; i < nLen; ++i)
347 const Reference<XIdlMethod> xMethod2 = maAllMethodSeq[ i ];
348 if( xMethod2->getName() == aPureMethodName )
350 Reference< XIdlClass > xMethClass2 = xMethod2->getDeclaringClass();
352 if( xClass->equals( xMethClass2 ) )
354 return i;
362 nSearchFrom = nFound - 1;
363 if( nSearchFrom < 0 )
364 break;
366 return -1;
369 void IntrospectionAccessStatic_Impl::setPropertyValue( const Any& obj, const OUString& aPropertyName, const Any& aValue ) const
370 //void IntrospectionAccessStatic_Impl::setPropertyValue( Any& obj, const OUString& aPropertyName, const Any& aValue ) const
372 sal_Int32 i = getPropertyIndex( aPropertyName );
373 if( i == -1 )
374 throw UnknownPropertyException(aPropertyName);
375 setPropertyValueByIndex( obj, i, aValue );
378 void IntrospectionAccessStatic_Impl::setPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
379 //void IntrospectionAccessStatic_Impl::setPropertyValueByIndex( Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
381 // Is the passed object something that fits?
382 Reference<XInterface> xInterface;
383 if( !(obj >>= xInterface) )
385 TypeClass eObjType = obj.getValueType().getTypeClass();
386 if( nSequenceIndex >= mnPropCount)
387 throw IllegalArgumentException(
388 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), index > propertyCount, " +
389 OUString::number(nSequenceIndex) + " > " + OUString::number(mnPropCount),
390 Reference<XInterface>(), 0);
391 if( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION )
392 throw IllegalArgumentException(
393 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), expected struct or exception, got" +
394 obj.getValueType().getTypeName(), Reference<XInterface>(), 0);
397 // Test flags
398 if( (maAllPropertySeq[ nSequenceIndex ].Attributes & READONLY) != 0 )
400 throw UnknownPropertyException(
401 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), property at index " + OUString::number(nSequenceIndex) + " is readonly");
404 switch( maMapTypeSeq[ nSequenceIndex ] )
406 case MAP_PROPERTY_SET:
408 // Get Property
409 const Property& rProp = maAllPropertySeq[ nSequenceIndex ];
411 // Convert Interface-Parameter to the correct type
412 bool bUseCopy = false;
413 Any aRealValue;
415 if( auto valInterface = o3tl::tryAccess<
416 css::uno::Reference<css::uno::XInterface>>(aValue) )
418 Type aPropType = rProp.Type;
419 OUString aTypeName( aPropType.getTypeName() );
420 Reference< XIdlClass > xPropClass = mxCoreReflection->forName( aTypeName );
421 //Reference<XIdlClass> xPropClass = rProp.Type;
422 if( xPropClass.is() && xPropClass->getTypeClass() == TypeClass_INTERFACE )
424 if( valInterface->is() )
426 //Any queryInterface( const Type& rType );
427 aRealValue = (*valInterface)->queryInterface( aPropType );
428 if( aRealValue.hasValue() )
429 bUseCopy = true;
434 // Do we have a FastPropertySet and a valid Handle?
435 // CAUTION: At this point we exploit that the PropertySet
436 // gets queried at the beginning of the Introspection-Process.
437 sal_Int32 nOrgHandle;
438 if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
440 // Retrieve PropertySet-Interface
441 Reference<XFastPropertySet> xFastPropSet =
442 Reference<XFastPropertySet>::query( xInterface );
443 if( xFastPropSet.is() )
445 xFastPropSet->setFastPropertyValue( nOrgHandle, bUseCopy ? aRealValue : aValue );
447 else
449 // throw UnknownPropertyException
452 // else take the normal one
453 else
455 // Retrieve PropertySet-Interface
456 Reference<XPropertySet> xPropSet =
457 Reference<XPropertySet>::query( xInterface );
458 if( xPropSet.is() )
460 xPropSet->setPropertyValue( rProp.Name, bUseCopy ? aRealValue : aValue );
462 else
464 // throw UnknownPropertyException
468 break;
470 case MAP_FIELD:
472 Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
473 Reference<XIdlField2> xField2(xField, UNO_QUERY);
474 if( xField2.is() )
476 xField2->set( const_cast<Any&>(obj), aValue );
477 // IllegalArgumentException
478 // NullPointerException
479 } else
480 if( xField.is() )
482 xField->set( obj, aValue );
483 // IllegalArgumentException
484 // NullPointerException
486 else
488 // throw IllegalArgumentException();
491 break;
493 case MAP_GETSET:
494 case MAP_SETONLY:
496 // Fetch set method
497 Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq2[ nSequenceIndex ].get());
498 if( xMethod.is() )
500 Sequence<Any> args( 1 );
501 args.getArray()[0] = aValue;
502 xMethod->invoke( obj, args );
504 else
506 // throw IllegalArgumentException();
509 break;
513 Any IntrospectionAccessStatic_Impl::getPropertyValue( const Any& obj, const OUString& aPropertyName ) const
515 sal_Int32 i = getPropertyIndex( aPropertyName );
516 if( i != -1 )
517 return getPropertyValueByIndex( obj, i );
519 throw UnknownPropertyException(aPropertyName);
522 Any IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex) const
524 Any aRet;
526 // Is there anything suitable in the passed object?
527 Reference<XInterface> xInterface;
528 if( !(obj >>= xInterface) )
530 TypeClass eObjType = obj.getValueType().getTypeClass();
531 if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) )
533 // throw IllegalArgumentException();
534 return aRet;
538 switch( maMapTypeSeq[ nSequenceIndex ] )
540 case MAP_PROPERTY_SET:
542 // Acquire property
543 const Property& rProp = maAllPropertySeq[ nSequenceIndex ];
545 // Do we have a FastPropertySet and a valid handle?
546 // NOTE: At this point is exploited that the PropertySet
547 // is queried at the beginning of introspection process.
548 sal_Int32 nOrgHandle;
549 if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
551 // Fetch the PropertySet interface
552 Reference<XFastPropertySet> xFastPropSet =
553 Reference<XFastPropertySet>::query( xInterface );
554 if( xFastPropSet.is() )
556 aRet = xFastPropSet->getFastPropertyValue( nOrgHandle);
558 else
560 // throw UnknownPropertyException
561 return aRet;
564 // Otherwise use the normal one
565 else
567 // Fetch the PropertySet interface
568 Reference<XPropertySet> xPropSet =
569 Reference<XPropertySet>::query( xInterface );
570 if( xPropSet.is() )
572 aRet = xPropSet->getPropertyValue( rProp.Name );
574 else
576 // throw UnknownPropertyException
577 return aRet;
581 break;
583 case MAP_FIELD:
585 Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
586 if( xField.is() )
588 aRet = xField->get( obj );
589 // IllegalArgumentException
590 // NullPointerException
592 else
594 // throw IllegalArgumentException();
595 return aRet;
598 break;
600 case MAP_GETSET:
602 // Fetch get method
603 Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq1[ nSequenceIndex ].get());
604 if( xMethod.is() )
606 Sequence<Any> args;
607 aRet = xMethod->invoke( obj, args );
609 else
611 // throw IllegalArgumentException();
612 return aRet;
615 break;
617 case MAP_SETONLY:
618 // Get method does not exist
619 // throw WriteOnlyPropertyException();
620 return aRet;
622 return aRet;
626 // Helper method to adjust the size of the vectors
627 void IntrospectionAccessStatic_Impl::checkPropertyArraysSize( sal_Int32 iNextIndex )
629 sal_Int32 nLen = static_cast<sal_Int32>(maAllPropertySeq.size());
630 if( iNextIndex >= nLen )
632 maAllPropertySeq.resize( nLen + ARRAY_SIZE_STEP );
633 maMapTypeSeq.resize( nLen + ARRAY_SIZE_STEP );
634 maPropertyConceptSeq.resize( nLen + ARRAY_SIZE_STEP );
638 void IntrospectionAccessStatic_Impl::checkInterfaceArraySize( std::vector< Reference<XInterface> >& rSeq,
639 std::vector<Reference<XInterface>>& rInterfaceVec, sal_Int32 iNextIndex )
641 sal_Int32 nLen = rSeq.size();
642 if( iNextIndex >= nLen )
644 // Synchronize new size with ARRAY_SIZE_STEP
645 sal_Int32 nMissingSize = iNextIndex - nLen + 1;
646 sal_Int32 nSteps = nMissingSize / ARRAY_SIZE_STEP + 1;
647 sal_Int32 nNewSize = nLen + nSteps * ARRAY_SIZE_STEP;
649 rSeq.resize( nNewSize );
650 rInterfaceVec = rSeq;
655 //*** ImplIntrospectionAccess ***
658 // New Impl class as part of the introspection conversion to instance-bound
659 // Introspection with property access via XPropertySet. The old class
660 // ImplIntrospectionAccess lives on as IntrospectionAccessStatic_Impl
661 class ImplIntrospectionAccess : public IntrospectionAccessHelper
663 friend class Implementation;
665 // Object under examination
666 Any maInspectedObject;
668 // As interface
669 Reference<XInterface> mxIface;
671 // Static introspection data
672 rtl::Reference< IntrospectionAccessStatic_Impl > mpStaticImpl;
674 // Last Sequence that came with getProperties (optimization)
675 Sequence<Property> maLastPropertySeq;
676 sal_Int32 mnLastPropertyConcept;
678 // Last Sequence that came with getMethods (optimization)
679 Sequence<Reference<XIdlMethod> > maLastMethodSeq;
680 sal_Int32 mnLastMethodConcept;
682 // Guards the caching of queried interfaces
683 osl::Mutex m_aMutex;
685 // Original interfaces of the objects
686 Reference<XElementAccess> mxObjElementAccess;
687 Reference<XNameContainer> mxObjNameContainer;
688 Reference<XNameReplace> mxObjNameReplace;
689 Reference<XNameAccess> mxObjNameAccess;
690 Reference<XIndexContainer> mxObjIndexContainer;
691 Reference<XIndexReplace> mxObjIndexReplace;
692 Reference<XIndexAccess> mxObjIndexAccess;
693 Reference<XEnumerationAccess> mxObjEnumerationAccess;
694 Reference<XIdlArray> mxObjIdlArray;
696 Reference<XElementAccess> getXElementAccess();
697 Reference<XNameContainer> getXNameContainer();
698 Reference<XNameReplace> getXNameReplace();
699 Reference<XNameAccess> getXNameAccess();
700 Reference<XIndexContainer> getXIndexContainer();
701 Reference<XIndexReplace> getXIndexReplace();
702 Reference<XIndexAccess> getXIndexAccess();
703 Reference<XEnumerationAccess> getXEnumerationAccess();
704 Reference<XIdlArray> getXIdlArray();
706 void cacheXNameContainer();
707 void cacheXIndexContainer();
709 public:
710 ImplIntrospectionAccess( const Any& obj, rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ );
712 // Methods from XIntrospectionAccess
713 virtual sal_Int32 SAL_CALL getSuppliedMethodConcepts() override;
714 virtual sal_Int32 SAL_CALL getSuppliedPropertyConcepts() override;
715 virtual Property SAL_CALL getProperty(const OUString& Name, sal_Int32 PropertyConcepts) override;
716 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name, sal_Int32 PropertyConcepts) override;
717 virtual Sequence< Property > SAL_CALL getProperties(sal_Int32 PropertyConcepts) override;
718 virtual Reference<XIdlMethod> SAL_CALL getMethod(const OUString& Name, sal_Int32 MethodConcepts) override;
719 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name, sal_Int32 MethodConcepts) override;
720 virtual Sequence< Reference<XIdlMethod> > SAL_CALL getMethods(sal_Int32 MethodConcepts) override;
721 virtual Sequence< Type > SAL_CALL getSupportedListeners() override;
722 using OWeakObject::queryAdapter;
723 virtual Reference<XInterface> SAL_CALL queryAdapter( const Type& rType ) override;
725 // Methods from XMaterialHolder
726 virtual Any SAL_CALL getMaterial() override;
728 // Methods from XExactName
729 virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) override;
731 // Methods from XInterface
732 virtual Any SAL_CALL queryInterface( const Type& rType ) override;
733 virtual void SAL_CALL acquire() throw() override { OWeakObject::acquire(); }
734 virtual void SAL_CALL release() throw() override { OWeakObject::release(); }
736 // Methods from XPropertySet
737 virtual Reference<XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
738 virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, const Any& aValue) override;
739 virtual Any SAL_CALL getPropertyValue(const OUString& aPropertyName) override;
740 virtual void SAL_CALL addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) override;
741 virtual void SAL_CALL removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) override;
742 virtual void SAL_CALL addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) override;
743 virtual void SAL_CALL removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) override;
745 // Methods from XFastPropertySet
746 virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const Any& aValue) override;
747 virtual Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override;
749 // Methods from XPropertySetInfo
750 virtual Sequence< Property > SAL_CALL getProperties() override;
751 virtual Property SAL_CALL getPropertyByName(const OUString& Name) override;
752 virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& Name) override;
754 // Methods from XElementAccess
755 virtual Type SAL_CALL getElementType() override;
756 virtual sal_Bool SAL_CALL hasElements() override;
758 // Methods from XNameAccess
759 virtual Any SAL_CALL getByName(const OUString& Name) override;
760 virtual Sequence< OUString > SAL_CALL getElementNames() override;
761 virtual sal_Bool SAL_CALL hasByName(const OUString& Name) override;
763 // Methods from XNameReplace
764 virtual void SAL_CALL replaceByName(const OUString& Name, const Any& Element) override;
766 // Methods from XNameContainer
767 virtual void SAL_CALL insertByName(const OUString& Name, const Any& Element) override;
768 virtual void SAL_CALL removeByName(const OUString& Name) override;
770 // Methods from XIndexAccess
771 virtual sal_Int32 SAL_CALL getCount() override;
772 virtual Any SAL_CALL getByIndex(sal_Int32 Index) override;
774 // Methods from XIndexReplace
775 virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element) override;
777 // Methods from XIndexContainer
778 virtual void SAL_CALL insertByIndex(sal_Int32 Index, const Any& Element) override;
779 virtual void SAL_CALL removeByIndex(sal_Int32 Index) override;
781 // Methods from XEnumerationAccess
782 virtual Reference<XEnumeration> SAL_CALL createEnumeration() override;
784 // Methods from XIdlArray
785 virtual void SAL_CALL realloc(Any& array, sal_Int32 length) override;
786 virtual sal_Int32 SAL_CALL getLen(const Any& array) override;
787 virtual Any SAL_CALL get(const Any& array, sal_Int32 index) override;
788 virtual void SAL_CALL set(Any& array, sal_Int32 index, const Any& value) override;
790 // Methods from XUnoTunnel
791 virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier ) override;
794 ImplIntrospectionAccess::ImplIntrospectionAccess
795 ( const Any& obj, rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ )
796 : maInspectedObject( obj ), mpStaticImpl( pStaticImpl_ ) //, maAdapter()
798 // Save object as an interface if possible
799 maInspectedObject >>= mxIface;
801 mnLastPropertyConcept = -1;
802 mnLastMethodConcept = -1;
805 Reference<XElementAccess> ImplIntrospectionAccess::getXElementAccess()
807 ResettableGuard< Mutex > aGuard( m_aMutex );
809 if( !mxObjElementAccess.is() )
811 aGuard.clear();
812 Reference<XElementAccess> xElementAccess( mxIface, UNO_QUERY );
813 aGuard.reset();
814 if( !mxObjElementAccess.is() )
815 mxObjElementAccess = xElementAccess;
817 return mxObjElementAccess;
820 void ImplIntrospectionAccess::cacheXNameContainer()
822 Reference<XNameContainer> xNameContainer;
823 Reference<XNameReplace> xNameReplace;
824 Reference<XNameAccess> xNameAccess;
825 if (mpStaticImpl->mbNameContainer)
827 xNameContainer.set( mxIface, UNO_QUERY );
828 xNameReplace.set( xNameContainer, UNO_QUERY );
829 xNameAccess.set( xNameContainer, UNO_QUERY );
831 else if (mpStaticImpl->mbNameReplace)
833 xNameReplace.set( mxIface, UNO_QUERY );
834 xNameAccess.set( xNameReplace, UNO_QUERY );
836 else if (mpStaticImpl->mbNameAccess)
838 xNameAccess.set( mxIface, UNO_QUERY );
842 MutexGuard aGuard( m_aMutex );
843 if( !mxObjNameContainer.is() )
844 mxObjNameContainer = xNameContainer;
845 if( !mxObjNameReplace.is() )
846 mxObjNameReplace = xNameReplace;
847 if( !mxObjNameAccess.is() )
848 mxObjNameAccess = xNameAccess;
852 Reference<XNameContainer> ImplIntrospectionAccess::getXNameContainer()
854 ClearableGuard< Mutex > aGuard( m_aMutex );
856 if( !mxObjNameContainer.is() )
858 aGuard.clear();
859 cacheXNameContainer();
861 return mxObjNameContainer;
864 Reference<XNameReplace> ImplIntrospectionAccess::getXNameReplace()
866 ClearableGuard< Mutex > aGuard( m_aMutex );
868 if( !mxObjNameReplace.is() )
870 aGuard.clear();
871 cacheXNameContainer();
873 return mxObjNameReplace;
876 Reference<XNameAccess> ImplIntrospectionAccess::getXNameAccess()
878 ClearableGuard< Mutex > aGuard( m_aMutex );
880 if( !mxObjNameAccess.is() )
882 aGuard.clear();
883 cacheXNameContainer();
885 return mxObjNameAccess;
888 void ImplIntrospectionAccess::cacheXIndexContainer()
890 Reference<XIndexContainer> xIndexContainer;
891 Reference<XIndexReplace> xIndexReplace;
892 Reference<XIndexAccess> xIndexAccess;
893 if (mpStaticImpl->mbIndexContainer)
895 xIndexContainer.set( mxIface, UNO_QUERY );
896 xIndexReplace.set( xIndexContainer, UNO_QUERY );
897 xIndexAccess.set( xIndexContainer, UNO_QUERY );
899 else if (mpStaticImpl->mbIndexReplace)
901 xIndexReplace.set( mxIface, UNO_QUERY );
902 xIndexAccess.set( xIndexReplace, UNO_QUERY );
904 else if (mpStaticImpl->mbIndexAccess)
906 xIndexAccess.set( mxIface, UNO_QUERY );
910 MutexGuard aGuard( m_aMutex );
911 if( !mxObjIndexContainer.is() )
912 mxObjIndexContainer = xIndexContainer;
913 if( !mxObjIndexReplace.is() )
914 mxObjIndexReplace = xIndexReplace;
915 if( !mxObjIndexAccess.is() )
916 mxObjIndexAccess = xIndexAccess;
920 Reference<XIndexContainer> ImplIntrospectionAccess::getXIndexContainer()
922 ClearableGuard< Mutex > aGuard( m_aMutex );
924 if( !mxObjIndexContainer.is() )
926 aGuard.clear();
927 cacheXIndexContainer();
929 return mxObjIndexContainer;
932 Reference<XIndexReplace> ImplIntrospectionAccess::getXIndexReplace()
934 ClearableGuard< Mutex > aGuard( m_aMutex );
936 if( !mxObjIndexReplace.is() )
938 aGuard.clear();
939 cacheXIndexContainer();
941 return mxObjIndexReplace;
944 Reference<XIndexAccess> ImplIntrospectionAccess::getXIndexAccess()
946 ClearableGuard< Mutex > aGuard( m_aMutex );
948 if( !mxObjIndexAccess.is() )
950 aGuard.clear();
951 cacheXIndexContainer();
953 return mxObjIndexAccess;
956 Reference<XEnumerationAccess> ImplIntrospectionAccess::getXEnumerationAccess()
958 ResettableGuard< Mutex > aGuard( m_aMutex );
960 if( !mxObjEnumerationAccess.is() )
962 aGuard.clear();
963 Reference<XEnumerationAccess> xEnumerationAccess( mxIface, UNO_QUERY );
964 aGuard.reset();
965 if( !mxObjEnumerationAccess.is() )
966 mxObjEnumerationAccess = xEnumerationAccess;
968 return mxObjEnumerationAccess;
971 Reference<XIdlArray> ImplIntrospectionAccess::getXIdlArray()
973 ResettableGuard< Mutex > aGuard( m_aMutex );
975 if( !mxObjIdlArray.is() )
977 aGuard.clear();
978 Reference<XIdlArray> xIdlArray( mxIface, UNO_QUERY );
979 aGuard.reset();
980 if( !mxObjIdlArray.is() )
981 mxObjIdlArray = xIdlArray;
983 return mxObjIdlArray;
986 // Methods from XInterface
987 Any SAL_CALL ImplIntrospectionAccess::queryInterface( const Type& rType )
989 Any aRet( ::cppu::queryInterface(
990 rType,
991 static_cast< XIntrospectionAccess * >( this ),
992 static_cast< XMaterialHolder * >( this ),
993 static_cast< XExactName * >( this ),
994 static_cast< XPropertySet * >( this ),
995 static_cast< XFastPropertySet * >( this ),
996 static_cast< XPropertySetInfo * >( this ) ) );
997 if( !aRet.hasValue() )
998 aRet = OWeakObject::queryInterface( rType );
1000 if( !aRet.hasValue() )
1002 // Wrapper for the object interfaces
1003 ( mpStaticImpl->mbElementAccess && (aRet = ::cppu::queryInterface
1004 ( rType, static_cast< XElementAccess* >( static_cast< XNameAccess* >( this ) ) ) ).hasValue() )
1005 || ( mpStaticImpl->mbNameAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() )
1006 || ( mpStaticImpl->mbNameReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XNameReplace* >( this ) ) ).hasValue() )
1007 || ( mpStaticImpl->mbNameContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() )
1008 || ( mpStaticImpl->mbIndexAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() )
1009 || ( mpStaticImpl->mbIndexReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexReplace* >( this ) ) ).hasValue() )
1010 || ( mpStaticImpl->mbIndexContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() )
1011 || ( mpStaticImpl->mbEnumerationAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() )
1012 || ( mpStaticImpl->mbIdlArray && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() )
1013 || ( mpStaticImpl->mbUnoTunnel && (aRet = ::cppu::queryInterface( rType, static_cast< XUnoTunnel* >( this ) ) ).hasValue() );
1015 return aRet;
1019 //*** Implementation of ImplIntrospectionAdapter ***
1022 // Methods from XPropertySet
1023 Reference<XPropertySetInfo> ImplIntrospectionAccess::getPropertySetInfo()
1025 return static_cast<XPropertySetInfo *>(this);
1028 void ImplIntrospectionAccess::setPropertyValue(const OUString& aPropertyName, const Any& aValue)
1030 mpStaticImpl->setPropertyValue( maInspectedObject, aPropertyName, aValue );
1033 Any ImplIntrospectionAccess::getPropertyValue(const OUString& aPropertyName)
1035 return mpStaticImpl->getPropertyValue( maInspectedObject, aPropertyName );
1038 void ImplIntrospectionAccess::addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
1040 if( mxIface.is() )
1042 Reference<XPropertySet> xPropSet =
1043 Reference<XPropertySet>::query( mxIface );
1044 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1045 if( xPropSet.is() )
1046 xPropSet->addPropertyChangeListener(aPropertyName, aListener);
1050 void ImplIntrospectionAccess::removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
1052 if( mxIface.is() )
1054 Reference<XPropertySet> xPropSet =
1055 Reference<XPropertySet>::query( mxIface );
1056 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1057 if( xPropSet.is() )
1058 xPropSet->removePropertyChangeListener(aPropertyName, aListener);
1062 void ImplIntrospectionAccess::addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1064 if( mxIface.is() )
1066 Reference<XPropertySet> xPropSet =
1067 Reference<XPropertySet>::query( mxIface );
1068 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1069 if( xPropSet.is() )
1070 xPropSet->addVetoableChangeListener(aPropertyName, aListener);
1074 void ImplIntrospectionAccess::removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1076 if( mxIface.is() )
1078 Reference<XPropertySet> xPropSet =
1079 Reference<XPropertySet>::query( mxIface );
1080 if( xPropSet.is() )
1081 xPropSet->removeVetoableChangeListener(aPropertyName, aListener);
1086 // Methods from XFastPropertySet
1087 void ImplIntrospectionAccess::setFastPropertyValue(sal_Int32, const Any&)
1091 Any ImplIntrospectionAccess::getFastPropertyValue(sal_Int32)
1093 return Any();
1096 // Methods from XPropertySetInfo
1097 Sequence< Property > ImplIntrospectionAccess::getProperties()
1099 return comphelper::containerToSequence(mpStaticImpl->getProperties());
1102 Property ImplIntrospectionAccess::getPropertyByName(const OUString& Name)
1104 return getProperty( Name, PropertyConcept::ALL );
1107 sal_Bool ImplIntrospectionAccess::hasPropertyByName(const OUString& Name)
1109 return hasProperty( Name, PropertyConcept::ALL );
1112 // Methods from XElementAccess
1113 Type ImplIntrospectionAccess::getElementType()
1115 return getXElementAccess()->getElementType();
1118 sal_Bool ImplIntrospectionAccess::hasElements()
1120 return getXElementAccess()->hasElements();
1123 // Methods from XNameAccess
1124 Any ImplIntrospectionAccess::getByName(const OUString& Name)
1126 return getXNameAccess()->getByName( Name );
1129 Sequence< OUString > ImplIntrospectionAccess::getElementNames()
1131 return getXNameAccess()->getElementNames();
1134 sal_Bool ImplIntrospectionAccess::hasByName(const OUString& Name)
1136 return getXNameAccess()->hasByName( Name );
1139 // Methods from XNameContainer
1140 void ImplIntrospectionAccess::insertByName(const OUString& Name, const Any& Element)
1142 getXNameContainer()->insertByName( Name, Element );
1145 void ImplIntrospectionAccess::replaceByName(const OUString& Name, const Any& Element)
1147 getXNameReplace()->replaceByName( Name, Element );
1150 void ImplIntrospectionAccess::removeByName(const OUString& Name)
1152 getXNameContainer()->removeByName( Name );
1155 // Methods from XIndexAccess
1156 // Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const
1157 sal_Int32 ImplIntrospectionAccess::getCount()
1159 return getXIndexAccess()->getCount();
1162 Any ImplIntrospectionAccess::getByIndex(sal_Int32 Index)
1164 return getXIndexAccess()->getByIndex( Index );
1167 // Methods from XIndexContainer
1168 void ImplIntrospectionAccess::insertByIndex(sal_Int32 Index, const Any& Element)
1170 getXIndexContainer()->insertByIndex( Index, Element );
1173 void ImplIntrospectionAccess::replaceByIndex(sal_Int32 Index, const Any& Element)
1175 getXIndexReplace()->replaceByIndex( Index, Element );
1178 void ImplIntrospectionAccess::removeByIndex(sal_Int32 Index)
1180 getXIndexContainer()->removeByIndex( Index );
1183 // Methods from XEnumerationAccess
1184 // Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const;
1185 Reference<XEnumeration> ImplIntrospectionAccess::createEnumeration()
1187 return getXEnumerationAccess()->createEnumeration();
1190 // Methods from XIdlArray
1191 void ImplIntrospectionAccess::realloc(Any& array, sal_Int32 length)
1193 getXIdlArray()->realloc( array, length );
1196 sal_Int32 ImplIntrospectionAccess::getLen(const Any& array)
1198 return getXIdlArray()->getLen( array );
1201 Any ImplIntrospectionAccess::get(const Any& array, sal_Int32 index)
1203 return getXIdlArray()->get( array, index );
1206 void ImplIntrospectionAccess::set(Any& array, sal_Int32 index, const Any& value)
1208 getXIdlArray()->set( array, index, value );
1211 // Methods from XUnoTunnel
1212 sal_Int64 ImplIntrospectionAccess::getSomething( const Sequence< sal_Int8 >& aIdentifier )
1214 return Reference<XUnoTunnel>::query( mxIface )->getSomething( aIdentifier );
1218 //*** Implementation of ImplIntrospectionAccess ***
1220 // Methods from XIntrospectionAccess
1221 sal_Int32 ImplIntrospectionAccess::getSuppliedMethodConcepts()
1223 return MethodConcept::DANGEROUS |
1224 PROPERTY |
1225 LISTENER |
1226 ENUMERATION |
1227 NAMECONTAINER |
1228 INDEXCONTAINER;
1231 sal_Int32 ImplIntrospectionAccess::getSuppliedPropertyConcepts()
1233 return PropertyConcept::DANGEROUS |
1234 PROPERTYSET |
1235 ATTRIBUTES |
1236 METHODS;
1239 Property ImplIntrospectionAccess::getProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1241 Property aRet;
1242 sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1243 bool bFound = false;
1244 if( i != -1 )
1246 sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1247 if( (PropertyConcepts & nConcept) != 0 )
1249 aRet = mpStaticImpl->getProperties()[ i ];
1250 bFound = true;
1253 if( !bFound )
1254 throw NoSuchElementException(Name);
1255 return aRet;
1258 sal_Bool ImplIntrospectionAccess::hasProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1260 sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1261 bool bRet = false;
1262 if( i != -1 )
1264 sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1265 if( (PropertyConcepts & nConcept) != 0 )
1266 bRet = true;
1268 return bRet;
1271 Sequence< Property > ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts)
1273 // If all supported concepts are required, simply pass through the sequence
1274 sal_Int32 nAllSupportedMask = PROPERTYSET |
1275 ATTRIBUTES |
1276 METHODS;
1277 if( ( PropertyConcepts & nAllSupportedMask ) == nAllSupportedMask )
1279 return comphelper::containerToSequence(mpStaticImpl->getProperties());
1282 // Same sequence as last time?
1283 if( mnLastPropertyConcept == PropertyConcepts )
1285 return maLastPropertySeq;
1288 // Number of properties to be delivered
1289 sal_Int32 nCount = 0;
1291 // There are currently no DANGEROUS properties
1292 // if( PropertyConcepts & DANGEROUS )
1293 // nCount += mpStaticImpl->mnDangerousPropCount;
1294 if( PropertyConcepts & PROPERTYSET )
1295 nCount += mpStaticImpl->mnPropertySetPropCount;
1296 if( PropertyConcepts & ATTRIBUTES )
1297 nCount += mpStaticImpl->mnAttributePropCount;
1298 if( PropertyConcepts & METHODS )
1299 nCount += mpStaticImpl->mnMethodPropCount;
1301 // Realloc sequence according to the required number
1302 maLastPropertySeq.realloc( nCount );
1303 Property* pDestProps = maLastPropertySeq.getArray();
1305 // Go through all the properties and apply according to the concept
1306 const std::vector<Property>& rPropSeq = mpStaticImpl->getProperties();
1307 const std::vector<sal_Int32>& rConcepts = mpStaticImpl->getPropertyConcepts();
1308 sal_Int32 nLen = static_cast<sal_Int32>(rPropSeq.size());
1310 sal_Int32 iDest = 0;
1311 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1313 sal_Int32 nConcept = rConcepts[ i ];
1314 if( nConcept & PropertyConcepts )
1315 pDestProps[ iDest++ ] = rPropSeq[ i ];
1318 // Remember PropertyConcept representing maLastPropertySeq
1319 mnLastPropertyConcept = PropertyConcepts;
1321 // Supply assembled Sequence
1322 return maLastPropertySeq;
1325 Reference<XIdlMethod> ImplIntrospectionAccess::getMethod(const OUString& Name, sal_Int32 MethodConcepts)
1327 Reference<XIdlMethod> xRet;
1328 sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1329 if( i != -1 )
1332 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1333 if( (MethodConcepts & nConcept) != 0 )
1335 xRet = mpStaticImpl->getMethods()[i];
1338 if( !xRet.is() )
1339 throw NoSuchMethodException(Name);
1340 return xRet;
1343 sal_Bool ImplIntrospectionAccess::hasMethod(const OUString& Name, sal_Int32 MethodConcepts)
1345 sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1346 bool bRet = false;
1347 if( i != -1 )
1349 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1350 if( (MethodConcepts & nConcept) != 0 )
1351 bRet = true;
1353 return bRet;
1356 Sequence< Reference<XIdlMethod> > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts)
1358 // If all supported concepts are required, simply pass through the sequence
1359 sal_Int32 nAllSupportedMask = MethodConcept::DANGEROUS |
1360 PROPERTY |
1361 LISTENER |
1362 ENUMERATION |
1363 NAMECONTAINER |
1364 INDEXCONTAINER |
1365 MethodConcept_NORMAL_IMPL;
1366 if( ( MethodConcepts & nAllSupportedMask ) == nAllSupportedMask )
1368 return comphelper::containerToSequence(mpStaticImpl->getMethods());
1371 // Same sequence as last time?
1372 if( mnLastMethodConcept == MethodConcepts )
1374 return maLastMethodSeq;
1377 // Get method sequences
1378 const std::vector< Reference<XIdlMethod> >& aMethodSeq = mpStaticImpl->getMethods();
1379 sal_Int32 nLen = static_cast<sal_Int32>(aMethodSeq.size());
1381 // Realloc sequence according to the required number
1382 // Unlike Properties, the number can not be determined by counters in
1383 // inspect() beforehand, since methods can belong to several concepts
1384 maLastMethodSeq.realloc( nLen );
1385 Reference<XIdlMethod>* pDestMethods = maLastMethodSeq.getArray();
1387 // Go through all the methods and apply according to the concept
1388 sal_Int32 iDest = 0;
1389 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1391 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1392 if( nConcept & MethodConcepts )
1393 pDestMethods[ iDest++ ] = aMethodSeq[ i ];
1396 // Bring to the correct length
1397 maLastMethodSeq.realloc( iDest );
1399 // Remember MethodConcept representing maLastMethodSeq
1400 mnLastMethodConcept = MethodConcepts;
1402 // Supply assembled Sequence
1403 return maLastMethodSeq;
1406 Sequence< Type > ImplIntrospectionAccess::getSupportedListeners()
1408 return comphelper::containerToSequence(mpStaticImpl->getSupportedListeners());
1411 Reference<XInterface> SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type& rType )
1413 Reference<XInterface> xRet;
1414 if( rType == cppu::UnoType<XInterface>::get()
1415 || rType == cppu::UnoType<XPropertySet>::get()
1416 || rType == cppu::UnoType<XFastPropertySet>::get()
1417 || rType == cppu::UnoType<XPropertySetInfo>::get()
1418 || rType == cppu::UnoType<XElementAccess>::get()
1419 || rType == cppu::UnoType<XNameAccess>::get()
1420 || rType == cppu::UnoType<XNameReplace>::get()
1421 || rType == cppu::UnoType<XNameContainer>::get()
1422 || rType == cppu::UnoType<XIndexAccess>::get()
1423 || rType == cppu::UnoType<XIndexReplace>::get()
1424 || rType == cppu::UnoType<XIndexContainer>::get()
1425 || rType == cppu::UnoType<XEnumerationAccess>::get()
1426 || rType == cppu::UnoType<XIdlArray>::get()
1427 || rType == cppu::UnoType<XUnoTunnel>::get() )
1429 queryInterface( rType ) >>= xRet;
1431 return xRet;
1434 // Methods from XMaterialHolder
1435 Any ImplIntrospectionAccess::getMaterial()
1437 return maInspectedObject;
1440 // Methods from XExactName
1441 OUString ImplIntrospectionAccess::getExactName( const OUString& rApproximateName )
1443 OUString aRetStr;
1444 LowerToExactNameMap::iterator aIt =
1445 mpStaticImpl->maLowerToExactNameMap.find( rApproximateName.toAsciiLowerCase() );
1446 if (aIt != mpStaticImpl->maLowerToExactNameMap.end())
1447 aRetStr = (*aIt).second;
1448 return aRetStr;
1451 struct TypeKey {
1452 TypeKey(
1453 css::uno::Reference<css::beans::XPropertySetInfo> const & theProperties,
1454 std::vector<css::uno::Type> const & theTypes):
1455 properties(theProperties)
1457 //TODO: Could even sort the types lexicographically first, to increase
1458 // the chance of matches between different implementations' getTypes(),
1459 // but the old scheme of using getImplementationId() would have missed
1460 // those matches, too:
1461 OUStringBuffer b;
1462 for (const css::uno::Type& rType : theTypes) {
1463 b.append(rType.getTypeName());
1464 b.append('*'); // arbitrary delimiter not used by type grammar
1466 types = b.makeStringAndClear();
1469 css::uno::Reference<css::beans::XPropertySetInfo> properties;
1470 OUString types;
1473 struct TypeKeyLess {
1474 bool operator ()(TypeKey const & key1, TypeKey const & key2) const {
1475 if (key1.properties.get() < key2.properties.get()) {
1476 return true;
1478 if (key1.properties.get() > key2.properties.get()) {
1479 return false;
1481 return key1.types < key2.types;
1485 template<typename Key, typename Less> class Cache {
1486 public:
1487 rtl::Reference<IntrospectionAccessStatic_Impl> find(Key const & key) const {
1488 typename Map::const_iterator i(map_.find(key));
1489 if (i == map_.end()) {
1490 return rtl::Reference<IntrospectionAccessStatic_Impl>();
1491 } else {
1492 if (i->second.hits < std::numeric_limits<unsigned>::max()) {
1493 ++i->second.hits;
1495 assert(i->second.access.is());
1496 return i->second.access;
1500 void insert(
1501 Key const & key,
1502 rtl::Reference<IntrospectionAccessStatic_Impl> const & access)
1504 assert(access.is());
1505 typename Map::size_type const MAX = 100;
1506 assert(map_.size() <= MAX);
1507 if (map_.size() == MAX) {
1508 typename Map::iterator del(map_.begin());
1509 for (typename Map::iterator i(map_.begin()); i != map_.end(); ++i) {
1510 if (i->second.hits < del->second.hits) {
1511 del = i;
1514 map_.erase(del);
1516 bool ins = map_.emplace(key, Data(access)).second;
1517 assert(ins); (void)ins;
1520 void clear() { map_.clear(); }
1522 private:
1523 struct Data {
1524 explicit Data(
1525 rtl::Reference<IntrospectionAccessStatic_Impl> const & theAccess):
1526 access(theAccess), hits(1)
1529 rtl::Reference<IntrospectionAccessStatic_Impl> access;
1530 mutable unsigned hits;
1533 typedef std::map<Key, Data, Less> Map;
1535 Map map_;
1538 typedef
1539 cppu::WeakComponentImplHelper<
1540 css::lang::XServiceInfo, css::beans::XIntrospection>
1541 Implementation_Base;
1543 class Implementation: private cppu::BaseMutex, public Implementation_Base {
1544 public:
1545 explicit Implementation(
1546 css::uno::Reference<css::uno::XComponentContext> const & context):
1547 Implementation_Base(m_aMutex),
1548 reflection_(css::reflection::theCoreReflection::get(context))
1551 private:
1552 virtual void SAL_CALL disposing() override {
1553 osl::MutexGuard g(m_aMutex);
1554 reflection_.clear();
1555 typeCache_.clear();
1558 virtual OUString SAL_CALL getImplementationName() override
1559 { return OUString("com.sun.star.comp.stoc.Introspection"); }
1561 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
1562 { return cppu::supportsService(this, ServiceName); }
1564 virtual css::uno::Sequence<OUString> SAL_CALL
1565 getSupportedServiceNames() override
1567 Sequence<OUString> s { "com.sun.star.beans.Introspection" };
1568 return s;
1571 virtual css::uno::Reference<css::beans::XIntrospectionAccess> SAL_CALL
1572 inspect(css::uno::Any const & aObject) override;
1574 css::uno::Reference<css::reflection::XIdlReflection> reflection_;
1575 Cache<TypeKey, TypeKeyLess> typeCache_;
1578 css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
1579 css::uno::Any const & aObject)
1581 css::uno::Reference<css::reflection::XIdlReflection> reflection;
1583 osl::MutexGuard g(m_aMutex);
1584 if (rBHelper.bDisposed || rBHelper.bInDispose) {
1585 throw css::lang::DisposedException(
1586 getImplementationName(), static_cast<OWeakObject *>(this));
1588 reflection = reflection_;
1590 css::uno::Any aToInspectObj;
1591 css::uno::Type t;
1592 if (aObject >>= t) {
1593 css::uno::Reference<css::reflection::XIdlClass> c(
1594 reflection->forName(t.getTypeName()));
1595 if (!c.is()) {
1596 SAL_WARN("stoc", "cannot reflect type " << t.getTypeName());
1597 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1599 aToInspectObj <<= c;
1600 } else {
1601 aToInspectObj = aObject;
1604 // Examine object
1605 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1606 if( eType != TypeClass_INTERFACE && eType != TypeClass_STRUCT && eType != TypeClass_EXCEPTION )
1607 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1609 if( auto x = o3tl::tryAccess<Reference<XInterface>>(aToInspectObj) )
1611 if( !x->is() )
1612 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1615 // Pointer to possibly needed new IntrospectionAccessStatic_Impl instance
1616 rtl::Reference< IntrospectionAccessStatic_Impl > pAccess;
1618 // Check: Is a matching access object already cached?
1619 std::vector< Reference<XIdlClass> > SupportedClassSeq;
1620 std::vector< Type > SupportedTypesSeq;
1621 Reference<XTypeProvider> xTypeProvider;
1622 Reference<XPropertySetInfo> xPropSetInfo;
1623 Reference<XPropertySet> xPropSet;
1625 // Look for interfaces XTypeProvider and PropertySet
1626 if( eType == TypeClass_INTERFACE )
1628 xTypeProvider.set( aToInspectObj, UNO_QUERY );
1629 if( xTypeProvider.is() )
1631 SupportedTypesSeq = comphelper::sequenceToContainer<std::vector<Type>>(xTypeProvider->getTypes());
1632 } else {
1633 SAL_WARN(
1634 "stoc",
1635 "object of type \"" << aToInspectObj.getValueTypeName()
1636 << "\" lacks XTypeProvider");
1637 SupportedTypesSeq = { aToInspectObj.getValueType() };
1639 // Now try to get the PropertySetInfo
1640 xPropSet.set( aToInspectObj, UNO_QUERY );
1641 if( xPropSet.is() )
1642 xPropSetInfo = xPropSet->getPropertySetInfo();
1644 } else {
1645 SupportedTypesSeq = { aToInspectObj.getValueType() };
1649 osl::MutexGuard g(m_aMutex);
1650 if (rBHelper.bDisposed || rBHelper.bInDispose) {
1651 throw css::lang::DisposedException(
1652 getImplementationName(), static_cast<OWeakObject *>(this));
1654 TypeKey key(xPropSetInfo, SupportedTypesSeq);
1655 pAccess = typeCache_.find(key);
1656 if (pAccess.is()) {
1657 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
1659 pAccess = new IntrospectionAccessStatic_Impl(reflection);
1660 typeCache_.insert(key, pAccess);
1663 // No access cached -> create new
1664 std::vector<Property>& rAllPropArray = pAccess->maAllPropertySeq;
1665 std::vector<Reference<XInterface>>& rInterfaces1 = pAccess->aInterfaceSeq1;
1666 std::vector<Reference<XInterface>>& rInterfaces2 = pAccess->aInterfaceSeq2;
1667 std::vector<sal_Int16>& rMapTypeArray = pAccess->maMapTypeSeq;
1668 std::vector<sal_Int32>& rPropertyConceptArray = pAccess->maPropertyConceptSeq;
1669 sal_Int32 i;
1671 // References to important data from pAccess
1672 sal_Int32& rPropCount = pAccess->mnPropCount;
1673 IntrospectionNameMap& rPropNameMap = pAccess->maPropertyNameMap;
1674 IntrospectionNameMap& rMethodNameMap = pAccess->maMethodNameMap;
1675 LowerToExactNameMap& rLowerToExactNameMap = pAccess->maLowerToExactNameMap;
1678 //*** Perform analysis ***
1680 if( eType == TypeClass_INTERFACE )
1682 size_t nTypeCount = SupportedTypesSeq.size();
1683 if( nTypeCount )
1685 SupportedClassSeq.resize( nTypeCount );
1687 for( i = 0 ; i < static_cast<sal_Int32>(nTypeCount) ; i++ )
1688 SupportedClassSeq[i] = reflection->forName( SupportedTypesSeq[i].getTypeName() );
1691 // First look for particular interfaces that are of particular
1692 // importance to the introspection
1694 // Is XPropertySet present?
1695 if( xPropSet.is() && xPropSetInfo.is() )
1697 // Is there also a FastPropertySet?
1698 Reference<XFastPropertySet> xDummy( aToInspectObj, UNO_QUERY );
1699 bool bFast = pAccess->mbFastPropSet = xDummy.is();
1701 Sequence<Property> aPropSeq = xPropSetInfo->getProperties();
1702 const Property* pProps = aPropSeq.getConstArray();
1703 sal_Int32 nLen = aPropSeq.getLength();
1705 // For a FastPropertySet we must remember the original handles
1706 if( bFast )
1707 pAccess->mpOrgPropertyHandleArray.reset( new sal_Int32[ nLen ] );
1709 for( i = 0 ; i < nLen ; i++ )
1711 // Put property in its own list
1712 pAccess->checkPropertyArraysSize( rPropCount );
1713 Property& rProp = rAllPropArray[ rPropCount ];
1714 rProp = pProps[ i ];
1716 if( bFast )
1717 pAccess->mpOrgPropertyHandleArray[ i ] = rProp.Handle;
1719 // Enter PropCount as a handle for its own FastPropertySet
1720 rProp.Handle = rPropCount;
1722 // Remember type of property
1723 rMapTypeArray[ rPropCount ] = MAP_PROPERTY_SET;
1724 rPropertyConceptArray[ rPropCount ] = PROPERTYSET;
1725 pAccess->mnPropertySetPropCount++;
1727 // Enter name in hash table if not already known
1728 OUString aPropName = rProp.Name;
1730 // Do we already have the name?
1731 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1732 if( aIt == rPropNameMap.end() )
1734 // New entry in the hash table
1735 rPropNameMap[ aPropName ] = rPropCount;
1737 // Maintain table for XExactName
1738 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1740 else
1742 SAL_WARN( "stoc", "Introspection: Property \"" <<
1743 aPropName << "\" found more than once in PropertySet" );
1746 // Adjust count
1747 rPropCount++;
1751 // Indices in the export table
1752 sal_Int32 iAllExportedMethod = 0;
1753 sal_Int32 iAllSupportedListener = 0;
1755 std::set<OUString> seen;
1757 // Flag, whether XInterface methods should be recorded
1758 // (this must be done only once, allowed initially)
1759 bool bXInterfaceIsInvalid = false;
1761 // Flag whether the XInterface methods have already been recorded. If
1762 // sal_True, bXInterfaceIsInvalid is activated at the end of the interface
1763 // loop, and XInterface methods are cut off thereafter.
1764 bool bFoundXInterface = false;
1766 size_t nClassCount = SupportedClassSeq.size();
1767 for( sal_Int32 nIdx = 0 ; nIdx < static_cast<sal_Int32>(nClassCount); nIdx++ )
1769 Reference<XIdlClass> xImplClass2 = SupportedClassSeq[nIdx];
1770 while( xImplClass2.is() )
1772 // Fetch interfaces from the implementation
1773 Sequence< Reference<XIdlClass> > aClassSeq = xImplClass2->getInterfaces();
1774 sal_Int32 nIfaceCount = aClassSeq.getLength();
1776 aClassSeq.realloc( nIfaceCount + 1 );
1777 aClassSeq.getArray()[ nIfaceCount ] = xImplClass2;
1778 nIfaceCount++;
1780 const Reference<XIdlClass>* pParamArray = aClassSeq.getConstArray();
1782 for( sal_Int32 j = 0 ; j < nIfaceCount ; j++ )
1784 const Reference<XIdlClass>& rxIfaceClass = pParamArray[j];
1785 if (!seen.insert(rxIfaceClass->getName()).second) {
1786 continue;
1789 // 2. Register fields as properties
1791 // Get fields
1792 Sequence< Reference<XIdlField> > fields = rxIfaceClass->getFields();
1793 const Reference<XIdlField>* pFields = fields.getConstArray();
1794 sal_Int32 nLen = fields.getLength();
1796 for( i = 0 ; i < nLen ; i++ )
1798 Reference<XIdlField> xField = pFields[i];
1799 Reference<XIdlClass> xPropType = xField->getType();
1801 // Is the property sequence big enough?
1802 pAccess->checkPropertyArraysSize( rPropCount );
1804 // Enter in own property array
1805 Property& rProp = rAllPropArray[ rPropCount ];
1806 OUString aFieldName = xField->getName();
1807 rProp.Name = aFieldName;
1808 rProp.Handle = rPropCount;
1809 Type aFieldType( xPropType->getTypeClass(), xPropType->getName() );
1810 rProp.Type = aFieldType;
1811 FieldAccessMode eAccessMode = xField->getAccessMode();
1812 rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
1813 eAccessMode == FieldAccessMode_CONST)
1814 ? READONLY : 0;
1816 // Enter name in hash table
1817 OUString aPropName = rProp.Name;
1819 // Do we have the name already?
1820 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1821 if (aIt != rPropNameMap.end())
1822 continue;
1824 // New entry in the hash table
1825 rPropNameMap[ aPropName ] = rPropCount;
1827 // Maintain table for XExactName
1828 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1830 // Remember field
1831 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
1832 rInterfaces1, rPropCount );
1833 rInterfaces1[ rPropCount ] = xField;
1835 // Remember type of property
1836 rMapTypeArray[ rPropCount ] = MAP_FIELD;
1837 rPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
1838 pAccess->mnAttributePropCount++;
1840 // Adjust count
1841 rPropCount++;
1845 // 3. Methods
1847 // Counter for found listeners
1848 sal_Int32 nListenerCount = 0;
1850 // Get and remember all methods
1851 Sequence< Reference<XIdlMethod> > methods = rxIfaceClass->getMethods();
1852 const Reference<XIdlMethod>* pSourceMethods = methods.getConstArray();
1853 sal_Int32 nSourceMethodCount = methods.getLength();
1855 // 3. a) Search get/set and listener methods
1857 // Create field for information about the methods, so that methods which are not
1858 // related to properties or listeners can easily be found later.
1859 // New: initialise MethodConceptArray
1860 enum MethodType
1862 STANDARD_METHOD, // normal method, not related to properties or listeners
1863 GETSET_METHOD, // belongs to a get/set property
1864 ADD_LISTENER_METHOD, // add method of a listener interface
1865 REMOVE_LISTENER_METHOD, // remove method of a listener interface
1866 INVALID_METHOD // method whose class is not considered, e.g. XPropertySet
1868 std::unique_ptr<MethodType[]> pMethodTypes( new MethodType[ nSourceMethodCount ] );
1869 std::unique_ptr<sal_Int32[]> pLocalMethodConcepts( new sal_Int32[ nSourceMethodCount ] );
1870 for( i = 0 ; i < nSourceMethodCount ; i++ )
1872 pMethodTypes[ i ] = STANDARD_METHOD;
1873 pLocalMethodConcepts[ i ] = 0;
1876 for( i = 0 ; i < nSourceMethodCount ; i++ )
1878 // Address method
1879 const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
1880 sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
1882 // Fetch name
1883 OUString aMethName = rxMethod_i->getName();
1885 // Catalogue methods
1886 // Filter all (?) methods of XInterface so e.g. acquire and release
1887 // can not be called from scripting
1888 rtl::OUString className(
1889 rxMethod_i->getDeclaringClass()->getName());
1890 if (className == "com.sun.star.uno.XInterface") {
1891 bFoundXInterface = true;
1893 if( bXInterfaceIsInvalid )
1895 pMethodTypes[ i ] = INVALID_METHOD;
1896 continue;
1898 else
1900 if( aMethName != "queryInterface" )
1902 rMethodConcept_i |= MethodConcept::DANGEROUS;
1903 continue;
1906 } else if (className == "com.sun.star.uno.XAggregation")
1908 if( aMethName == "setDelegator" )
1910 rMethodConcept_i |= MethodConcept::DANGEROUS;
1911 continue;
1913 } else if (className
1914 == "com.sun.star.container.XElementAccess")
1916 rMethodConcept_i |= ( NAMECONTAINER |
1917 INDEXCONTAINER |
1918 ENUMERATION );
1919 pAccess->mbElementAccess = true;
1920 } else if (className
1921 == "com.sun.star.container.XNameContainer")
1923 rMethodConcept_i |= NAMECONTAINER;
1924 pAccess->mbNameContainer = true;
1925 pAccess->mbNameReplace = true;
1926 pAccess->mbNameAccess = true;
1927 pAccess->mbElementAccess = true;
1928 } else if (className
1929 == "com.sun.star.container.XNameReplace")
1931 rMethodConcept_i |= NAMECONTAINER;
1932 pAccess->mbNameReplace = true;
1933 pAccess->mbNameAccess = true;
1934 pAccess->mbElementAccess = true;
1935 } else if (className
1936 == "com.sun.star.container.XNameAccess")
1938 rMethodConcept_i |= NAMECONTAINER;
1939 pAccess->mbNameAccess = true;
1940 pAccess->mbElementAccess = true;
1941 } else if (className
1942 == "com.sun.star.container.XIndexContainer")
1944 rMethodConcept_i |= INDEXCONTAINER;
1945 pAccess->mbIndexContainer = true;
1946 pAccess->mbIndexReplace = true;
1947 pAccess->mbIndexAccess = true;
1948 pAccess->mbElementAccess = true;
1949 } else if (className
1950 == "com.sun.star.container.XIndexReplace")
1952 rMethodConcept_i |= INDEXCONTAINER;
1953 pAccess->mbIndexReplace = true;
1954 pAccess->mbIndexAccess = true;
1955 pAccess->mbElementAccess = true;
1956 } else if (className
1957 == "com.sun.star.container.XIndexAccess")
1959 rMethodConcept_i |= INDEXCONTAINER;
1960 pAccess->mbIndexAccess = true;
1961 pAccess->mbElementAccess = true;
1962 } else if (className
1963 == "com.sun.star.container.XEnumerationAccess")
1965 rMethodConcept_i |= ENUMERATION;
1966 pAccess->mbEnumerationAccess = true;
1967 pAccess->mbElementAccess = true;
1968 } else if (className
1969 == "com.sun.star.reflection.XIdlArray")
1971 pAccess->mbIdlArray = true;
1972 } else if (className
1973 == "com.sun.star.lang.XUnoTunnel")
1975 pAccess->mbUnoTunnel = true;
1978 // If the name is too short, it isn't anything
1979 if( aMethName.getLength() <= 3 )
1980 continue;
1982 // Is it a get method?
1983 OUString aPropName;
1984 if( aMethName.startsWith("get", &aPropName) )
1986 // Get methods must not have any parameters
1987 Sequence< Reference<XIdlClass> > getParams = rxMethod_i->getParameterTypes();
1988 if( getParams.getLength() > 0 )
1990 continue;
1993 // Do we have the name already?
1994 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1995 if (aIt != rPropNameMap.end())
1997 /* TODO
1998 SAL_INFO("stoc",(
1999 String( "Introspection: Property \"" ) +
2000 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2001 String( "\" found more than once" ) );
2003 continue;
2006 // It is already at least a read-only property
2007 rMethodConcept_i |= PROPERTY;
2009 pMethodTypes[i] = GETSET_METHOD;
2010 Reference<XIdlClass> xGetRetType = rxMethod_i->getReturnType();
2012 // Is the property sequence big enough?
2013 pAccess->checkPropertyArraysSize( rPropCount );
2015 // Write it in its property array
2016 Property& rProp = rAllPropArray[ rPropCount ];
2017 rProp.Name = aPropName;
2018 rProp.Handle = rPropCount;
2019 rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
2020 rProp.Attributes = READONLY;
2022 // New entry in the hash table
2023 rPropNameMap[ aPropName ] = rPropCount;
2025 // Maintain table for XExactName
2026 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2028 // Remember get method
2029 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
2030 rInterfaces1, rPropCount );
2031 rInterfaces1[ rPropCount ] = rxMethod_i;
2033 // Remember type of property
2034 rMapTypeArray[ rPropCount ] = MAP_GETSET;
2035 rPropertyConceptArray[ rPropCount ] = METHODS;
2036 pAccess->mnMethodPropCount++;
2038 // Search for matching set method
2039 sal_Int32 k;
2040 for( k = 0 ; k < nSourceMethodCount ; k++ )
2042 // Address method
2043 const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k];
2045 // Accept only methods that are not already assigned
2046 if( k == i || pMethodTypes[k] != STANDARD_METHOD )
2047 continue;
2049 // Get name and evaluate
2050 OUString aMethName2 = rxMethod_k->getName();
2051 OUString aPropName2;
2052 if (!(aMethName2.startsWith("set", &aPropName2)
2053 && aPropName2 == aPropName))
2054 continue;
2056 // A set method must return void
2057 Reference<XIdlClass> xSetRetType = rxMethod_k->getReturnType();
2058 if( xSetRetType->getTypeClass() != TypeClass_VOID )
2060 continue;
2063 // A set method may only have one parameter
2064 Sequence< Reference<XIdlClass> > setParams = rxMethod_k->getParameterTypes();
2065 sal_Int32 nParamCount = setParams.getLength();
2066 if( nParamCount != 1 )
2068 continue;
2071 // Next, the return type must correspond to the parameter type
2072 const Reference<XIdlClass>* pParamArray2 = setParams.getConstArray();
2073 Reference<XIdlClass> xParamType = pParamArray2[ 0 ];
2074 if( xParamType->equals( xGetRetType ) )
2076 pLocalMethodConcepts[ k ] = PROPERTY;
2078 pMethodTypes[k] = GETSET_METHOD;
2080 // Delete read-only flag again
2081 rProp.Attributes &= ~READONLY;
2083 // Remember set method
2084 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2085 rInterfaces2, rPropCount );
2086 rInterfaces2[ rPropCount ] = rxMethod_k;
2090 // Adjust count
2091 rPropCount++;
2094 // Is it an add listener method?
2095 else if( aMethName.startsWith("add", &aPropName) )
2097 // Does it end with "Listener"?
2098 OUString aListenerName;
2099 if( !aPropName.endsWith("Listener", &aListenerName) )
2100 continue;
2102 // TODO: More accurate tests could still be carried out here
2103 // - Return type
2104 // - Number and type of parameters
2107 // Search for matching remove method, otherwise not applicable
2108 sal_Int32 k;
2109 for( k = 0 ; k < nSourceMethodCount ; k++ )
2111 // Address method
2112 const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k];
2114 // Accept only methods that are not already assigned
2115 if( k == i || pMethodTypes[k] != STANDARD_METHOD )
2116 continue;
2118 // Get name and evaluate
2119 OUString aMethName2 = rxMethod_k->getName();
2120 OUString aListenerName2;
2121 if (!(aMethName2.startsWith(
2122 "remove", &aPropName)
2123 && aPropName.endsWith(
2124 "Listener", &aListenerName2)
2125 && aListenerName2 == aListenerName))
2126 continue;
2128 // TODO: More accurate tests could still be carried out here
2129 // - Return type
2130 // - Number and type of parameters
2133 // Methods are recognised as a listener interface
2134 rMethodConcept_i |= LISTENER;
2135 pLocalMethodConcepts[ k ] |= LISTENER;
2137 pMethodTypes[i] = ADD_LISTENER_METHOD;
2138 pMethodTypes[k] = REMOVE_LISTENER_METHOD;
2139 nListenerCount++;
2145 // A set method could still exist without a corresponding get method,
2146 // this must be a write-only property
2147 for( i = 0 ; i < nSourceMethodCount ; i++ )
2149 // Address method
2150 const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
2152 // Accept only methods that are not already assigned
2153 if( pMethodTypes[i] != STANDARD_METHOD )
2154 continue;
2156 // Get name
2157 OUString aMethName = rxMethod_i->getName();
2159 // If the name is too short, it isn't anything
2160 if( aMethName.getLength() <= 3 )
2161 continue;
2163 // Is it a set method without associated get method?
2164 OUString aPropName;
2165 if( aMethName.startsWith("set", &aPropName) )
2167 // A set method must return void
2168 Reference<XIdlClass> xSetRetType = rxMethod_i->getReturnType();
2169 if( xSetRetType->getTypeClass() != TypeClass_VOID )
2171 continue;
2174 // A set method may only have one parameter
2175 Sequence< Reference<XIdlClass> > setParams = rxMethod_i->getParameterTypes();
2176 sal_Int32 nParamCount = setParams.getLength();
2177 if( nParamCount != 1 )
2179 continue;
2182 // Do we have the name already?
2183 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2184 if (aIt != rPropNameMap.end())
2186 /* TODO:
2187 SAL_INFO("stoc",(
2188 String( "Introspection: Property \"" ) +
2189 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2190 String( "\" found more than once" ) );
2192 continue;
2195 // Now we know it's a write only property
2196 pLocalMethodConcepts[ i ] = PROPERTY;
2198 pMethodTypes[i] = GETSET_METHOD;
2199 Reference<XIdlClass> xGetRetType = setParams.getConstArray()[0];
2201 // Is the property sequence big enough?
2202 pAccess->checkPropertyArraysSize( rPropCount );
2204 // Write it in its property array
2205 Property& rProp = rAllPropArray[ rPropCount ];
2206 rProp.Name = aPropName;
2207 rProp.Handle = rPropCount;
2208 rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
2209 rProp.Attributes = 0; // PROPERTY_WRITEONLY ???
2211 // New entry in the hash table
2212 rPropNameMap[ aPropName ] = rPropCount;
2214 // Maintain table for XExactName
2215 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2217 // Remember set method
2218 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2219 rInterfaces2, rPropCount );
2220 rInterfaces2[ rPropCount ] = rxMethod_i;
2222 // Remember type of property
2223 rMapTypeArray[ rPropCount ] = MAP_SETONLY;
2224 rPropertyConceptArray[ rPropCount ] = METHODS;
2225 pAccess->mnMethodPropCount++;
2227 // Adjust count
2228 rPropCount++;
2233 // 4. Place methods in overall sequence
2235 // How many methods in the method sequence
2236 sal_Int32 nExportedMethodCount = 0;
2237 sal_Int32 nSupportedListenerCount = 0;
2238 for( i = 0 ; i < nSourceMethodCount ; i++ )
2240 if( pMethodTypes[ i ] != INVALID_METHOD )
2242 nExportedMethodCount++;
2244 if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2246 nSupportedListenerCount++;
2250 // Enlarge sequences in the access object accordingly
2251 pAccess->maAllMethodSeq.resize( nExportedMethodCount + iAllExportedMethod );
2252 pAccess->maMethodConceptSeq.resize( nExportedMethodCount + iAllExportedMethod );
2253 pAccess->maSupportedListenerSeq.resize( nSupportedListenerCount + iAllSupportedListener );
2255 // Write in methods
2256 for( i = 0 ; i < nSourceMethodCount ; i++ )
2258 if( pMethodTypes[ i ] != INVALID_METHOD )
2260 // Address method
2261 const Reference<XIdlMethod>& rxMethod = pSourceMethods[i];
2263 // Enter name in hash table if not already known
2264 OUString aMethName2 = rxMethod->getName();
2265 IntrospectionNameMap::iterator aIt = rMethodNameMap.find( aMethName2 );
2266 if( aIt == rMethodNameMap.end() )
2268 // Enter
2269 rMethodNameMap[ aMethName2 ] = iAllExportedMethod;
2271 // Maintain table for XExactName
2272 rLowerToExactNameMap[ aMethName2.toAsciiLowerCase() ] = aMethName2;
2274 else
2276 sal_Int32 iHashResult = aIt->second;
2278 Reference<XIdlMethod> xExistingMethod = pAccess->maAllMethodSeq[iHashResult];
2280 Reference< XIdlClass > xExistingMethClass =
2281 xExistingMethod->getDeclaringClass();
2282 Reference< XIdlClass > xNewMethClass = rxMethod->getDeclaringClass();
2283 if( xExistingMethClass->equals( xNewMethClass ) )
2284 continue;
2287 pAccess->maAllMethodSeq[iAllExportedMethod] = rxMethod;
2289 // If a concept has been set, is the method "normal"?
2290 sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
2291 if( !rMethodConcept_i )
2292 rMethodConcept_i = MethodConcept_NORMAL_IMPL;
2293 pAccess->maMethodConceptSeq[ iAllExportedMethod ] = rMethodConcept_i;
2294 iAllExportedMethod++;
2296 if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2298 // Determine class of listener
2299 const Reference<XIdlMethod>& rxMethod = pSourceMethods[i];
2301 // Enter void as default class
2302 css::uno::Reference<css::reflection::XIdlClass>
2303 xListenerClass(
2304 reflection->forName(
2305 cppu::UnoType<void>::get()
2306 .getTypeName()));
2307 // Old: Reference<XIdlClass> xListenerClass = Void_getReflection()->getIdlClass();
2309 // Option 1: Search for parameters for a listener class
2310 // Disadvantage: Superclasses should be searched recursively
2311 Sequence< Reference<XIdlClass> > aParams = rxMethod->getParameterTypes();
2312 const Reference<XIdlClass>* pParamArray2 = aParams.getConstArray();
2314 css::uno::Reference<css::reflection::XIdlClass>
2315 xEventListenerClass(
2316 reflection->forName(
2317 cppu::UnoType<
2318 css::lang::XEventListener>::get()
2319 .getTypeName()));
2320 // Old: Reference<XIdlClass> xEventListenerClass = XEventListener_getReflection()->getIdlClass();
2321 sal_Int32 nParamCount = aParams.getLength();
2322 sal_Int32 k;
2323 for( k = 0 ; k < nParamCount ; k++ )
2325 const Reference<XIdlClass>& rxClass = pParamArray2[k];
2327 // Are we derived from a listener?
2328 if( rxClass->equals( xEventListenerClass ) ||
2329 isDerivedFrom( rxClass, xEventListenerClass ) )
2331 xListenerClass = rxClass;
2332 break;
2336 // Option 2: Unload the name of the method
2337 // Disadvantage: Does not work with test listeners, where it does not exist
2338 //aMethName = rxMethod->getName();
2339 //aListenerName = aMethName.Copy( 3, aMethName.Len()-8-3 );
2340 //Reference<XIdlClass> xListenerClass = reflection->forName( aListenerName );
2341 Type aListenerType( TypeClass_INTERFACE, xListenerClass->getName() );
2342 pAccess->maSupportedListenerSeq[ iAllSupportedListener ] = aListenerType;
2343 iAllSupportedListener++;
2347 // When there were XInterface methods in this run,
2348 // ignore them in the future
2349 if( bFoundXInterface )
2350 bXInterfaceIsInvalid = true;
2353 // Do superclasses exist? Then continue here
2354 Sequence< Reference<XIdlClass> > aSuperClassSeq = xImplClass2->getSuperclasses();
2356 // Currently only one superclass is considered
2357 if( aSuperClassSeq.getLength() >= 1 )
2359 xImplClass2 = aSuperClassSeq.getConstArray()[0];
2360 OSL_ENSURE( xImplClass2.is(), "super class null" );
2362 else
2364 xImplClass2 = nullptr;
2369 // Apply number of exported methods and adapt Sequences
2370 // (can be different because duplicate methods are thrown
2371 // out only after the determination of nExportedMethodCount)
2372 sal_Int32& rMethCount = pAccess->mnMethCount;
2373 rMethCount = iAllExportedMethod;
2374 pAccess->maAllMethodSeq.resize( rMethCount );
2375 pAccess->maMethodConceptSeq.resize( rMethCount );
2377 // Resize the property sequences
2378 pAccess->maAllPropertySeq.resize( rPropCount );
2379 pAccess->maPropertyConceptSeq.resize( rPropCount );
2380 pAccess->maMapTypeSeq.resize( rPropCount );
2382 // Register struct fields as properties
2383 else //if( eType == TypeClass_STRUCT )
2385 // Is it an interface or a struct?
2386 //Reference<XIdlClass> xClassRef = aToInspectObj.getReflection()->getIdlClass();
2387 css::uno::Reference<css::reflection::XIdlClass> xClassRef(
2388 reflection->forName(aToInspectObj.getValueTypeName()));
2389 if( !xClassRef.is() )
2391 SAL_WARN( "stoc", "Can't get XIdlClass from Reflection" );
2392 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
2395 // Get fields
2396 Sequence< Reference<XIdlField> > fields = xClassRef->getFields();
2397 const Reference<XIdlField>* pFields = fields.getConstArray();
2398 sal_Int32 nLen = fields.getLength();
2400 for( i = 0 ; i < nLen ; i++ )
2402 Reference<XIdlField> xField = pFields[i];
2403 Reference<XIdlClass> xPropType = xField->getType();
2404 OUString aPropName = xField->getName();
2406 // Is the property sequence big enough?
2407 pAccess->checkPropertyArraysSize( rPropCount );
2409 // Write it in its property array
2410 Property& rProp = rAllPropArray[ rPropCount ];
2411 rProp.Name = aPropName;
2412 rProp.Handle = rPropCount;
2413 rProp.Type = Type( xPropType->getTypeClass(), xPropType->getName() );
2414 FieldAccessMode eAccessMode = xField->getAccessMode();
2415 rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
2416 eAccessMode == FieldAccessMode_CONST)
2417 ? READONLY : 0;
2419 //FieldAccessMode eAccessMode = xField->getAccessMode();
2420 //rProp.Attributes = (eAccessMode == FieldAccessMode::READONLY || eAccessMode == CONST)
2421 //? PropertyAttribute::READONLY : 0;
2423 // Write name in hash table
2424 rPropNameMap[ aPropName ] = rPropCount;
2426 // Maintain table for XExactName
2427 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2429 // Remember field
2430 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
2431 rInterfaces1, rPropCount );
2432 rInterfaces1[ rPropCount ] = xField;
2434 // Remember type of property
2435 rMapTypeArray[ rPropCount ] = MAP_FIELD;
2436 rPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
2437 pAccess->mnAttributePropCount++;
2439 // Adjust count
2440 rPropCount++;
2444 // Set property sequence to the correct length
2445 pAccess->maAllPropertySeq.resize( pAccess->mnPropCount );
2447 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
2450 struct Instance {
2451 explicit Instance(
2452 css::uno::Reference<css::uno::XComponentContext> const & context):
2453 instance(new Implementation(context))
2456 rtl::Reference<cppu::OWeakObject> instance;
2459 struct Singleton:
2460 public rtl::StaticWithArg<
2461 Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
2466 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
2467 com_sun_star_comp_stoc_Introspection_get_implementation(
2468 css::uno::XComponentContext * context,
2469 css::uno::Sequence<css::uno::Any> const & arguments)
2471 SAL_WARN_IF(
2472 arguments.hasElements(), "stoc", "unexpected singleton arguments");
2473 return cppu::acquire(Singleton::get(context).instance.get());
2476 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */