Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / stoc / source / inspect / introspection.cxx
blob986e57fb4642bd3525beafbc77a13b968cf910ad
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,
147 OUStringHash
149 IntrospectionNameMap;
152 // Hashtable to assign exact names to the Lower-Case
153 // converted names, for the support of XExactName
154 typedef std::unordered_map
156 OUString,
157 OUString,
158 OUStringHash
160 LowerToExactNameMap;
163 class ImplIntrospectionAccess;
164 class IntrospectionAccessStatic_Impl: public salhelper::SimpleReferenceObject
166 friend class Implementation;
167 friend class ImplIntrospectionAccess;
169 // Holding CoreReflection
170 Reference< XIdlReflection > mxCoreReflection;
172 // InterfaceSequences, to save additional information in a property
173 // for example the Field at MAP_FIELD, the get/set-Methods at MAP_GETSET, et cetera
174 std::vector< Reference<XInterface> > aInterfaceSeq1;
175 std::vector< Reference<XInterface> > aInterfaceSeq2;
177 // Hashtables for names
178 IntrospectionNameMap maPropertyNameMap;
179 IntrospectionNameMap maMethodNameMap;
180 LowerToExactNameMap maLowerToExactNameMap;
182 // Vector of all Properties, also for delivering from getProperties()
183 std::vector<Property> maAllPropertySeq;
185 // Mapping of properties to Access-Types
186 std::vector<sal_Int16> maMapTypeSeq;
188 // Classification of found methods
189 std::vector<sal_Int32> maPropertyConceptSeq;
191 // Number of Properties
192 sal_Int32 mnPropCount;
194 // Number of Properties, which are assigned to particular concepts
195 //sal_Int32 mnDangerousPropCount;
196 sal_Int32 mnPropertySetPropCount;
197 sal_Int32 mnAttributePropCount;
198 sal_Int32 mnMethodPropCount;
200 // Flags which indicate if various interfaces are present
201 bool mbFastPropSet;
202 bool mbElementAccess;
203 bool mbNameAccess;
204 bool mbNameReplace;
205 bool mbNameContainer;
206 bool mbIndexAccess;
207 bool mbIndexReplace;
208 bool mbIndexContainer;
209 bool mbEnumerationAccess;
210 bool mbIdlArray;
211 bool mbUnoTunnel;
213 // Original handles of FastPropertySets
214 std::unique_ptr<sal_Int32[]> mpOrgPropertyHandleArray;
216 // MethodSequence, that accepts all methods
217 std::vector< Reference<XIdlMethod> > maAllMethodSeq;
219 // Classification of found methods
220 std::vector<sal_Int32> maMethodConceptSeq;
222 // Number of methods
223 sal_Int32 mnMethCount;
225 // Sequence of Listener, that can be registered
226 std::vector< Type > maSupportedListenerSeq;
228 // Helper-methods for adjusting sizes of Sequences
229 void checkPropertyArraysSize( sal_Int32 iNextIndex );
230 static void checkInterfaceArraySize( std::vector< Reference<XInterface> >& rSeq, std::vector<Reference<XInterface>>& rInterfaceVec,
231 sal_Int32 iNextIndex );
233 public:
234 explicit IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ );
235 sal_Int32 getPropertyIndex( const OUString& aPropertyName ) const;
236 sal_Int32 getMethodIndex( const OUString& aMethodName ) const;
238 // Methods of XIntrospectionAccess (OLD, now only Impl)
239 void setPropertyValue(const Any& obj, const OUString& aPropertyName, const Any& aValue) const;
240 // void setPropertyValue(Any& obj, const OUString& aPropertyName, const Any& aValue) const;
241 Any getPropertyValue(const Any& obj, const OUString& aPropertyName) const;
242 void setPropertyValueByIndex(const Any& obj, sal_Int32 nIndex, const Any& aValue) const;
243 // void setPropertyValueByIndex(Any& obj, sal_Int32 nIndex, const Any& aValue) const;
244 Any getPropertyValueByIndex(const Any& obj, sal_Int32 nIndex) const;
246 const std::vector<Property>& getProperties() const { return maAllPropertySeq; }
247 const std::vector< Reference<XIdlMethod> >& getMethods() const { return maAllMethodSeq; }
248 const std::vector< Type >& getSupportedListeners() const { return maSupportedListenerSeq; }
249 const std::vector<sal_Int32>& getPropertyConcepts() const { return maPropertyConceptSeq; }
250 const std::vector<sal_Int32>& getMethodConcepts() const { return maMethodConceptSeq; }
254 // Ctor
255 IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ )
256 : mxCoreReflection( xCoreReflection_ )
258 aInterfaceSeq1.resize( ARRAY_SIZE_STEP );
259 aInterfaceSeq2.resize( ARRAY_SIZE_STEP );
261 // Property-Data
262 maAllPropertySeq.resize( ARRAY_SIZE_STEP );
263 maMapTypeSeq.resize( ARRAY_SIZE_STEP );
264 maPropertyConceptSeq.resize( ARRAY_SIZE_STEP );
266 mbFastPropSet = false;
267 mbElementAccess = false;
268 mbNameAccess = false;
269 mbNameReplace = false;
270 mbNameContainer = false;
271 mbIndexAccess = false;
272 mbIndexReplace = false;
273 mbIndexContainer = false;
274 mbEnumerationAccess = false;
275 mbIdlArray = false;
276 mbUnoTunnel = false;
278 mpOrgPropertyHandleArray = nullptr;
280 mnPropCount = 0;
281 //mnDangerousPropCount = 0;
282 mnPropertySetPropCount = 0;
283 mnAttributePropCount = 0;
284 mnMethodPropCount = 0;
286 // Method-Data
287 mnMethCount = 0;
290 sal_Int32 IntrospectionAccessStatic_Impl::getPropertyIndex( const OUString& aPropertyName ) const
292 IntrospectionAccessStatic_Impl* pThis = const_cast<IntrospectionAccessStatic_Impl*>(this);
293 IntrospectionNameMap::iterator aIt = pThis->maPropertyNameMap.find( aPropertyName );
294 if (aIt != pThis->maPropertyNameMap.end())
295 return aIt->second;
297 return -1;
300 sal_Int32 IntrospectionAccessStatic_Impl::getMethodIndex( const OUString& aMethodName ) const
302 IntrospectionAccessStatic_Impl* pThis = const_cast<IntrospectionAccessStatic_Impl*>(this);
303 IntrospectionNameMap::iterator aIt = pThis->maMethodNameMap.find( aMethodName );
304 if (aIt != pThis->maMethodNameMap.end())
306 return aIt->second;
309 // #95159 Check if full qualified name matches
310 sal_Int32 nSearchFrom = aMethodName.getLength();
311 while( true )
313 // Strategy: Search back until the first '_' is found
314 sal_Int32 nFound = aMethodName.lastIndexOf( '_', nSearchFrom );
315 if( nFound == -1 )
316 break;
318 OUString aPureMethodName = aMethodName.copy( nFound + 1 );
320 aIt = pThis->maMethodNameMap.find( aPureMethodName );
321 if (aIt != pThis->maMethodNameMap.end())
323 // Check if it can be a type?
324 // Problem: Does not work if package names contain _ ?!
325 OUString aStr = aMethodName.copy( 0, nFound );
326 OUString aTypeName = aStr.replace( '_', '.' );
327 Reference< XIdlClass > xClass = mxCoreReflection->forName( aTypeName );
328 if( xClass.is() )
330 // If this is a valid class it could be the right method
332 // Could be the right method, type has to be checked
333 const sal_Int32 iHashResult = aIt->second;
335 const Reference<XIdlMethod> xMethod = maAllMethodSeq[iHashResult];
337 Reference< XIdlClass > xMethClass = xMethod->getDeclaringClass();
338 if( xClass->equals( xMethClass ) )
340 return iHashResult;
342 else
344 // Could also be another method with the same name
345 // Iterate over all methods
346 size_t nLen = maAllMethodSeq.size();
347 for (size_t i = 0; i < nLen; ++i)
349 const Reference<XIdlMethod> xMethod2 = maAllMethodSeq[ i ];
350 if( xMethod2->getName() == aPureMethodName )
352 Reference< XIdlClass > xMethClass2 = xMethod2->getDeclaringClass();
354 if( xClass->equals( xMethClass2 ) )
356 return i;
364 nSearchFrom = nFound - 1;
365 if( nSearchFrom < 0 )
366 break;
368 return -1;
371 void IntrospectionAccessStatic_Impl::setPropertyValue( const Any& obj, const OUString& aPropertyName, const Any& aValue ) const
372 //void IntrospectionAccessStatic_Impl::setPropertyValue( Any& obj, const OUString& aPropertyName, const Any& aValue ) const
374 sal_Int32 i = getPropertyIndex( aPropertyName );
375 if( i != -1 )
376 setPropertyValueByIndex( obj, i, aValue );
377 else
378 throw UnknownPropertyException(aPropertyName);
381 void IntrospectionAccessStatic_Impl::setPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
382 //void IntrospectionAccessStatic_Impl::setPropertyValueByIndex( Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
384 // Is the passed object something that fits?
385 Reference<XInterface> xInterface;
386 if( !(obj >>= xInterface) )
388 TypeClass eObjType = obj.getValueType().getTypeClass();
389 if( nSequenceIndex >= mnPropCount)
390 throw IllegalArgumentException(
391 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), index > propertyCount, " +
392 OUString::number(nSequenceIndex) + " > " + OUString::number(mnPropCount),
393 Reference<XInterface>(), 0);
394 if( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION )
395 throw IllegalArgumentException(
396 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), expected struct or exception, got" +
397 obj.getValueType().getTypeName(), Reference<XInterface>(), 0);
400 // Test flags
401 if( (maAllPropertySeq[ nSequenceIndex ].Attributes & READONLY) != 0 )
403 throw UnknownPropertyException(
404 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), property at index " + OUString::number(nSequenceIndex) + " is readonly");
407 switch( maMapTypeSeq[ nSequenceIndex ] )
409 case MAP_PROPERTY_SET:
411 // Get Property
412 const Property& rProp = maAllPropertySeq[ nSequenceIndex ];
414 // Convert Interface-Parameter to the correct type
415 bool bUseCopy = false;
416 Any aRealValue;
418 if( auto valInterface = o3tl::tryAccess<
419 css::uno::Reference<css::uno::XInterface>>(aValue) )
421 Type aPropType = rProp.Type;
422 OUString aTypeName( aPropType.getTypeName() );
423 Reference< XIdlClass > xPropClass = mxCoreReflection->forName( aTypeName );
424 //Reference<XIdlClass> xPropClass = rProp.Type;
425 if( xPropClass.is() && xPropClass->getTypeClass() == TypeClass_INTERFACE )
427 if( valInterface->is() )
429 //Any queryInterface( const Type& rType );
430 aRealValue = (*valInterface)->queryInterface( aPropType );
431 if( aRealValue.hasValue() )
432 bUseCopy = true;
437 // Do we have a FastPropertySet and a valid Handle?
438 // CAUTION: At this point we exploit that the PropertySet
439 // gets queried at the beginning of the Introspection-Process.
440 sal_Int32 nOrgHandle;
441 if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
443 // Retrieve PropertySet-Interface
444 Reference<XFastPropertySet> xFastPropSet =
445 Reference<XFastPropertySet>::query( xInterface );
446 if( xFastPropSet.is() )
448 xFastPropSet->setFastPropertyValue( nOrgHandle, bUseCopy ? aRealValue : aValue );
450 else
452 // throw UnknownPropertyException
455 // else take the normal one
456 else
458 // Retrieve PropertySet-Interface
459 Reference<XPropertySet> xPropSet =
460 Reference<XPropertySet>::query( xInterface );
461 if( xPropSet.is() )
463 xPropSet->setPropertyValue( rProp.Name, bUseCopy ? aRealValue : aValue );
465 else
467 // throw UnknownPropertyException
471 break;
473 case MAP_FIELD:
475 Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
476 Reference<XIdlField2> xField2(xField, UNO_QUERY);
477 if( xField2.is() )
479 xField2->set( (Any&)obj, aValue );
480 // IllegalArgumentException
481 // NullPointerException
482 } else
483 if( xField.is() )
485 xField->set( obj, aValue );
486 // IllegalArgumentException
487 // NullPointerException
489 else
491 // throw IllegalArgumentException();
494 break;
496 case MAP_GETSET:
497 case MAP_SETONLY:
499 // Fetch set method
500 Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq2[ nSequenceIndex ].get());
501 if( xMethod.is() )
503 Sequence<Any> args( 1 );
504 args.getArray()[0] = aValue;
505 xMethod->invoke( obj, args );
507 else
509 // throw IllegalArgumentException();
512 break;
516 Any IntrospectionAccessStatic_Impl::getPropertyValue( const Any& obj, const OUString& aPropertyName ) const
518 sal_Int32 i = getPropertyIndex( aPropertyName );
519 if( i != -1 )
520 return getPropertyValueByIndex( obj, i );
522 throw UnknownPropertyException(aPropertyName);
525 Any IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex) const
527 Any aRet;
529 // Is there anything suitable in the passed object?
530 Reference<XInterface> xInterface;
531 if( !(obj >>= xInterface) )
533 TypeClass eObjType = obj.getValueType().getTypeClass();
534 if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) )
536 // throw IllegalArgumentException();
537 return aRet;
541 switch( maMapTypeSeq[ nSequenceIndex ] )
543 case MAP_PROPERTY_SET:
545 // Acquire property
546 const Property& rProp = maAllPropertySeq[ nSequenceIndex ];
548 // Do we have a FastPropertySet and a valid handle?
549 // NOTE: At this point is exploited that the PropertySet
550 // is queried at the beginning of introspection process.
551 sal_Int32 nOrgHandle;
552 if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
554 // Fetch the PropertySet interface
555 Reference<XFastPropertySet> xFastPropSet =
556 Reference<XFastPropertySet>::query( xInterface );
557 if( xFastPropSet.is() )
559 aRet = xFastPropSet->getFastPropertyValue( nOrgHandle);
561 else
563 // throw UnknownPropertyException
564 return aRet;
567 // Otherwise use the normal one
568 else
570 // Fetch the PropertySet interface
571 Reference<XPropertySet> xPropSet =
572 Reference<XPropertySet>::query( xInterface );
573 if( xPropSet.is() )
575 aRet = xPropSet->getPropertyValue( rProp.Name );
577 else
579 // throw UnknownPropertyException
580 return aRet;
584 break;
586 case MAP_FIELD:
588 Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
589 if( xField.is() )
591 aRet = xField->get( obj );
592 // IllegalArgumentException
593 // NullPointerException
595 else
597 // throw IllegalArgumentException();
598 return aRet;
601 break;
603 case MAP_GETSET:
605 // Fetch get method
606 Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq1[ nSequenceIndex ].get());
607 if( xMethod.is() )
609 Sequence<Any> args;
610 aRet = xMethod->invoke( obj, args );
612 else
614 // throw IllegalArgumentException();
615 return aRet;
618 break;
620 case MAP_SETONLY:
621 // Get method does not exist
622 // throw WriteOnlyPropertyException();
623 return aRet;
625 return aRet;
629 // Helper method to adjust the size of the vectors
630 void IntrospectionAccessStatic_Impl::checkPropertyArraysSize( sal_Int32 iNextIndex )
632 sal_Int32 nLen = (sal_Int32)maAllPropertySeq.size();
633 if( iNextIndex >= nLen )
635 maAllPropertySeq.resize( nLen + ARRAY_SIZE_STEP );
636 maMapTypeSeq.resize( nLen + ARRAY_SIZE_STEP );
637 maPropertyConceptSeq.resize( nLen + ARRAY_SIZE_STEP );
641 void IntrospectionAccessStatic_Impl::checkInterfaceArraySize( std::vector< Reference<XInterface> >& rSeq,
642 std::vector<Reference<XInterface>>& rInterfaceVec, sal_Int32 iNextIndex )
644 sal_Int32 nLen = rSeq.size();
645 if( iNextIndex >= nLen )
647 // Synchronize new size with ARRAY_SIZE_STEP
648 sal_Int32 nMissingSize = iNextIndex - nLen + 1;
649 sal_Int32 nSteps = nMissingSize / ARRAY_SIZE_STEP + 1;
650 sal_Int32 nNewSize = nLen + nSteps * ARRAY_SIZE_STEP;
652 rSeq.resize( nNewSize );
653 rInterfaceVec = rSeq;
658 //*** ImplIntrospectionAccess ***
661 // New Impl class as part of the introspection conversion to instance-bound
662 // Introspection with property access via XPropertySet. The old class
663 // ImplIntrospectionAccess lives on as IntrospectionAccessStatic_Impl
664 class ImplIntrospectionAccess : public IntrospectionAccessHelper
666 friend class Implementation;
668 // Object under examination
669 Any maInspectedObject;
671 // As interface
672 Reference<XInterface> mxIface;
674 // Static introspection data
675 rtl::Reference< IntrospectionAccessStatic_Impl > mpStaticImpl;
677 // Last Sequence that came with getProperties (optimization)
678 Sequence<Property> maLastPropertySeq;
679 sal_Int32 mnLastPropertyConcept;
681 // Last Sequence that came with getMethods (optimization)
682 Sequence<Reference<XIdlMethod> > maLastMethodSeq;
683 sal_Int32 mnLastMethodConcept;
685 // Guards the caching of queried interfaces
686 osl::Mutex m_aMutex;
688 // Original interfaces of the objects
689 Reference<XElementAccess> mxObjElementAccess;
690 Reference<XNameContainer> mxObjNameContainer;
691 Reference<XNameReplace> mxObjNameReplace;
692 Reference<XNameAccess> mxObjNameAccess;
693 Reference<XIndexContainer> mxObjIndexContainer;
694 Reference<XIndexReplace> mxObjIndexReplace;
695 Reference<XIndexAccess> mxObjIndexAccess;
696 Reference<XEnumerationAccess> mxObjEnumerationAccess;
697 Reference<XIdlArray> mxObjIdlArray;
699 Reference<XElementAccess> getXElementAccess();
700 Reference<XNameContainer> getXNameContainer();
701 Reference<XNameReplace> getXNameReplace();
702 Reference<XNameAccess> getXNameAccess();
703 Reference<XIndexContainer> getXIndexContainer();
704 Reference<XIndexReplace> getXIndexReplace();
705 Reference<XIndexAccess> getXIndexAccess();
706 Reference<XEnumerationAccess> getXEnumerationAccess();
707 Reference<XIdlArray> getXIdlArray();
709 void cacheXNameContainer();
710 void cacheXIndexContainer();
712 public:
713 ImplIntrospectionAccess( const Any& obj, rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ );
715 // Methods from XIntrospectionAccess
716 virtual sal_Int32 SAL_CALL getSuppliedMethodConcepts() override;
717 virtual sal_Int32 SAL_CALL getSuppliedPropertyConcepts() override;
718 virtual Property SAL_CALL getProperty(const OUString& Name, sal_Int32 PropertyConcepts) override;
719 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name, sal_Int32 PropertyConcepts) override;
720 virtual Sequence< Property > SAL_CALL getProperties(sal_Int32 PropertyConcepts) override;
721 virtual Reference<XIdlMethod> SAL_CALL getMethod(const OUString& Name, sal_Int32 MethodConcepts) override;
722 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name, sal_Int32 MethodConcepts) override;
723 virtual Sequence< Reference<XIdlMethod> > SAL_CALL getMethods(sal_Int32 MethodConcepts) override;
724 virtual Sequence< Type > SAL_CALL getSupportedListeners() override;
725 using OWeakObject::queryAdapter;
726 virtual Reference<XInterface> SAL_CALL queryAdapter( const Type& rType ) override;
728 // Methods from XMaterialHolder
729 virtual Any SAL_CALL getMaterial() override;
731 // Methods from XExactName
732 virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) override;
734 // Methods from XInterface
735 virtual Any SAL_CALL queryInterface( const Type& rType ) override;
736 virtual void SAL_CALL acquire() throw() override { OWeakObject::acquire(); }
737 virtual void SAL_CALL release() throw() override { OWeakObject::release(); }
739 // Methods from XPropertySet
740 virtual Reference<XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
741 virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, const Any& aValue) override;
742 virtual Any SAL_CALL getPropertyValue(const OUString& aPropertyName) override;
743 virtual void SAL_CALL addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) override;
744 virtual void SAL_CALL removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) override;
745 virtual void SAL_CALL addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) override;
746 virtual void SAL_CALL removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) override;
748 // Methods from XFastPropertySet
749 virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const Any& aValue) override;
750 virtual Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override;
752 // Methods from XPropertySetInfo
753 virtual Sequence< Property > SAL_CALL getProperties() override;
754 virtual Property SAL_CALL getPropertyByName(const OUString& Name) override;
755 virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& Name) override;
757 // Methods from XElementAccess
758 virtual Type SAL_CALL getElementType() override;
759 virtual sal_Bool SAL_CALL hasElements() override;
761 // Methods from XNameAccess
762 virtual Any SAL_CALL getByName(const OUString& Name) override;
763 virtual Sequence< OUString > SAL_CALL getElementNames() override;
764 virtual sal_Bool SAL_CALL hasByName(const OUString& Name) override;
766 // Methods from XNameReplace
767 virtual void SAL_CALL replaceByName(const OUString& Name, const Any& Element) override;
769 // Methods from XNameContainer
770 virtual void SAL_CALL insertByName(const OUString& Name, const Any& Element) override;
771 virtual void SAL_CALL removeByName(const OUString& Name) override;
773 // Methods from XIndexAccess
774 virtual sal_Int32 SAL_CALL getCount() override;
775 virtual Any SAL_CALL getByIndex(sal_Int32 Index) override;
777 // Methods from XIndexReplace
778 virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element) override;
780 // Methods from XIndexContainer
781 virtual void SAL_CALL insertByIndex(sal_Int32 Index, const Any& Element) override;
782 virtual void SAL_CALL removeByIndex(sal_Int32 Index) override;
784 // Methods from XEnumerationAccess
785 virtual Reference<XEnumeration> SAL_CALL createEnumeration() override;
787 // Methods from XIdlArray
788 virtual void SAL_CALL realloc(Any& array, sal_Int32 length) override;
789 virtual sal_Int32 SAL_CALL getLen(const Any& array) override;
790 virtual Any SAL_CALL get(const Any& array, sal_Int32 index) override;
791 virtual void SAL_CALL set(Any& array, sal_Int32 index, const Any& value) override;
793 // Methods from XUnoTunnel
794 virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier ) override;
797 ImplIntrospectionAccess::ImplIntrospectionAccess
798 ( const Any& obj, rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ )
799 : maInspectedObject( obj ), mpStaticImpl( pStaticImpl_ ) //, maAdapter()
801 // Save object as an interface if possible
802 maInspectedObject >>= mxIface;
804 mnLastPropertyConcept = -1;
805 mnLastMethodConcept = -1;
808 Reference<XElementAccess> ImplIntrospectionAccess::getXElementAccess()
810 ResettableGuard< Mutex > aGuard( m_aMutex );
812 if( !mxObjElementAccess.is() )
814 aGuard.clear();
815 Reference<XElementAccess> xElementAccess( mxIface, UNO_QUERY );
816 aGuard.reset();
817 if( !mxObjElementAccess.is() )
818 mxObjElementAccess = xElementAccess;
820 return mxObjElementAccess;
823 void ImplIntrospectionAccess::cacheXNameContainer()
825 Reference<XNameContainer> xNameContainer;
826 Reference<XNameReplace> xNameReplace;
827 Reference<XNameAccess> xNameAccess;
828 if (mpStaticImpl->mbNameContainer)
830 xNameContainer.set( mxIface, UNO_QUERY );
831 xNameReplace.set( xNameContainer, UNO_QUERY );
832 xNameAccess.set( xNameContainer, UNO_QUERY );
834 else if (mpStaticImpl->mbNameReplace)
836 xNameReplace.set( mxIface, UNO_QUERY );
837 xNameAccess.set( xNameReplace, UNO_QUERY );
839 else if (mpStaticImpl->mbNameAccess)
841 xNameAccess.set( mxIface, UNO_QUERY );
845 MutexGuard aGuard( m_aMutex );
846 if( !mxObjNameContainer.is() )
847 mxObjNameContainer = xNameContainer;
848 if( !mxObjNameReplace.is() )
849 mxObjNameReplace = xNameReplace;
850 if( !mxObjNameAccess.is() )
851 mxObjNameAccess = xNameAccess;
855 Reference<XNameContainer> ImplIntrospectionAccess::getXNameContainer()
857 ClearableGuard< Mutex > aGuard( m_aMutex );
859 if( !mxObjNameContainer.is() )
861 aGuard.clear();
862 cacheXNameContainer();
864 return mxObjNameContainer;
867 Reference<XNameReplace> ImplIntrospectionAccess::getXNameReplace()
869 ClearableGuard< Mutex > aGuard( m_aMutex );
871 if( !mxObjNameReplace.is() )
873 aGuard.clear();
874 cacheXNameContainer();
876 return mxObjNameReplace;
879 Reference<XNameAccess> ImplIntrospectionAccess::getXNameAccess()
881 ClearableGuard< Mutex > aGuard( m_aMutex );
883 if( !mxObjNameAccess.is() )
885 aGuard.clear();
886 cacheXNameContainer();
888 return mxObjNameAccess;
891 void ImplIntrospectionAccess::cacheXIndexContainer()
893 Reference<XIndexContainer> xIndexContainer;
894 Reference<XIndexReplace> xIndexReplace;
895 Reference<XIndexAccess> xIndexAccess;
896 if (mpStaticImpl->mbIndexContainer)
898 xIndexContainer.set( mxIface, UNO_QUERY );
899 xIndexReplace.set( xIndexContainer, UNO_QUERY );
900 xIndexAccess.set( xIndexContainer, UNO_QUERY );
902 else if (mpStaticImpl->mbIndexReplace)
904 xIndexReplace.set( mxIface, UNO_QUERY );
905 xIndexAccess.set( xIndexReplace, UNO_QUERY );
907 else if (mpStaticImpl->mbIndexAccess)
909 xIndexAccess.set( mxIface, UNO_QUERY );
913 MutexGuard aGuard( m_aMutex );
914 if( !mxObjIndexContainer.is() )
915 mxObjIndexContainer = xIndexContainer;
916 if( !mxObjIndexReplace.is() )
917 mxObjIndexReplace = xIndexReplace;
918 if( !mxObjIndexAccess.is() )
919 mxObjIndexAccess = xIndexAccess;
923 Reference<XIndexContainer> ImplIntrospectionAccess::getXIndexContainer()
925 ClearableGuard< Mutex > aGuard( m_aMutex );
927 if( !mxObjIndexContainer.is() )
929 aGuard.clear();
930 cacheXIndexContainer();
932 return mxObjIndexContainer;
935 Reference<XIndexReplace> ImplIntrospectionAccess::getXIndexReplace()
937 ClearableGuard< Mutex > aGuard( m_aMutex );
939 if( !mxObjIndexReplace.is() )
941 aGuard.clear();
942 cacheXIndexContainer();
944 return mxObjIndexReplace;
947 Reference<XIndexAccess> ImplIntrospectionAccess::getXIndexAccess()
949 ClearableGuard< Mutex > aGuard( m_aMutex );
951 if( !mxObjIndexAccess.is() )
953 aGuard.clear();
954 cacheXIndexContainer();
956 return mxObjIndexAccess;
959 Reference<XEnumerationAccess> ImplIntrospectionAccess::getXEnumerationAccess()
961 ResettableGuard< Mutex > aGuard( m_aMutex );
963 if( !mxObjEnumerationAccess.is() )
965 aGuard.clear();
966 Reference<XEnumerationAccess> xEnumerationAccess( mxIface, UNO_QUERY );
967 aGuard.reset();
968 if( !mxObjEnumerationAccess.is() )
969 mxObjEnumerationAccess = xEnumerationAccess;
971 return mxObjEnumerationAccess;
974 Reference<XIdlArray> ImplIntrospectionAccess::getXIdlArray()
976 ResettableGuard< Mutex > aGuard( m_aMutex );
978 if( !mxObjIdlArray.is() )
980 aGuard.clear();
981 Reference<XIdlArray> xIdlArray( mxIface, UNO_QUERY );
982 aGuard.reset();
983 if( !mxObjIdlArray.is() )
984 mxObjIdlArray = xIdlArray;
986 return mxObjIdlArray;
989 // Methods from XInterface
990 Any SAL_CALL ImplIntrospectionAccess::queryInterface( const Type& rType )
992 Any aRet( ::cppu::queryInterface(
993 rType,
994 static_cast< XIntrospectionAccess * >( this ),
995 static_cast< XMaterialHolder * >( this ),
996 static_cast< XExactName * >( this ),
997 static_cast< XPropertySet * >( this ),
998 static_cast< XFastPropertySet * >( this ),
999 static_cast< XPropertySetInfo * >( this ) ) );
1000 if( !aRet.hasValue() )
1001 aRet = OWeakObject::queryInterface( rType );
1003 if( !aRet.hasValue() )
1005 // Wrapper for the object interfaces
1006 if( ( mpStaticImpl->mbElementAccess && (aRet = ::cppu::queryInterface
1007 ( rType, static_cast< XElementAccess* >( static_cast< XNameAccess* >( this ) ) ) ).hasValue() )
1008 || ( mpStaticImpl->mbNameAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() )
1009 || ( mpStaticImpl->mbNameReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XNameReplace* >( this ) ) ).hasValue() )
1010 || ( mpStaticImpl->mbNameContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() )
1011 || ( mpStaticImpl->mbIndexAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() )
1012 || ( mpStaticImpl->mbIndexReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexReplace* >( this ) ) ).hasValue() )
1013 || ( mpStaticImpl->mbIndexContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() )
1014 || ( mpStaticImpl->mbEnumerationAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() )
1015 || ( mpStaticImpl->mbIdlArray && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() )
1016 || ( mpStaticImpl->mbUnoTunnel && (aRet = ::cppu::queryInterface( rType, static_cast< XUnoTunnel* >( this ) ) ).hasValue() )
1021 return aRet;
1025 //*** Implementation of ImplIntrospectionAdapter ***
1028 // Methods from XPropertySet
1029 Reference<XPropertySetInfo> ImplIntrospectionAccess::getPropertySetInfo()
1031 return static_cast<XPropertySetInfo *>(this);
1034 void ImplIntrospectionAccess::setPropertyValue(const OUString& aPropertyName, const Any& aValue)
1036 mpStaticImpl->setPropertyValue( maInspectedObject, aPropertyName, aValue );
1039 Any ImplIntrospectionAccess::getPropertyValue(const OUString& aPropertyName)
1041 return mpStaticImpl->getPropertyValue( maInspectedObject, aPropertyName );
1044 void ImplIntrospectionAccess::addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
1046 if( mxIface.is() )
1048 Reference<XPropertySet> xPropSet =
1049 Reference<XPropertySet>::query( mxIface );
1050 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1051 if( xPropSet.is() )
1052 xPropSet->addPropertyChangeListener(aPropertyName, aListener);
1056 void ImplIntrospectionAccess::removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
1058 if( mxIface.is() )
1060 Reference<XPropertySet> xPropSet =
1061 Reference<XPropertySet>::query( mxIface );
1062 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1063 if( xPropSet.is() )
1064 xPropSet->removePropertyChangeListener(aPropertyName, aListener);
1068 void ImplIntrospectionAccess::addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1070 if( mxIface.is() )
1072 Reference<XPropertySet> xPropSet =
1073 Reference<XPropertySet>::query( mxIface );
1074 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1075 if( xPropSet.is() )
1076 xPropSet->addVetoableChangeListener(aPropertyName, aListener);
1080 void ImplIntrospectionAccess::removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1082 if( mxIface.is() )
1084 Reference<XPropertySet> xPropSet =
1085 Reference<XPropertySet>::query( mxIface );
1086 if( xPropSet.is() )
1087 xPropSet->removeVetoableChangeListener(aPropertyName, aListener);
1092 // Methods from XFastPropertySet
1093 void ImplIntrospectionAccess::setFastPropertyValue(sal_Int32, const Any&)
1097 Any ImplIntrospectionAccess::getFastPropertyValue(sal_Int32)
1099 return Any();
1102 // Methods from XPropertySetInfo
1103 Sequence< Property > ImplIntrospectionAccess::getProperties()
1105 return comphelper::containerToSequence(mpStaticImpl->getProperties());
1108 Property ImplIntrospectionAccess::getPropertyByName(const OUString& Name)
1110 return getProperty( Name, PropertyConcept::ALL );
1113 sal_Bool ImplIntrospectionAccess::hasPropertyByName(const OUString& Name)
1115 return hasProperty( Name, PropertyConcept::ALL );
1118 // Methods from XElementAccess
1119 Type ImplIntrospectionAccess::getElementType()
1121 return getXElementAccess()->getElementType();
1124 sal_Bool ImplIntrospectionAccess::hasElements()
1126 return getXElementAccess()->hasElements();
1129 // Methods from XNameAccess
1130 Any ImplIntrospectionAccess::getByName(const OUString& Name)
1132 return getXNameAccess()->getByName( Name );
1135 Sequence< OUString > ImplIntrospectionAccess::getElementNames()
1137 return getXNameAccess()->getElementNames();
1140 sal_Bool ImplIntrospectionAccess::hasByName(const OUString& Name)
1142 return getXNameAccess()->hasByName( Name );
1145 // Methods from XNameContainer
1146 void ImplIntrospectionAccess::insertByName(const OUString& Name, const Any& Element)
1148 getXNameContainer()->insertByName( Name, Element );
1151 void ImplIntrospectionAccess::replaceByName(const OUString& Name, const Any& Element)
1153 getXNameReplace()->replaceByName( Name, Element );
1156 void ImplIntrospectionAccess::removeByName(const OUString& Name)
1158 getXNameContainer()->removeByName( Name );
1161 // Methods from XIndexAccess
1162 // Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const
1163 sal_Int32 ImplIntrospectionAccess::getCount()
1165 return getXIndexAccess()->getCount();
1168 Any ImplIntrospectionAccess::getByIndex(sal_Int32 Index)
1170 return getXIndexAccess()->getByIndex( Index );
1173 // Methods from XIndexContainer
1174 void ImplIntrospectionAccess::insertByIndex(sal_Int32 Index, const Any& Element)
1176 getXIndexContainer()->insertByIndex( Index, Element );
1179 void ImplIntrospectionAccess::replaceByIndex(sal_Int32 Index, const Any& Element)
1181 getXIndexReplace()->replaceByIndex( Index, Element );
1184 void ImplIntrospectionAccess::removeByIndex(sal_Int32 Index)
1186 getXIndexContainer()->removeByIndex( Index );
1189 // Methods from XEnumerationAccess
1190 // Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const;
1191 Reference<XEnumeration> ImplIntrospectionAccess::createEnumeration()
1193 return getXEnumerationAccess()->createEnumeration();
1196 // Methods from XIdlArray
1197 void ImplIntrospectionAccess::realloc(Any& array, sal_Int32 length)
1199 getXIdlArray()->realloc( array, length );
1202 sal_Int32 ImplIntrospectionAccess::getLen(const Any& array)
1204 return getXIdlArray()->getLen( array );
1207 Any ImplIntrospectionAccess::get(const Any& array, sal_Int32 index)
1209 return getXIdlArray()->get( array, index );
1212 void ImplIntrospectionAccess::set(Any& array, sal_Int32 index, const Any& value)
1214 getXIdlArray()->set( array, index, value );
1217 // Methods from XUnoTunnel
1218 sal_Int64 ImplIntrospectionAccess::getSomething( const Sequence< sal_Int8 >& aIdentifier )
1220 return Reference<XUnoTunnel>::query( mxIface )->getSomething( aIdentifier );
1224 //*** Implementation of ImplIntrospectionAccess ***
1226 // Methods from XIntrospectionAccess
1227 sal_Int32 ImplIntrospectionAccess::getSuppliedMethodConcepts()
1229 return MethodConcept::DANGEROUS |
1230 PROPERTY |
1231 LISTENER |
1232 ENUMERATION |
1233 NAMECONTAINER |
1234 INDEXCONTAINER;
1237 sal_Int32 ImplIntrospectionAccess::getSuppliedPropertyConcepts()
1239 return PropertyConcept::DANGEROUS |
1240 PROPERTYSET |
1241 ATTRIBUTES |
1242 METHODS;
1245 Property ImplIntrospectionAccess::getProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1247 Property aRet;
1248 sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1249 bool bFound = false;
1250 if( i != -1 )
1252 sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1253 if( (PropertyConcepts & nConcept) != 0 )
1255 aRet = mpStaticImpl->getProperties()[ i ];
1256 bFound = true;
1259 if( !bFound )
1260 throw NoSuchElementException(Name);
1261 return aRet;
1264 sal_Bool ImplIntrospectionAccess::hasProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1266 sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1267 bool bRet = false;
1268 if( i != -1 )
1270 sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1271 if( (PropertyConcepts & nConcept) != 0 )
1272 bRet = true;
1274 return bRet;
1277 Sequence< Property > ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts)
1279 // If all supported concepts are required, simply pass through the sequence
1280 sal_Int32 nAllSupportedMask = PROPERTYSET |
1281 ATTRIBUTES |
1282 METHODS;
1283 if( ( PropertyConcepts & nAllSupportedMask ) == nAllSupportedMask )
1285 return comphelper::containerToSequence(mpStaticImpl->getProperties());
1288 // Same sequence as last time?
1289 if( mnLastPropertyConcept == PropertyConcepts )
1291 return maLastPropertySeq;
1294 // Number of properties to be delivered
1295 sal_Int32 nCount = 0;
1297 // There are currently no DANGEROUS properties
1298 // if( PropertyConcepts & DANGEROUS )
1299 // nCount += mpStaticImpl->mnDangerousPropCount;
1300 if( PropertyConcepts & PROPERTYSET )
1301 nCount += mpStaticImpl->mnPropertySetPropCount;
1302 if( PropertyConcepts & ATTRIBUTES )
1303 nCount += mpStaticImpl->mnAttributePropCount;
1304 if( PropertyConcepts & METHODS )
1305 nCount += mpStaticImpl->mnMethodPropCount;
1307 // Realloc sequence according to the required number
1308 maLastPropertySeq.realloc( nCount );
1309 Property* pDestProps = maLastPropertySeq.getArray();
1311 // Go through all the properties and apply according to the concept
1312 const std::vector<Property>& rPropSeq = mpStaticImpl->getProperties();
1313 const std::vector<sal_Int32>& rConcepts = mpStaticImpl->getPropertyConcepts();
1314 sal_Int32 nLen = (sal_Int32)rPropSeq.size();
1316 sal_Int32 iDest = 0;
1317 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1319 sal_Int32 nConcept = rConcepts[ i ];
1320 if( nConcept & PropertyConcepts )
1321 pDestProps[ iDest++ ] = rPropSeq[ i ];
1324 // Remember PropertyConcept representing maLastPropertySeq
1325 mnLastPropertyConcept = PropertyConcepts;
1327 // Supply assembled Sequence
1328 return maLastPropertySeq;
1331 Reference<XIdlMethod> ImplIntrospectionAccess::getMethod(const OUString& Name, sal_Int32 MethodConcepts)
1333 Reference<XIdlMethod> xRet;
1334 sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1335 if( i != -1 )
1338 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1339 if( (MethodConcepts & nConcept) != 0 )
1341 xRet = mpStaticImpl->getMethods()[i];
1344 if( !xRet.is() )
1345 throw NoSuchMethodException(Name);
1346 return xRet;
1349 sal_Bool ImplIntrospectionAccess::hasMethod(const OUString& Name, sal_Int32 MethodConcepts)
1351 sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1352 bool bRet = false;
1353 if( i != -1 )
1355 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1356 if( (MethodConcepts & nConcept) != 0 )
1357 bRet = true;
1359 return bRet;
1362 Sequence< Reference<XIdlMethod> > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts)
1364 // If all supported concepts are required, simply pass through the sequence
1365 sal_Int32 nAllSupportedMask = MethodConcept::DANGEROUS |
1366 PROPERTY |
1367 LISTENER |
1368 ENUMERATION |
1369 NAMECONTAINER |
1370 INDEXCONTAINER |
1371 MethodConcept_NORMAL_IMPL;
1372 if( ( MethodConcepts & nAllSupportedMask ) == nAllSupportedMask )
1374 return comphelper::containerToSequence(mpStaticImpl->getMethods());
1377 // Same sequence as last time?
1378 if( mnLastMethodConcept == MethodConcepts )
1380 return maLastMethodSeq;
1383 // Get method sequences
1384 const std::vector< Reference<XIdlMethod> >& aMethodSeq = mpStaticImpl->getMethods();
1385 sal_Int32 nLen = (sal_Int32)aMethodSeq.size();
1387 // Realloc sequence according to the required number
1388 // Unlike Properties, the number can not be determined by counters in
1389 // inspect() beforehand, since methods can belong to several concepts
1390 maLastMethodSeq.realloc( nLen );
1391 Reference<XIdlMethod>* pDestMethods = maLastMethodSeq.getArray();
1393 // Go through all the methods and apply according to the concept
1394 sal_Int32 iDest = 0;
1395 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1397 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1398 if( nConcept & MethodConcepts )
1399 pDestMethods[ iDest++ ] = aMethodSeq[ i ];
1402 // Bring to the correct length
1403 maLastMethodSeq.realloc( iDest );
1405 // Remember MethodConcept representing maLastMethodSeq
1406 mnLastMethodConcept = MethodConcepts;
1408 // Supply assembled Sequence
1409 return maLastMethodSeq;
1412 Sequence< Type > ImplIntrospectionAccess::getSupportedListeners()
1414 return comphelper::containerToSequence(mpStaticImpl->getSupportedListeners());
1417 Reference<XInterface> SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type& rType )
1419 Reference<XInterface> xRet;
1420 if( rType == cppu::UnoType<XInterface>::get()
1421 || rType == cppu::UnoType<XPropertySet>::get()
1422 || rType == cppu::UnoType<XFastPropertySet>::get()
1423 || rType == cppu::UnoType<XPropertySetInfo>::get()
1424 || rType == cppu::UnoType<XElementAccess>::get()
1425 || rType == cppu::UnoType<XNameAccess>::get()
1426 || rType == cppu::UnoType<XNameReplace>::get()
1427 || rType == cppu::UnoType<XNameContainer>::get()
1428 || rType == cppu::UnoType<XIndexAccess>::get()
1429 || rType == cppu::UnoType<XIndexReplace>::get()
1430 || rType == cppu::UnoType<XIndexContainer>::get()
1431 || rType == cppu::UnoType<XEnumerationAccess>::get()
1432 || rType == cppu::UnoType<XIdlArray>::get()
1433 || rType == cppu::UnoType<XUnoTunnel>::get() )
1435 queryInterface( rType ) >>= xRet;
1437 return xRet;
1440 // Methods from XMaterialHolder
1441 Any ImplIntrospectionAccess::getMaterial()
1443 return maInspectedObject;
1446 // Methods from XExactName
1447 OUString ImplIntrospectionAccess::getExactName( const OUString& rApproximateName )
1449 OUString aRetStr;
1450 LowerToExactNameMap::iterator aIt =
1451 mpStaticImpl->maLowerToExactNameMap.find( rApproximateName.toAsciiLowerCase() );
1452 if (aIt != mpStaticImpl->maLowerToExactNameMap.end())
1453 aRetStr = (*aIt).second;
1454 return aRetStr;
1457 struct TypeKey {
1458 TypeKey(
1459 css::uno::Reference<css::beans::XPropertySetInfo> const & theProperties,
1460 std::vector<css::uno::Type> const & theTypes):
1461 properties(theProperties)
1463 //TODO: Could even sort the types lexicographically first, to increase
1464 // the chance of matches between different implementations' getTypes(),
1465 // but the old scheme of using getImplementationId() would have missed
1466 // those matches, too:
1467 OUStringBuffer b;
1468 for (const css::uno::Type& rType : theTypes) {
1469 b.append(rType.getTypeName());
1470 b.append('*'); // arbitrary delimiter not used by type grammar
1472 types = b.makeStringAndClear();
1475 css::uno::Reference<css::beans::XPropertySetInfo> properties;
1476 OUString types;
1479 struct TypeKeyLess {
1480 bool operator ()(TypeKey const & key1, TypeKey const & key2) const {
1481 if (key1.properties.get() < key2.properties.get()) {
1482 return true;
1484 if (key1.properties.get() > key2.properties.get()) {
1485 return false;
1487 return key1.types < key2.types;
1491 template<typename Key, typename Less> class Cache {
1492 public:
1493 rtl::Reference<IntrospectionAccessStatic_Impl> find(Key const & key) const {
1494 typename Map::const_iterator i(map_.find(key));
1495 if (i == map_.end()) {
1496 return rtl::Reference<IntrospectionAccessStatic_Impl>();
1497 } else {
1498 if (i->second.hits < std::numeric_limits<unsigned>::max()) {
1499 ++i->second.hits;
1501 assert(i->second.access.is());
1502 return i->second.access;
1506 void insert(
1507 Key const & key,
1508 rtl::Reference<IntrospectionAccessStatic_Impl> const & access)
1510 assert(access.is());
1511 typename Map::size_type const MAX = 100;
1512 assert(map_.size() <= MAX);
1513 if (map_.size() == MAX) {
1514 typename Map::iterator del(map_.begin());
1515 for (typename Map::iterator i(map_.begin()); i != map_.end(); ++i) {
1516 if (i->second.hits < del->second.hits) {
1517 del = i;
1520 map_.erase(del);
1522 bool ins = map_.insert(typename Map::value_type(key, Data(access)))
1523 .second;
1524 assert(ins); (void)ins;
1527 void clear() { map_.clear(); }
1529 private:
1530 struct Data {
1531 explicit Data(
1532 rtl::Reference<IntrospectionAccessStatic_Impl> const & theAccess):
1533 access(theAccess), hits(1)
1536 rtl::Reference<IntrospectionAccessStatic_Impl> access;
1537 mutable unsigned hits;
1540 typedef std::map<Key, Data, Less> Map;
1542 Map map_;
1545 typedef
1546 cppu::WeakComponentImplHelper<
1547 css::lang::XServiceInfo, css::beans::XIntrospection>
1548 Implementation_Base;
1550 class Implementation: private cppu::BaseMutex, public Implementation_Base {
1551 public:
1552 explicit Implementation(
1553 css::uno::Reference<css::uno::XComponentContext> const & context):
1554 Implementation_Base(m_aMutex),
1555 reflection_(css::reflection::theCoreReflection::get(context))
1558 private:
1559 virtual void SAL_CALL disposing() override {
1560 osl::MutexGuard g(m_aMutex);
1561 reflection_.clear();
1562 typeCache_.clear();
1565 virtual OUString SAL_CALL getImplementationName() override
1566 { return OUString("com.sun.star.comp.stoc.Introspection"); }
1568 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
1569 { return cppu::supportsService(this, ServiceName); }
1571 virtual css::uno::Sequence<OUString> SAL_CALL
1572 getSupportedServiceNames() override
1574 Sequence<OUString> s { "com.sun.star.beans.Introspection" };
1575 return s;
1578 virtual css::uno::Reference<css::beans::XIntrospectionAccess> SAL_CALL
1579 inspect(css::uno::Any const & aObject) override;
1581 css::uno::Reference<css::reflection::XIdlReflection> reflection_;
1582 Cache<TypeKey, TypeKeyLess> typeCache_;
1585 css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
1586 css::uno::Any const & aObject)
1588 css::uno::Reference<css::reflection::XIdlReflection> reflection;
1590 osl::MutexGuard g(m_aMutex);
1591 if (rBHelper.bDisposed || rBHelper.bInDispose) {
1592 throw css::lang::DisposedException(
1593 getImplementationName(), static_cast<OWeakObject *>(this));
1595 reflection = reflection_;
1597 css::uno::Any aToInspectObj;
1598 css::uno::Type t;
1599 if (aObject >>= t) {
1600 css::uno::Reference<css::reflection::XIdlClass> c(
1601 reflection->forName(t.getTypeName()));
1602 if (!c.is()) {
1603 SAL_WARN("stoc", "cannot reflect type " << t.getTypeName());
1604 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1606 aToInspectObj <<= c;
1607 } else {
1608 aToInspectObj = aObject;
1611 // Examine object
1612 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1613 if( eType != TypeClass_INTERFACE && eType != TypeClass_STRUCT && eType != TypeClass_EXCEPTION )
1614 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1616 if( auto x = o3tl::tryAccess<Reference<XInterface>>(aToInspectObj) )
1618 if( !x->is() )
1619 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1622 // Pointer to possibly needed new IntrospectionAccessStatic_Impl instance
1623 rtl::Reference< IntrospectionAccessStatic_Impl > pAccess;
1625 // Check: Is a matching access object already cached?
1626 std::vector< Reference<XIdlClass> > SupportedClassSeq;
1627 std::vector< Type > SupportedTypesSeq;
1628 Reference<XTypeProvider> xTypeProvider;
1629 Reference<XPropertySetInfo> xPropSetInfo;
1630 Reference<XPropertySet> xPropSet;
1632 // Look for interfaces XTypeProvider and PropertySet
1633 if( eType == TypeClass_INTERFACE )
1635 xTypeProvider.set( aToInspectObj, UNO_QUERY );
1636 if( xTypeProvider.is() )
1638 SupportedTypesSeq = comphelper::sequenceToContainer<std::vector<Type>>(xTypeProvider->getTypes());
1639 } else {
1640 SAL_WARN(
1641 "stoc",
1642 "object of type \"" << aToInspectObj.getValueTypeName()
1643 << "\" lacks XTypeProvider");
1644 SupportedTypesSeq = { aToInspectObj.getValueType() };
1646 // Now try to get the PropertySetInfo
1647 xPropSet.set( aToInspectObj, UNO_QUERY );
1648 if( xPropSet.is() )
1649 xPropSetInfo = xPropSet->getPropertySetInfo();
1651 } else {
1652 SupportedTypesSeq = { aToInspectObj.getValueType() };
1656 osl::MutexGuard g(m_aMutex);
1657 if (rBHelper.bDisposed || rBHelper.bInDispose) {
1658 throw css::lang::DisposedException(
1659 getImplementationName(), static_cast<OWeakObject *>(this));
1661 TypeKey key(xPropSetInfo, SupportedTypesSeq);
1662 pAccess = typeCache_.find(key);
1663 if (pAccess.is()) {
1664 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
1666 pAccess = new IntrospectionAccessStatic_Impl(reflection);
1667 typeCache_.insert(key, pAccess);
1670 // No access cached -> create new
1671 std::vector<Property>& rAllPropArray = pAccess->maAllPropertySeq;
1672 std::vector<Reference<XInterface>>& rInterfaces1 = pAccess->aInterfaceSeq1;
1673 std::vector<Reference<XInterface>>& rInterfaces2 = pAccess->aInterfaceSeq2;
1674 std::vector<sal_Int16>& rMapTypeArray = pAccess->maMapTypeSeq;
1675 std::vector<sal_Int32>& rPropertyConceptArray = pAccess->maPropertyConceptSeq;
1676 sal_Int32 i;
1678 // References to important data from pAccess
1679 sal_Int32& rPropCount = pAccess->mnPropCount;
1680 IntrospectionNameMap& rPropNameMap = pAccess->maPropertyNameMap;
1681 IntrospectionNameMap& rMethodNameMap = pAccess->maMethodNameMap;
1682 LowerToExactNameMap& rLowerToExactNameMap = pAccess->maLowerToExactNameMap;
1685 //*** Perform analysis ***
1687 if( eType == TypeClass_INTERFACE )
1689 size_t nTypeCount = SupportedTypesSeq.size();
1690 if( nTypeCount )
1692 SupportedClassSeq.resize( nTypeCount );
1694 for( i = 0 ; i < (sal_Int32)nTypeCount ; i++ )
1695 SupportedClassSeq[i] = reflection->forName( SupportedTypesSeq[i].getTypeName() );
1698 // First look for particular interfaces that are of particular
1699 // importance to the introspection
1701 // Is XPropertySet present?
1702 if( xPropSet.is() && xPropSetInfo.is() )
1704 // Is there also a FastPropertySet?
1705 Reference<XFastPropertySet> xDummy( aToInspectObj, UNO_QUERY );
1706 bool bFast = pAccess->mbFastPropSet = xDummy.is();
1708 Sequence<Property> aPropSeq = xPropSetInfo->getProperties();
1709 const Property* pProps = aPropSeq.getConstArray();
1710 sal_Int32 nLen = aPropSeq.getLength();
1712 // For a FastPropertySet we must remember the original handles
1713 if( bFast )
1714 pAccess->mpOrgPropertyHandleArray.reset( new sal_Int32[ nLen ] );
1716 for( i = 0 ; i < nLen ; i++ )
1718 // Put property in its own list
1719 pAccess->checkPropertyArraysSize( rPropCount );
1720 Property& rProp = rAllPropArray[ rPropCount ];
1721 rProp = pProps[ i ];
1723 if( bFast )
1724 pAccess->mpOrgPropertyHandleArray[ i ] = rProp.Handle;
1726 // Enter PropCount as a handle for its own FastPropertySet
1727 rProp.Handle = rPropCount;
1729 // Remember type of property
1730 rMapTypeArray[ rPropCount ] = MAP_PROPERTY_SET;
1731 rPropertyConceptArray[ rPropCount ] = PROPERTYSET;
1732 pAccess->mnPropertySetPropCount++;
1734 // Enter name in hash table if not already known
1735 OUString aPropName = rProp.Name;
1737 // Do we already have the name?
1738 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1739 if( aIt == rPropNameMap.end() )
1741 // New entry in the hash table
1742 rPropNameMap[ aPropName ] = rPropCount;
1744 // Maintain table for XExactName
1745 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1747 else
1749 SAL_WARN( "stoc", "Introspection: Property \"" <<
1750 aPropName << "\" found more than once in PropertySet" );
1753 // Adjust count
1754 rPropCount++;
1758 // Indices in the export table
1759 sal_Int32 iAllExportedMethod = 0;
1760 sal_Int32 iAllSupportedListener = 0;
1762 std::set<OUString> seen;
1764 // Flag, whether XInterface methods should be recorded
1765 // (this must be done only once, allowed initially)
1766 bool bXInterfaceIsInvalid = false;
1768 // Flag whether the XInterface methods have already been recorded. If
1769 // sal_True, bXInterfaceIsInvalid is activated at the end of the interface
1770 // loop, and XInterface methods are cut off thereafter.
1771 bool bFoundXInterface = false;
1773 size_t nClassCount = SupportedClassSeq.size();
1774 for( sal_Int32 nIdx = 0 ; nIdx < (sal_Int32)nClassCount; nIdx++ )
1776 Reference<XIdlClass> xImplClass2 = SupportedClassSeq[nIdx];
1777 while( xImplClass2.is() )
1779 // Fetch interfaces from the implementation
1780 Sequence< Reference<XIdlClass> > aClassSeq = xImplClass2->getInterfaces();
1781 sal_Int32 nIfaceCount = aClassSeq.getLength();
1783 aClassSeq.realloc( nIfaceCount + 1 );
1784 aClassSeq.getArray()[ nIfaceCount ] = xImplClass2;
1785 nIfaceCount++;
1787 const Reference<XIdlClass>* pParamArray = aClassSeq.getConstArray();
1789 for( sal_Int32 j = 0 ; j < nIfaceCount ; j++ )
1791 const Reference<XIdlClass>& rxIfaceClass = pParamArray[j];
1792 if (!seen.insert(rxIfaceClass->getName()).second) {
1793 continue;
1796 // 2. Register fields as properties
1798 // Get fields
1799 Sequence< Reference<XIdlField> > fields = rxIfaceClass->getFields();
1800 const Reference<XIdlField>* pFields = fields.getConstArray();
1801 sal_Int32 nLen = fields.getLength();
1803 for( i = 0 ; i < nLen ; i++ )
1805 Reference<XIdlField> xField = pFields[i];
1806 Reference<XIdlClass> xPropType = xField->getType();
1808 // Is the property sequence big enough?
1809 pAccess->checkPropertyArraysSize( rPropCount );
1811 // Enter in own property array
1812 Property& rProp = rAllPropArray[ rPropCount ];
1813 OUString aFieldName = xField->getName();
1814 rProp.Name = aFieldName;
1815 rProp.Handle = rPropCount;
1816 Type aFieldType( xPropType->getTypeClass(), xPropType->getName() );
1817 rProp.Type = aFieldType;
1818 FieldAccessMode eAccessMode = xField->getAccessMode();
1819 rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
1820 eAccessMode == FieldAccessMode_CONST)
1821 ? READONLY : 0;
1823 // Enter name in hash table
1824 OUString aPropName = rProp.Name;
1826 // Do we have the name already?
1827 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1828 if (aIt != rPropNameMap.end())
1829 continue;
1831 // New entry in the hash table
1832 rPropNameMap[ aPropName ] = rPropCount;
1834 // Maintain table for XExactName
1835 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1837 // Remember field
1838 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
1839 rInterfaces1, rPropCount );
1840 rInterfaces1[ rPropCount ] = xField;
1842 // Remember type of property
1843 rMapTypeArray[ rPropCount ] = MAP_FIELD;
1844 rPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
1845 pAccess->mnAttributePropCount++;
1847 // Adjust count
1848 rPropCount++;
1852 // 3. Methods
1854 // Counter for found listeners
1855 sal_Int32 nListenerCount = 0;
1857 // Get and remember all methods
1858 Sequence< Reference<XIdlMethod> > methods = rxIfaceClass->getMethods();
1859 const Reference<XIdlMethod>* pSourceMethods = methods.getConstArray();
1860 sal_Int32 nSourceMethodCount = methods.getLength();
1862 // 3. a) Search get/set and listener methods
1864 // Create field for information about the methods, so that methods which are not
1865 // related to properties or listeners can easily be found later.
1866 // New: initialise MethodConceptArray
1867 enum MethodType
1869 STANDARD_METHOD, // normal method, not related to properties or listeners
1870 GETSET_METHOD, // belongs to a get/set property
1871 ADD_LISTENER_METHOD, // add method of a listener interface
1872 REMOVE_LISTENER_METHOD, // remove method of a listener interface
1873 INVALID_METHOD // method whose class is not considered, e.g. XPropertySet
1875 std::unique_ptr<MethodType[]> pMethodTypes( new MethodType[ nSourceMethodCount ] );
1876 std::unique_ptr<sal_Int32[]> pLocalMethodConcepts( new sal_Int32[ nSourceMethodCount ] );
1877 for( i = 0 ; i < nSourceMethodCount ; i++ )
1879 pMethodTypes[ i ] = STANDARD_METHOD;
1880 pLocalMethodConcepts[ i ] = 0;
1883 for( i = 0 ; i < nSourceMethodCount ; i++ )
1885 // Address method
1886 const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
1887 sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
1889 // Fetch name
1890 OUString aMethName = rxMethod_i->getName();
1892 // Catalogue methods
1893 // Filter all (?) methods of XInterface so e.g. acquire and release
1894 // can not be called from scripting
1895 rtl::OUString className(
1896 rxMethod_i->getDeclaringClass()->getName());
1897 if (className == "com.sun.star.uno.XInterface") {
1898 bFoundXInterface = true;
1900 if( bXInterfaceIsInvalid )
1902 pMethodTypes[ i ] = INVALID_METHOD;
1903 continue;
1905 else
1907 if( aMethName != "queryInterface" )
1909 rMethodConcept_i |= MethodConcept::DANGEROUS;
1910 continue;
1913 } else if (className == "com.sun.star.uno.XAggregation")
1915 if( aMethName == "setDelegator" )
1917 rMethodConcept_i |= MethodConcept::DANGEROUS;
1918 continue;
1920 } else if (className
1921 == "com.sun.star.container.XElementAccess")
1923 rMethodConcept_i |= ( NAMECONTAINER |
1924 INDEXCONTAINER |
1925 ENUMERATION );
1926 pAccess->mbElementAccess = true;
1927 } else if ((className
1928 == "com.sun.star.container.XNameContainer"))
1930 rMethodConcept_i |= NAMECONTAINER;
1931 pAccess->mbNameContainer = true;
1932 pAccess->mbNameReplace = true;
1933 pAccess->mbNameAccess = true;
1934 pAccess->mbElementAccess = true;
1935 } else if ((className
1936 == "com.sun.star.container.XNameReplace"))
1938 rMethodConcept_i |= NAMECONTAINER;
1939 pAccess->mbNameReplace = true;
1940 pAccess->mbNameAccess = true;
1941 pAccess->mbElementAccess = true;
1942 } else if ((className
1943 == "com.sun.star.container.XNameAccess"))
1945 rMethodConcept_i |= NAMECONTAINER;
1946 pAccess->mbNameAccess = true;
1947 pAccess->mbElementAccess = true;
1948 } else if ((className
1949 == "com.sun.star.container.XIndexContainer"))
1951 rMethodConcept_i |= INDEXCONTAINER;
1952 pAccess->mbIndexContainer = true;
1953 pAccess->mbIndexReplace = true;
1954 pAccess->mbIndexAccess = true;
1955 pAccess->mbElementAccess = true;
1956 } else if ((className
1957 == "com.sun.star.container.XIndexReplace"))
1959 rMethodConcept_i |= INDEXCONTAINER;
1960 pAccess->mbIndexReplace = true;
1961 pAccess->mbIndexAccess = true;
1962 pAccess->mbElementAccess = true;
1963 } else if ((className
1964 == "com.sun.star.container.XIndexAccess"))
1966 rMethodConcept_i |= INDEXCONTAINER;
1967 pAccess->mbIndexAccess = true;
1968 pAccess->mbElementAccess = true;
1969 } else if (className
1970 == "com.sun.star.container.XEnumerationAccess")
1972 rMethodConcept_i |= ENUMERATION;
1973 pAccess->mbEnumerationAccess = true;
1974 pAccess->mbElementAccess = true;
1975 } else if (className
1976 == "com.sun.star.reflection.XIdlArray")
1978 pAccess->mbIdlArray = true;
1979 } else if (className
1980 == "com.sun.star.lang.XUnoTunnel")
1982 pAccess->mbUnoTunnel = true;
1985 // If the name is too short, it isn't anything
1986 if( aMethName.getLength() <= 3 )
1987 continue;
1989 // Is it a get method?
1990 OUString aPropName;
1991 if( aMethName.startsWith("get", &aPropName) )
1993 // Get methods must not have any parameters
1994 Sequence< Reference<XIdlClass> > getParams = rxMethod_i->getParameterTypes();
1995 if( getParams.getLength() > 0 )
1997 continue;
2000 // Do we have the name already?
2001 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2002 if (aIt != rPropNameMap.end())
2004 /* TODO
2005 SAL_INFO("stoc",(
2006 String( "Introspection: Property \"" ) +
2007 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2008 String( "\" found more than once" ) );
2010 continue;
2013 // It is already at least a read-only property
2014 rMethodConcept_i |= PROPERTY;
2016 pMethodTypes[i] = GETSET_METHOD;
2017 Reference<XIdlClass> xGetRetType = rxMethod_i->getReturnType();
2019 // Is the property sequence big enough?
2020 pAccess->checkPropertyArraysSize( rPropCount );
2022 // Write it in its property array
2023 Property& rProp = rAllPropArray[ rPropCount ];
2024 rProp.Name = aPropName;
2025 rProp.Handle = rPropCount;
2026 rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
2027 rProp.Attributes = READONLY;
2029 // New entry in the hash table
2030 rPropNameMap[ aPropName ] = rPropCount;
2032 // Maintain table for XExactName
2033 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2035 // Remember get method
2036 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
2037 rInterfaces1, rPropCount );
2038 rInterfaces1[ rPropCount ] = rxMethod_i;
2040 // Remember type of property
2041 rMapTypeArray[ rPropCount ] = MAP_GETSET;
2042 rPropertyConceptArray[ rPropCount ] = METHODS;
2043 pAccess->mnMethodPropCount++;
2045 // Search for matching set method
2046 sal_Int32 k;
2047 for( k = 0 ; k < nSourceMethodCount ; k++ )
2049 // Address method
2050 const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k];
2052 // Accept only methods that are not already assigned
2053 if( k == i || pMethodTypes[k] != STANDARD_METHOD )
2054 continue;
2056 // Get name and evaluate
2057 OUString aMethName2 = rxMethod_k->getName();
2058 OUString aPropName2;
2059 if (!(aMethName2.startsWith("set", &aPropName2)
2060 && aPropName2 == aPropName))
2061 continue;
2063 // A set method must return void
2064 Reference<XIdlClass> xSetRetType = rxMethod_k->getReturnType();
2065 if( xSetRetType->getTypeClass() != TypeClass_VOID )
2067 continue;
2070 // A set method may only have one parameter
2071 Sequence< Reference<XIdlClass> > setParams = rxMethod_k->getParameterTypes();
2072 sal_Int32 nParamCount = setParams.getLength();
2073 if( nParamCount != 1 )
2075 continue;
2078 // Next, the return type must correspond to the parameter type
2079 const Reference<XIdlClass>* pParamArray2 = setParams.getConstArray();
2080 Reference<XIdlClass> xParamType = pParamArray2[ 0 ];
2081 if( xParamType->equals( xGetRetType ) )
2083 pLocalMethodConcepts[ k ] = PROPERTY;
2085 pMethodTypes[k] = GETSET_METHOD;
2087 // Delete read-only flag again
2088 rProp.Attributes &= ~READONLY;
2090 // Remember set method
2091 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2092 rInterfaces2, rPropCount );
2093 rInterfaces2[ rPropCount ] = rxMethod_k;
2097 // Adjust count
2098 rPropCount++;
2101 // Is it an add listener method?
2102 else if( aMethName.startsWith("add", &aPropName) )
2104 // Does it end with "Listener"?
2105 OUString aListenerName;
2106 if( !aPropName.endsWith("Listener", &aListenerName) )
2107 continue;
2109 // TODO: More accurate tests could still be carried out here
2110 // - Return type
2111 // - Number and type of parameters
2114 // Search for matching remove method, otherwise not applicable
2115 sal_Int32 k;
2116 for( k = 0 ; k < nSourceMethodCount ; k++ )
2118 // Address method
2119 const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k];
2121 // Accept only methods that are not already assigned
2122 if( k == i || pMethodTypes[k] != STANDARD_METHOD )
2123 continue;
2125 // Get name and evaluate
2126 OUString aMethName2 = rxMethod_k->getName();
2127 OUString aListenerName2;
2128 if (!(aMethName2.startsWith(
2129 "remove", &aPropName)
2130 && aPropName.endsWith(
2131 "Listener", &aListenerName2)
2132 && aListenerName2 == aListenerName))
2133 continue;
2135 // TODO: More accurate tests could still be carried out here
2136 // - Return type
2137 // - Number and type of parameters
2140 // Methods are recognised as a listener interface
2141 rMethodConcept_i |= LISTENER;
2142 pLocalMethodConcepts[ k ] |= LISTENER;
2144 pMethodTypes[i] = ADD_LISTENER_METHOD;
2145 pMethodTypes[k] = REMOVE_LISTENER_METHOD;
2146 nListenerCount++;
2152 // A set method could still exist without a corresponding get method,
2153 // this must be a write-only property
2154 for( i = 0 ; i < nSourceMethodCount ; i++ )
2156 // Address method
2157 const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
2159 // Accept only methods that are not already assigned
2160 if( pMethodTypes[i] != STANDARD_METHOD )
2161 continue;
2163 // Get name
2164 OUString aMethName = rxMethod_i->getName();
2166 // If the name is too short, it isn't anything
2167 if( aMethName.getLength() <= 3 )
2168 continue;
2170 // Is it a set method without associated get method?
2171 OUString aPropName;
2172 if( aMethName.startsWith("set", &aPropName) )
2174 // A set method must return void
2175 Reference<XIdlClass> xSetRetType = rxMethod_i->getReturnType();
2176 if( xSetRetType->getTypeClass() != TypeClass_VOID )
2178 continue;
2181 // A set method may only have one parameter
2182 Sequence< Reference<XIdlClass> > setParams = rxMethod_i->getParameterTypes();
2183 sal_Int32 nParamCount = setParams.getLength();
2184 if( nParamCount != 1 )
2186 continue;
2189 // Do we have the name already?
2190 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2191 if (aIt != rPropNameMap.end())
2193 /* TODO:
2194 SAL_INFO("stoc",(
2195 String( "Introspection: Property \"" ) +
2196 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2197 String( "\" found more than once" ) );
2199 continue;
2202 // Now we know it's a write only property
2203 pLocalMethodConcepts[ i ] = PROPERTY;
2205 pMethodTypes[i] = GETSET_METHOD;
2206 Reference<XIdlClass> xGetRetType = setParams.getConstArray()[0];
2208 // Is the property sequence big enough?
2209 pAccess->checkPropertyArraysSize( rPropCount );
2211 // Write it in its property array
2212 Property& rProp = rAllPropArray[ rPropCount ];
2213 rProp.Name = aPropName;
2214 rProp.Handle = rPropCount;
2215 rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
2216 rProp.Attributes = 0; // PROPERTY_WRITEONLY ???
2218 // New entry in the hash table
2219 rPropNameMap[ aPropName ] = rPropCount;
2221 // Maintain table for XExactName
2222 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2224 // Remember set method
2225 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2226 rInterfaces2, rPropCount );
2227 rInterfaces2[ rPropCount ] = rxMethod_i;
2229 // Remember type of property
2230 rMapTypeArray[ rPropCount ] = MAP_SETONLY;
2231 rPropertyConceptArray[ rPropCount ] = METHODS;
2232 pAccess->mnMethodPropCount++;
2234 // Adjust count
2235 rPropCount++;
2240 // 4. Place methods in overall sequence
2242 // How many methods in the method sequence
2243 sal_Int32 nExportedMethodCount = 0;
2244 sal_Int32 nSupportedListenerCount = 0;
2245 for( i = 0 ; i < nSourceMethodCount ; i++ )
2247 if( pMethodTypes[ i ] != INVALID_METHOD )
2249 nExportedMethodCount++;
2251 if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2253 nSupportedListenerCount++;
2257 // Enlarge sequences in the access object accordingly
2258 pAccess->maAllMethodSeq.resize( nExportedMethodCount + iAllExportedMethod );
2259 pAccess->maMethodConceptSeq.resize( nExportedMethodCount + iAllExportedMethod );
2260 pAccess->maSupportedListenerSeq.resize( nSupportedListenerCount + iAllSupportedListener );
2262 // Write in methods
2263 for( i = 0 ; i < nSourceMethodCount ; i++ )
2265 if( pMethodTypes[ i ] != INVALID_METHOD )
2267 // Address method
2268 const Reference<XIdlMethod>& rxMethod = pSourceMethods[i];
2270 // Enter name in hash table if not already known
2271 OUString aMethName2 = rxMethod->getName();
2272 IntrospectionNameMap::iterator aIt = rMethodNameMap.find( aMethName2 );
2273 if( aIt == rMethodNameMap.end() )
2275 // Enter
2276 rMethodNameMap[ aMethName2 ] = iAllExportedMethod;
2278 // Maintain table for XExactName
2279 rLowerToExactNameMap[ aMethName2.toAsciiLowerCase() ] = aMethName2;
2281 else
2283 sal_Int32 iHashResult = aIt->second;
2285 Reference<XIdlMethod> xExistingMethod = pAccess->maAllMethodSeq[iHashResult];
2287 Reference< XIdlClass > xExistingMethClass =
2288 xExistingMethod->getDeclaringClass();
2289 Reference< XIdlClass > xNewMethClass = rxMethod->getDeclaringClass();
2290 if( xExistingMethClass->equals( xNewMethClass ) )
2291 continue;
2294 pAccess->maAllMethodSeq[iAllExportedMethod] = rxMethod;
2296 // If a concept has been set, is the method "normal"?
2297 sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
2298 if( !rMethodConcept_i )
2299 rMethodConcept_i = MethodConcept_NORMAL_IMPL;
2300 pAccess->maMethodConceptSeq[ iAllExportedMethod ] = rMethodConcept_i;
2301 iAllExportedMethod++;
2303 if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2305 // Determine class of listener
2306 const Reference<XIdlMethod>& rxMethod = pSourceMethods[i];
2308 // Enter void as default class
2309 css::uno::Reference<css::reflection::XIdlClass>
2310 xListenerClass(
2311 reflection->forName(
2312 cppu::UnoType<void>::get()
2313 .getTypeName()));
2314 // Old: Reference<XIdlClass> xListenerClass = Void_getReflection()->getIdlClass();
2316 // Option 1: Search for parameters for a listener class
2317 // Disadvantage: Superclasses should be searched recursively
2318 Sequence< Reference<XIdlClass> > aParams = rxMethod->getParameterTypes();
2319 const Reference<XIdlClass>* pParamArray2 = aParams.getConstArray();
2321 css::uno::Reference<css::reflection::XIdlClass>
2322 xEventListenerClass(
2323 reflection->forName(
2324 cppu::UnoType<
2325 css::lang::XEventListener>::get()
2326 .getTypeName()));
2327 // Old: Reference<XIdlClass> xEventListenerClass = XEventListener_getReflection()->getIdlClass();
2328 sal_Int32 nParamCount = aParams.getLength();
2329 sal_Int32 k;
2330 for( k = 0 ; k < nParamCount ; k++ )
2332 const Reference<XIdlClass>& rxClass = pParamArray2[k];
2334 // Are we derived from a listener?
2335 if( rxClass->equals( xEventListenerClass ) ||
2336 isDerivedFrom( rxClass, xEventListenerClass ) )
2338 xListenerClass = rxClass;
2339 break;
2343 // Option 2: Unload the name of the method
2344 // Disadvantage: Does not work with test listeners, where it does not exist
2345 //aMethName = rxMethod->getName();
2346 //aListenerName = aMethName.Copy( 3, aMethName.Len()-8-3 );
2347 //Reference<XIdlClass> xListenerClass = reflection->forName( aListenerName );
2348 Type aListenerType( TypeClass_INTERFACE, xListenerClass->getName() );
2349 pAccess->maSupportedListenerSeq[ iAllSupportedListener ] = aListenerType;
2350 iAllSupportedListener++;
2354 // When there were XInterface methods in this run,
2355 // ignore them in the future
2356 if( bFoundXInterface )
2357 bXInterfaceIsInvalid = true;
2360 // Do superclasses exist? Then continue here
2361 Sequence< Reference<XIdlClass> > aSuperClassSeq = xImplClass2->getSuperclasses();
2363 // Currently only one superclass is considered
2364 if( aSuperClassSeq.getLength() >= 1 )
2366 xImplClass2 = aSuperClassSeq.getConstArray()[0];
2367 OSL_ENSURE( xImplClass2.is(), "super class null" );
2369 else
2371 xImplClass2 = nullptr;
2376 // Apply number of exported methods and adapt Sequences
2377 // (can be different because duplicate methods are thrown
2378 // out only after the determination of nExportedMethodCount)
2379 sal_Int32& rMethCount = pAccess->mnMethCount;
2380 rMethCount = iAllExportedMethod;
2381 pAccess->maAllMethodSeq.resize( rMethCount );
2382 pAccess->maMethodConceptSeq.resize( rMethCount );
2384 // Resize the property sequences
2385 pAccess->maAllPropertySeq.resize( rPropCount );
2386 pAccess->maPropertyConceptSeq.resize( rPropCount );
2387 pAccess->maMapTypeSeq.resize( rPropCount );
2389 // Register struct fields as properties
2390 else //if( eType == TypeClass_STRUCT )
2392 // Is it an interface or a struct?
2393 //Reference<XIdlClass> xClassRef = aToInspectObj.getReflection()->getIdlClass();
2394 css::uno::Reference<css::reflection::XIdlClass> xClassRef(
2395 reflection->forName(aToInspectObj.getValueTypeName()));
2396 if( !xClassRef.is() )
2398 SAL_WARN( "stoc", "Can't get XIdlClass from Reflection" );
2399 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
2402 // Get fields
2403 Sequence< Reference<XIdlField> > fields = xClassRef->getFields();
2404 const Reference<XIdlField>* pFields = fields.getConstArray();
2405 sal_Int32 nLen = fields.getLength();
2407 for( i = 0 ; i < nLen ; i++ )
2409 Reference<XIdlField> xField = pFields[i];
2410 Reference<XIdlClass> xPropType = xField->getType();
2411 OUString aPropName = xField->getName();
2413 // Is the property sequence big enough?
2414 pAccess->checkPropertyArraysSize( rPropCount );
2416 // Write it in its property array
2417 Property& rProp = rAllPropArray[ rPropCount ];
2418 rProp.Name = aPropName;
2419 rProp.Handle = rPropCount;
2420 rProp.Type = Type( xPropType->getTypeClass(), xPropType->getName() );
2421 FieldAccessMode eAccessMode = xField->getAccessMode();
2422 rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
2423 eAccessMode == FieldAccessMode_CONST)
2424 ? READONLY : 0;
2426 //FieldAccessMode eAccessMode = xField->getAccessMode();
2427 //rProp.Attributes = (eAccessMode == FieldAccessMode::READONLY || eAccessMode == CONST)
2428 //? PropertyAttribute::READONLY : 0;
2430 // Write name in hash table
2431 rPropNameMap[ aPropName ] = rPropCount;
2433 // Maintain table for XExactName
2434 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2436 // Remember field
2437 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
2438 rInterfaces1, rPropCount );
2439 rInterfaces1[ rPropCount ] = xField;
2441 // Remember type of property
2442 rMapTypeArray[ rPropCount ] = MAP_FIELD;
2443 rPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
2444 pAccess->mnAttributePropCount++;
2446 // Adjust count
2447 rPropCount++;
2451 // Set property sequence to the correct length
2452 pAccess->maAllPropertySeq.resize( pAccess->mnPropCount );
2454 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
2457 struct Instance {
2458 explicit Instance(
2459 css::uno::Reference<css::uno::XComponentContext> const & context):
2460 instance(new Implementation(context))
2463 rtl::Reference<cppu::OWeakObject> instance;
2466 struct Singleton:
2467 public rtl::StaticWithArg<
2468 Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
2473 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
2474 com_sun_star_comp_stoc_Introspection_get_implementation(
2475 css::uno::XComponentContext * context,
2476 css::uno::Sequence<css::uno::Any> const & arguments)
2478 SAL_WARN_IF(
2479 arguments.hasElements(), "stoc", "unexpected singleton arguments");
2480 return cppu::acquire(Singleton::get(context).instance.get());
2483 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */