LibreOffice Module stoc (master) 1
introspection.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <cassert>
23#include <cstddef>
24#include <limits>
25#include <map>
26#include <memory>
27#include <mutex>
28#include <set>
29
30#include <o3tl/any.hxx>
31#include <osl/diagnose.h>
32#include <sal/log.hxx>
36#include <cppuhelper/weak.hxx>
41
42#include <com/sun/star/lang/NoSuchMethodException.hpp>
43#include <com/sun/star/lang/XServiceInfo.hpp>
44#include <com/sun/star/lang/XUnoTunnel.hpp>
45#include <com/sun/star/reflection/XIdlReflection.hpp>
46#include <com/sun/star/reflection/XIdlClass.hpp>
47#include <com/sun/star/reflection/XIdlField2.hpp>
48#include <com/sun/star/reflection/theCoreReflection.hpp>
49#include <com/sun/star/beans/UnknownPropertyException.hpp>
50#include <com/sun/star/beans/Property.hpp>
51#include <com/sun/star/beans/XPropertySet.hpp>
52#include <com/sun/star/beans/XFastPropertySet.hpp>
53#include <com/sun/star/beans/XIntrospection.hpp>
54#include <com/sun/star/beans/XIntrospectionAccess.hpp>
55#include <com/sun/star/beans/XMaterialHolder.hpp>
56#include <com/sun/star/beans/XExactName.hpp>
57#include <com/sun/star/beans/PropertyAttribute.hpp>
58#include <com/sun/star/beans/PropertyConcept.hpp>
59#include <com/sun/star/beans/MethodConcept.hpp>
60#include <com/sun/star/container/XNameContainer.hpp>
61#include <com/sun/star/container/XIndexContainer.hpp>
62#include <com/sun/star/container/XEnumerationAccess.hpp>
63
64#include <rtl/ref.hxx>
65#include <rtl/ustrbuf.hxx>
66#include <unordered_map>
67#include <utility>
68
69using namespace css::uno;
70using namespace css::lang;
71using namespace css::reflection;
72using namespace css::container;
73using namespace css::beans;
74using namespace css::beans::PropertyAttribute;
75using namespace css::beans::PropertyConcept;
76using namespace css::beans::MethodConcept;
77using namespace cppu;
78using namespace osl;
79
80namespace
81{
82
83typedef WeakImplHelper< XIntrospectionAccess, XMaterialHolder, XExactName,
84 XPropertySet, XFastPropertySet, XPropertySetInfo,
85 XNameContainer, XIndexContainer, XEnumerationAccess,
86 XIdlArray, XUnoTunnel > IntrospectionAccessHelper;
87
88
89// Special value for Method-Concept, to be able to mark "normal" functions
90#define MethodConcept_NORMAL_IMPL 0x80000000
91
92
93// Method to assert, if a class is derived from another class
94bool isDerivedFrom( const Reference<XIdlClass>& xToTestClass, const Reference<XIdlClass>& xDerivedFromClass )
95{
96 const Sequence< Reference<XIdlClass> > aClassesSeq = xToTestClass->getSuperclasses();
97
98 return std::any_of(aClassesSeq.begin(), aClassesSeq.end(),
99 [&xDerivedFromClass](const Reference<XIdlClass>& rxClass) {
100 return xDerivedFromClass->equals( rxClass )
101 || isDerivedFrom( rxClass, xDerivedFromClass );
102 });
103}
104
105
106// *** Classification of Properties (no enum, to be able to use Sequence) ***
107// Properties from a PropertySet-Interface
108#define MAP_PROPERTY_SET 0
109// Properties from Fields
110#define MAP_FIELD 1
111// Properties that get described with get/set methods
112#define MAP_GETSET 2
113// Properties with only a set method
114#define MAP_SETONLY 3
115
116
117// Increments by which the size of sequences get adjusted
118#define ARRAY_SIZE_STEP 20
119
120
121//*** IntrospectionAccessStatic_Impl ***
122
123// Equals to the old IntrospectionAccessImpl, forms now a static
124// part of the new Instance-related ImplIntrospectionAccess
125
126// Hashtable for the search of names
127typedef std::unordered_map
128<
129 OUString,
130 sal_Int32
131>
132IntrospectionNameMap;
133
134
135// Hashtable to assign exact names to the Lower-Case
136// converted names, for the support of XExactName
137typedef std::unordered_map
138<
139 OUString,
140 OUString
141>
142LowerToExactNameMap;
143
144
145class IntrospectionAccessStatic_Impl: public salhelper::SimpleReferenceObject
146{
147 friend class Implementation;
148 friend class ImplIntrospectionAccess;
149
150 // Holding CoreReflection
151 Reference< XIdlReflection > mxCoreReflection;
152
153 // InterfaceSequences, to save additional information in a property
154 // for example the Field at MAP_FIELD, the get/set-Methods at MAP_GETSET, et cetera
155 std::vector< Reference<XInterface> > aInterfaceSeq1;
156 std::vector< Reference<XInterface> > aInterfaceSeq2;
157
158 // Hashtables for names
159 IntrospectionNameMap maPropertyNameMap;
160 IntrospectionNameMap maMethodNameMap;
161 LowerToExactNameMap maLowerToExactNameMap;
162
163 // Vector of all Properties, also for delivering from getProperties()
164 std::vector<Property> maAllPropertySeq;
165
166 // Mapping of properties to Access-Types
167 std::vector<sal_Int16> maMapTypeSeq;
168
169 // Classification of found methods
170 std::vector<sal_Int32> maPropertyConceptSeq;
171
172 // Number of Properties
173 sal_Int32 mnPropCount;
174
175 // Number of Properties, which are assigned to particular concepts
176 //sal_Int32 mnDangerousPropCount;
177 sal_Int32 mnPropertySetPropCount;
178 sal_Int32 mnAttributePropCount;
179 sal_Int32 mnMethodPropCount;
180
181 // Flags which indicate if various interfaces are present
182 bool mbFastPropSet;
183 bool mbElementAccess;
184 bool mbNameAccess;
185 bool mbNameReplace;
186 bool mbNameContainer;
187 bool mbIndexAccess;
188 bool mbIndexReplace;
189 bool mbIndexContainer;
190 bool mbEnumerationAccess;
191 bool mbIdlArray;
192 bool mbUnoTunnel;
193
194 // Original handles of FastPropertySets
195 std::unique_ptr<sal_Int32[]> mpOrgPropertyHandleArray;
196
197 // MethodSequence, that accepts all methods
198 std::vector< Reference<XIdlMethod> > maAllMethodSeq;
199
200 // Classification of found methods
201 std::vector<sal_Int32> maMethodConceptSeq;
202
203 // Number of methods
204 sal_Int32 mnMethCount;
205
206 // Sequence of Listener, that can be registered
207 std::vector< Type > maSupportedListenerSeq;
208
209 // Helper-methods for adjusting sizes of Sequences
210 void checkPropertyArraysSize( sal_Int32 iNextIndex );
211 static void checkInterfaceArraySize( std::vector< Reference<XInterface> >& rSeq, std::vector<Reference<XInterface>>& rInterfaceVec,
212 sal_Int32 iNextIndex );
213
214public:
215 explicit IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ );
216 sal_Int32 getPropertyIndex( const OUString& aPropertyName ) const;
217 sal_Int32 getMethodIndex( const OUString& aMethodName ) const;
218
219 // Methods of XIntrospectionAccess (OLD, now only Impl)
220 void setPropertyValue(const Any& obj, const OUString& aPropertyName, const Any& aValue) const;
221// void setPropertyValue(Any& obj, const OUString& aPropertyName, const Any& aValue) const;
222 Any getPropertyValue(const Any& obj, const OUString& aPropertyName) const;
223 void setPropertyValueByIndex(const Any& obj, sal_Int32 nIndex, const Any& aValue) const;
224// void setPropertyValueByIndex(Any& obj, sal_Int32 nIndex, const Any& aValue) const;
225 Any getPropertyValueByIndex(const Any& obj, sal_Int32 nIndex) const;
226
227 const std::vector<Property>& getProperties() const { return maAllPropertySeq; }
228 const std::vector< Reference<XIdlMethod> >& getMethods() const { return maAllMethodSeq; }
229 const std::vector< Type >& getSupportedListeners() const { return maSupportedListenerSeq; }
230 const std::vector<sal_Int32>& getPropertyConcepts() const { return maPropertyConceptSeq; }
231 const std::vector<sal_Int32>& getMethodConcepts() const { return maMethodConceptSeq; }
232};
233
234
235// Ctor
236IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlReflection > const & xCoreReflection_ )
237 : mxCoreReflection( xCoreReflection_ )
238{
239 aInterfaceSeq1.resize( ARRAY_SIZE_STEP );
240 aInterfaceSeq2.resize( ARRAY_SIZE_STEP );
241
242 // Property-Data
243 maAllPropertySeq.resize( ARRAY_SIZE_STEP );
244 maMapTypeSeq.resize( ARRAY_SIZE_STEP );
245 maPropertyConceptSeq.resize( ARRAY_SIZE_STEP );
246
247 mbFastPropSet = false;
248 mbElementAccess = false;
249 mbNameAccess = false;
250 mbNameReplace = false;
251 mbNameContainer = false;
252 mbIndexAccess = false;
253 mbIndexReplace = false;
254 mbIndexContainer = false;
255 mbEnumerationAccess = false;
256 mbIdlArray = false;
257 mbUnoTunnel = false;
258
259 mpOrgPropertyHandleArray = nullptr;
260
261 mnPropCount = 0;
262 //mnDangerousPropCount = 0;
263 mnPropertySetPropCount = 0;
264 mnAttributePropCount = 0;
265 mnMethodPropCount = 0;
266
267 // Method-Data
268 mnMethCount = 0;
269}
270
271sal_Int32 IntrospectionAccessStatic_Impl::getPropertyIndex( const OUString& aPropertyName ) const
272{
273 auto aIt = maPropertyNameMap.find(aPropertyName);
274 if (aIt != maPropertyNameMap.end())
275 return aIt->second;
276
277 return -1;
278}
279
280sal_Int32 IntrospectionAccessStatic_Impl::getMethodIndex( const OUString& aMethodName ) const
281{
282 auto aIt = maMethodNameMap.find(aMethodName);
283 if (aIt != maMethodNameMap.end())
284 {
285 return aIt->second;
286 }
287
288 // #95159 Check if full qualified name matches
289 sal_Int32 nSearchFrom = aMethodName.getLength();
290 while( true )
291 {
292 // Strategy: Search back until the first '_' is found
293 sal_Int32 nFound = aMethodName.lastIndexOf( '_', nSearchFrom );
294 if( nFound == -1 )
295 break;
296
297 OUString aPureMethodName = aMethodName.copy( nFound + 1 );
298
299 aIt = maMethodNameMap.find( aPureMethodName );
300 if (aIt != maMethodNameMap.end())
301 {
302 // Check if it can be a type?
303 // Problem: Does not work if package names contain _ ?!
304 OUString aStr = aMethodName.copy( 0, nFound );
305 OUString aTypeName = aStr.replace( '_', '.' );
306 Reference< XIdlClass > xClass = mxCoreReflection->forName( aTypeName );
307 if( xClass.is() )
308 {
309 // If this is a valid class it could be the right method
310
311 // Could be the right method, type has to be checked
312 const sal_Int32 iHashResult = aIt->second;
313
314 const Reference<XIdlMethod> xMethod = maAllMethodSeq[iHashResult];
315
316 Reference< XIdlClass > xMethClass = xMethod->getDeclaringClass();
317 if( xClass->equals( xMethClass ) )
318 {
319 return iHashResult;
320 }
321 else
322 {
323 // Could also be another method with the same name
324 // Iterate over all methods
325 size_t nLen = maAllMethodSeq.size();
326 for (size_t i = 0; i < nLen; ++i)
327 {
328 const Reference<XIdlMethod> xMethod2 = maAllMethodSeq[ i ];
329 if( xMethod2->getName() == aPureMethodName )
330 {
331 Reference< XIdlClass > xMethClass2 = xMethod2->getDeclaringClass();
332
333 if( xClass->equals( xMethClass2 ) )
334 {
335 return i;
336 }
337 }
338 }
339 }
340 }
341 }
342
343 nSearchFrom = nFound - 1;
344 if( nSearchFrom < 0 )
345 break;
346 }
347 return -1;
348}
349
350void IntrospectionAccessStatic_Impl::setPropertyValue( const Any& obj, const OUString& aPropertyName, const Any& aValue ) const
351//void IntrospectionAccessStatic_Impl::setPropertyValue( Any& obj, const OUString& aPropertyName, const Any& aValue ) const
352{
353 sal_Int32 i = getPropertyIndex( aPropertyName );
354 if( i == -1 )
355 throw UnknownPropertyException(aPropertyName);
356 setPropertyValueByIndex( obj, i, aValue );
357}
358
359void IntrospectionAccessStatic_Impl::setPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
360//void IntrospectionAccessStatic_Impl::setPropertyValueByIndex( Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
361{
362 // Is the passed object something that fits?
363 Reference<XInterface> xInterface;
364 if( !(obj >>= xInterface) )
365 {
366 TypeClass eObjType = obj.getValueType().getTypeClass();
367 if( nSequenceIndex >= mnPropCount)
368 throw IllegalArgumentException(
369 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), index > propertyCount, " +
370 OUString::number(nSequenceIndex) + " > " + OUString::number(mnPropCount),
371 Reference<XInterface>(), 0);
372 if( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION )
373 throw IllegalArgumentException(
374 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), expected struct or exception, got" +
375 obj.getValueType().getTypeName(), Reference<XInterface>(), 0);
376 }
377
378 // Test flags
379 if( (maAllPropertySeq[ nSequenceIndex ].Attributes & READONLY) != 0 )
380 {
381 throw UnknownPropertyException(
382 "IntrospectionAccessStatic_Impl::setPropertyValueByIndex(), property at index " + OUString::number(nSequenceIndex) + " is readonly");
383 }
384
385 switch( maMapTypeSeq[ nSequenceIndex ] )
386 {
387 case MAP_PROPERTY_SET:
388 {
389 // Get Property
390 const Property& rProp = maAllPropertySeq[ nSequenceIndex ];
391
392 // Convert Interface-Parameter to the correct type
393 bool bUseCopy = false;
394 Any aRealValue;
395
396 if( auto valInterface = o3tl::tryAccess<
397 css::uno::Reference<css::uno::XInterface>>(aValue) )
398 {
399 Type aPropType = rProp.Type;
400 OUString aTypeName( aPropType.getTypeName() );
401 Reference< XIdlClass > xPropClass = mxCoreReflection->forName( aTypeName );
402 //Reference<XIdlClass> xPropClass = rProp.Type;
403 if( xPropClass.is() && xPropClass->getTypeClass() == TypeClass_INTERFACE )
404 {
405 if( valInterface->is() )
406 {
407 //Any queryInterface( const Type& rType );
408 aRealValue = (*valInterface)->queryInterface( aPropType );
409 if( aRealValue.hasValue() )
410 bUseCopy = true;
411 }
412 }
413 }
414
415 // Do we have a FastPropertySet and a valid Handle?
416 // CAUTION: At this point we exploit that the PropertySet
417 // gets queried at the beginning of the Introspection-Process.
418 sal_Int32 nOrgHandle;
419 if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
420 {
421 // Retrieve PropertySet-Interface
422 Reference<XFastPropertySet> xFastPropSet =
423 Reference<XFastPropertySet>::query( xInterface );
424 if( xFastPropSet.is() )
425 {
426 xFastPropSet->setFastPropertyValue( nOrgHandle, bUseCopy ? aRealValue : aValue );
427 }
428 else
429 {
430 // throw UnknownPropertyException
431 }
432 }
433 // else take the normal one
434 else
435 {
436 // Retrieve PropertySet-Interface
437 Reference<XPropertySet> xPropSet =
438 Reference<XPropertySet>::query( xInterface );
439 if( xPropSet.is() )
440 {
441 xPropSet->setPropertyValue( rProp.Name, bUseCopy ? aRealValue : aValue );
442 }
443 else
444 {
445 // throw UnknownPropertyException
446 }
447 }
448 }
449 break;
450
451 case MAP_FIELD:
452 {
453 Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
454 Reference<XIdlField2> xField2(xField, UNO_QUERY);
455 if( xField2.is() )
456 {
457 xField2->set( const_cast<Any&>(obj), aValue );
458 // IllegalArgumentException
459 // NullPointerException
460 } else
461 if( xField.is() )
462 {
463 xField->set( obj, aValue );
464 // IllegalArgumentException
465 // NullPointerException
466 }
467 else
468 {
469 // throw IllegalArgumentException();
470 }
471 }
472 break;
473
474 case MAP_GETSET:
475 case MAP_SETONLY:
476 {
477 // Fetch set method
478 Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq2[ nSequenceIndex ].get());
479 if( xMethod.is() )
480 {
481 Sequence<Any> args( 1 );
482 args.getArray()[0] = aValue;
483 xMethod->invoke( obj, args );
484 }
485 else
486 {
487 // throw IllegalArgumentException();
488 }
489 }
490 break;
491 }
492}
493
494Any IntrospectionAccessStatic_Impl::getPropertyValue( const Any& obj, const OUString& aPropertyName ) const
495{
496 sal_Int32 i = getPropertyIndex( aPropertyName );
497 if( i != -1 )
498 return getPropertyValueByIndex( obj, i );
499
500 throw UnknownPropertyException(aPropertyName);
501}
502
503Any IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex) const
504{
505 Any aRet;
506
507 // Is there anything suitable in the passed object?
508 Reference<XInterface> xInterface;
509 if( !(obj >>= xInterface) )
510 {
511 TypeClass eObjType = obj.getValueType().getTypeClass();
512 if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) )
513 {
514 // throw IllegalArgumentException();
515 return aRet;
516 }
517 }
518
519 switch( maMapTypeSeq[ nSequenceIndex ] )
520 {
521 case MAP_PROPERTY_SET:
522 {
523 // Acquire property
524 const Property& rProp = maAllPropertySeq[ nSequenceIndex ];
525
526 // Do we have a FastPropertySet and a valid handle?
527 // NOTE: At this point is exploited that the PropertySet
528 // is queried at the beginning of introspection process.
529 sal_Int32 nOrgHandle;
530 if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
531 {
532 // Fetch the PropertySet interface
533 Reference<XFastPropertySet> xFastPropSet =
534 Reference<XFastPropertySet>::query( xInterface );
535 if( xFastPropSet.is() )
536 {
537 aRet = xFastPropSet->getFastPropertyValue( nOrgHandle);
538 }
539 else
540 {
541 // throw UnknownPropertyException
542 return aRet;
543 }
544 }
545 // Otherwise use the normal one
546 else
547 {
548 // Fetch the PropertySet interface
549 Reference<XPropertySet> xPropSet =
550 Reference<XPropertySet>::query( xInterface );
551 if( xPropSet.is() )
552 {
553 aRet = xPropSet->getPropertyValue( rProp.Name );
554 }
555 else
556 {
557 // throw UnknownPropertyException
558 return aRet;
559 }
560 }
561 }
562 break;
563
564 case MAP_FIELD:
565 {
566 Reference<XIdlField> xField = static_cast<XIdlField*>(aInterfaceSeq1[ nSequenceIndex ].get());
567 if( xField.is() )
568 {
569 aRet = xField->get( obj );
570 // IllegalArgumentException
571 // NullPointerException
572 }
573 else
574 {
575 // throw IllegalArgumentException();
576 return aRet;
577 }
578 }
579 break;
580
581 case MAP_GETSET:
582 {
583 // Fetch get method
584 Reference<XIdlMethod> xMethod = static_cast<XIdlMethod*>(aInterfaceSeq1[ nSequenceIndex ].get());
585 if( xMethod.is() )
586 {
587 Sequence<Any> args;
588 aRet = xMethod->invoke( obj, args );
589 }
590 else
591 {
592 // throw IllegalArgumentException();
593 return aRet;
594 }
595 }
596 break;
597
598 case MAP_SETONLY:
599 // Get method does not exist
600 // throw WriteOnlyPropertyException();
601 return aRet;
602 }
603 return aRet;
604}
605
606
607// Helper method to adjust the size of the vectors
608void IntrospectionAccessStatic_Impl::checkPropertyArraysSize( sal_Int32 iNextIndex )
609{
610 sal_Int32 nLen = static_cast<sal_Int32>(maAllPropertySeq.size());
611 if( iNextIndex >= nLen )
612 {
613 maAllPropertySeq.resize( nLen + ARRAY_SIZE_STEP );
614 maMapTypeSeq.resize( nLen + ARRAY_SIZE_STEP );
615 maPropertyConceptSeq.resize( nLen + ARRAY_SIZE_STEP );
616 }
617}
618
619void IntrospectionAccessStatic_Impl::checkInterfaceArraySize( std::vector< Reference<XInterface> >& rSeq,
620 std::vector<Reference<XInterface>>& rInterfaceVec, sal_Int32 iNextIndex )
621{
622 sal_Int32 nLen = rSeq.size();
623 if( iNextIndex >= nLen )
624 {
625 // Synchronize new size with ARRAY_SIZE_STEP
626 sal_Int32 nMissingSize = iNextIndex - nLen + 1;
627 sal_Int32 nSteps = nMissingSize / ARRAY_SIZE_STEP + 1;
628 sal_Int32 nNewSize = nLen + nSteps * ARRAY_SIZE_STEP;
629
630 rSeq.resize( nNewSize );
631 rInterfaceVec = rSeq;
632 }
633}
634
635
636//*** ImplIntrospectionAccess ***
637
638
639// New Impl class as part of the introspection conversion to instance-bound
640// Introspection with property access via XPropertySet. The old class
641// ImplIntrospectionAccess lives on as IntrospectionAccessStatic_Impl
642class ImplIntrospectionAccess : public IntrospectionAccessHelper
643{
644 friend class Implementation;
645
646 // Object under examination
647 Any maInspectedObject;
648
649 // As interface
650 Reference<XInterface> mxIface;
651
652 // Static introspection data
654
655 // Last Sequence that came with getProperties (optimization)
656 Sequence<Property> maLastPropertySeq;
657 sal_Int32 mnLastPropertyConcept;
658
659 // Last Sequence that came with getMethods (optimization)
660 Sequence<Reference<XIdlMethod> > maLastMethodSeq;
661 sal_Int32 mnLastMethodConcept;
662
663 // Guards the caching of queried interfaces
664 std::mutex m_aMutex;
665
666 // Original interfaces of the objects
667 Reference<XElementAccess> mxObjElementAccess;
668 Reference<XNameContainer> mxObjNameContainer;
669 Reference<XNameReplace> mxObjNameReplace;
670 Reference<XNameAccess> mxObjNameAccess;
671 Reference<XIndexContainer> mxObjIndexContainer;
672 Reference<XIndexReplace> mxObjIndexReplace;
673 Reference<XIndexAccess> mxObjIndexAccess;
674 Reference<XEnumerationAccess> mxObjEnumerationAccess;
675 Reference<XIdlArray> mxObjIdlArray;
676
677 Reference<XElementAccess> getXElementAccess();
678 Reference<XNameContainer> getXNameContainer();
679 Reference<XNameReplace> getXNameReplace();
680 Reference<XNameAccess> getXNameAccess();
681 Reference<XIndexContainer> getXIndexContainer();
682 Reference<XIndexReplace> getXIndexReplace();
683 Reference<XIndexAccess> getXIndexAccess();
684 Reference<XEnumerationAccess> getXEnumerationAccess();
685 Reference<XIdlArray> getXIdlArray();
686
687 void cacheXNameContainer();
688 void cacheXIndexContainer();
689
690public:
691 ImplIntrospectionAccess( Any obj, rtl::Reference< IntrospectionAccessStatic_Impl > pStaticImpl_ );
692
693 // Methods from XIntrospectionAccess
694 virtual sal_Int32 SAL_CALL getSuppliedMethodConcepts() override;
695 virtual sal_Int32 SAL_CALL getSuppliedPropertyConcepts() override;
696 virtual Property SAL_CALL getProperty(const OUString& Name, sal_Int32 PropertyConcepts) override;
697 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name, sal_Int32 PropertyConcepts) override;
698 virtual Sequence< Property > SAL_CALL getProperties(sal_Int32 PropertyConcepts) override;
699 virtual Reference<XIdlMethod> SAL_CALL getMethod(const OUString& Name, sal_Int32 MethodConcepts) override;
700 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name, sal_Int32 MethodConcepts) override;
701 virtual Sequence< Reference<XIdlMethod> > SAL_CALL getMethods(sal_Int32 MethodConcepts) override;
702 virtual Sequence< Type > SAL_CALL getSupportedListeners() override;
703 using OWeakObject::queryAdapter;
704 virtual Reference<XInterface> SAL_CALL queryAdapter( const Type& rType ) override;
705
706 // Methods from XMaterialHolder
707 virtual Any SAL_CALL getMaterial() override;
708
709 // Methods from XExactName
710 virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) override;
711
712 // Methods from XInterface
713 virtual Any SAL_CALL queryInterface( const Type& rType ) override;
714 virtual void SAL_CALL acquire() noexcept override { OWeakObject::acquire(); }
715 virtual void SAL_CALL release() noexcept override { OWeakObject::release(); }
716
717 // Methods from XPropertySet
718 virtual Reference<XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
719 virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, const Any& aValue) override;
720 virtual Any SAL_CALL getPropertyValue(const OUString& aPropertyName) override;
721 virtual void SAL_CALL addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) override;
722 virtual void SAL_CALL removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) override;
723 virtual void SAL_CALL addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) override;
724 virtual void SAL_CALL removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) override;
725
726 // Methods from XFastPropertySet
727 virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const Any& aValue) override;
728 virtual Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override;
729
730 // Methods from XPropertySetInfo
731 virtual Sequence< Property > SAL_CALL getProperties() override;
732 virtual Property SAL_CALL getPropertyByName(const OUString& Name) override;
733 virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& Name) override;
734
735 // Methods from XElementAccess
736 virtual Type SAL_CALL getElementType() override;
737 virtual sal_Bool SAL_CALL hasElements() override;
738
739 // Methods from XNameAccess
740 virtual Any SAL_CALL getByName(const OUString& Name) override;
741 virtual Sequence< OUString > SAL_CALL getElementNames() override;
742 virtual sal_Bool SAL_CALL hasByName(const OUString& Name) override;
743
744 // Methods from XNameReplace
745 virtual void SAL_CALL replaceByName(const OUString& Name, const Any& Element) override;
746
747 // Methods from XNameContainer
748 virtual void SAL_CALL insertByName(const OUString& Name, const Any& Element) override;
749 virtual void SAL_CALL removeByName(const OUString& Name) override;
750
751 // Methods from XIndexAccess
752 virtual sal_Int32 SAL_CALL getCount() override;
753 virtual Any SAL_CALL getByIndex(sal_Int32 Index) override;
754
755 // Methods from XIndexReplace
756 virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element) override;
757
758 // Methods from XIndexContainer
759 virtual void SAL_CALL insertByIndex(sal_Int32 Index, const Any& Element) override;
760 virtual void SAL_CALL removeByIndex(sal_Int32 Index) override;
761
762 // Methods from XEnumerationAccess
763 virtual Reference<XEnumeration> SAL_CALL createEnumeration() override;
764
765 // Methods from XIdlArray
766 virtual void SAL_CALL realloc(Any& array, sal_Int32 length) override;
767 virtual sal_Int32 SAL_CALL getLen(const Any& array) override;
768 virtual Any SAL_CALL get(const Any& array, sal_Int32 index) override;
769 virtual void SAL_CALL set(Any& array, sal_Int32 index, const Any& value) override;
770
771 // Methods from XUnoTunnel
772 virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier ) override;
773};
774
775ImplIntrospectionAccess::ImplIntrospectionAccess
777 : maInspectedObject(std::move( obj )), mpStaticImpl(std::move( pStaticImpl_ )) ,
778 mnLastPropertyConcept(-1), mnLastMethodConcept(-1) //, maAdapter()
779{
780 // Save object as an interface if possible
781 maInspectedObject >>= mxIface;
782}
783
784Reference<XElementAccess> ImplIntrospectionAccess::getXElementAccess()
785{
786 std::unique_lock aGuard( m_aMutex );
787
788 if( !mxObjElementAccess.is() )
789 {
790 aGuard.unlock();
791 Reference<XElementAccess> xElementAccess( mxIface, UNO_QUERY );
792 aGuard.lock();
793 if( !mxObjElementAccess.is() )
794 mxObjElementAccess = xElementAccess;
795 }
796 return mxObjElementAccess;
797}
798
799void ImplIntrospectionAccess::cacheXNameContainer()
800{
801 Reference<XNameContainer> xNameContainer;
802 Reference<XNameReplace> xNameReplace;
803 Reference<XNameAccess> xNameAccess;
804 if (mpStaticImpl->mbNameContainer)
805 {
806 xNameContainer.set( mxIface, UNO_QUERY );
807 xNameReplace = xNameContainer;
808 xNameAccess = xNameContainer;
809 }
810 else if (mpStaticImpl->mbNameReplace)
811 {
812 xNameReplace.set( mxIface, UNO_QUERY );
813 xNameAccess = xNameReplace;
814 }
815 else if (mpStaticImpl->mbNameAccess)
816 {
817 xNameAccess.set( mxIface, UNO_QUERY );
818 }
819
820 {
821 std::unique_lock aGuard( m_aMutex );
822 if( !mxObjNameContainer.is() )
823 mxObjNameContainer = xNameContainer;
824 if( !mxObjNameReplace.is() )
825 mxObjNameReplace = xNameReplace;
826 if( !mxObjNameAccess.is() )
827 mxObjNameAccess = xNameAccess;
828 }
829}
830
831Reference<XNameContainer> ImplIntrospectionAccess::getXNameContainer()
832{
833 std::unique_lock aGuard( m_aMutex );
834
835 if( !mxObjNameContainer.is() )
836 {
837 aGuard.unlock();
838 cacheXNameContainer();
839 }
840 return mxObjNameContainer;
841}
842
843Reference<XNameReplace> ImplIntrospectionAccess::getXNameReplace()
844{
845 std::unique_lock aGuard( m_aMutex );
846
847 if( !mxObjNameReplace.is() )
848 {
849 aGuard.unlock();
850 cacheXNameContainer();
851 }
852 return mxObjNameReplace;
853}
854
855Reference<XNameAccess> ImplIntrospectionAccess::getXNameAccess()
856{
857 std::unique_lock aGuard( m_aMutex );
858
859 if( !mxObjNameAccess.is() )
860 {
861 aGuard.unlock();
862 cacheXNameContainer();
863 }
864 return mxObjNameAccess;
865}
866
867void ImplIntrospectionAccess::cacheXIndexContainer()
868{
869 Reference<XIndexContainer> xIndexContainer;
870 Reference<XIndexReplace> xIndexReplace;
871 Reference<XIndexAccess> xIndexAccess;
872 if (mpStaticImpl->mbIndexContainer)
873 {
874 xIndexContainer.set( mxIface, UNO_QUERY );
875 xIndexReplace = xIndexContainer;
876 xIndexAccess = xIndexContainer;
877 }
878 else if (mpStaticImpl->mbIndexReplace)
879 {
880 xIndexReplace.set( mxIface, UNO_QUERY );
881 xIndexAccess = xIndexReplace;
882 }
883 else if (mpStaticImpl->mbIndexAccess)
884 {
885 xIndexAccess.set( mxIface, UNO_QUERY );
886 }
887
888 {
889 std::unique_lock aGuard( m_aMutex );
890 if( !mxObjIndexContainer.is() )
891 mxObjIndexContainer = xIndexContainer;
892 if( !mxObjIndexReplace.is() )
893 mxObjIndexReplace = xIndexReplace;
894 if( !mxObjIndexAccess.is() )
895 mxObjIndexAccess = xIndexAccess;
896 }
897}
898
899Reference<XIndexContainer> ImplIntrospectionAccess::getXIndexContainer()
900{
901 std::unique_lock aGuard( m_aMutex );
902
903 if( !mxObjIndexContainer.is() )
904 {
905 aGuard.unlock();
906 cacheXIndexContainer();
907 }
908 return mxObjIndexContainer;
909}
910
911Reference<XIndexReplace> ImplIntrospectionAccess::getXIndexReplace()
912{
913 std::unique_lock aGuard( m_aMutex );
914
915 if( !mxObjIndexReplace.is() )
916 {
917 aGuard.unlock();
918 cacheXIndexContainer();
919 }
920 return mxObjIndexReplace;
921}
922
923Reference<XIndexAccess> ImplIntrospectionAccess::getXIndexAccess()
924{
925 std::unique_lock aGuard( m_aMutex );
926
927 if( !mxObjIndexAccess.is() )
928 {
929 aGuard.unlock();
930 cacheXIndexContainer();
931 }
932 return mxObjIndexAccess;
933}
934
935Reference<XEnumerationAccess> ImplIntrospectionAccess::getXEnumerationAccess()
936{
937 std::unique_lock aGuard( m_aMutex );
938
939 if( !mxObjEnumerationAccess.is() )
940 {
941 aGuard.unlock();
942 Reference<XEnumerationAccess> xEnumerationAccess( mxIface, UNO_QUERY );
943 aGuard.lock();
944 if( !mxObjEnumerationAccess.is() )
945 mxObjEnumerationAccess = xEnumerationAccess;
946 }
947 return mxObjEnumerationAccess;
948}
949
950Reference<XIdlArray> ImplIntrospectionAccess::getXIdlArray()
951{
952 std::unique_lock aGuard( m_aMutex );
953
954 if( !mxObjIdlArray.is() )
955 {
956 aGuard.unlock();
957 Reference<XIdlArray> xIdlArray( mxIface, UNO_QUERY );
958 aGuard.lock();
959 if( !mxObjIdlArray.is() )
960 mxObjIdlArray = xIdlArray;
961 }
962 return mxObjIdlArray;
963}
964
965// Methods from XInterface
966Any SAL_CALL ImplIntrospectionAccess::queryInterface( const Type& rType )
967{
968 Any aRet( ::cppu::queryInterface(
969 rType,
970 static_cast< XIntrospectionAccess * >( this ),
971 static_cast< XMaterialHolder * >( this ),
972 static_cast< XExactName * >( this ),
973 static_cast< XPropertySet * >( this ),
974 static_cast< XFastPropertySet * >( this ),
975 static_cast< XPropertySetInfo * >( this ) ) );
976 if( !aRet.hasValue() )
977 aRet = OWeakObject::queryInterface( rType );
978
979 if( !aRet.hasValue() )
980 {
981 // Wrapper for the object interfaces
982 ( mpStaticImpl->mbElementAccess && (aRet = ::cppu::queryInterface
983 ( rType, static_cast< XElementAccess* >( static_cast< XNameAccess* >( this ) ) ) ).hasValue() )
984 || ( mpStaticImpl->mbNameAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() )
985 || ( mpStaticImpl->mbNameReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XNameReplace* >( this ) ) ).hasValue() )
986 || ( mpStaticImpl->mbNameContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() )
987 || ( mpStaticImpl->mbIndexAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() )
988 || ( mpStaticImpl->mbIndexReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexReplace* >( this ) ) ).hasValue() )
989 || ( mpStaticImpl->mbIndexContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() )
990 || ( mpStaticImpl->mbEnumerationAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() )
991 || ( mpStaticImpl->mbIdlArray && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() )
992 || ( mpStaticImpl->mbUnoTunnel && (aRet = ::cppu::queryInterface( rType, static_cast< XUnoTunnel* >( this ) ) ).hasValue() );
993 }
994 return aRet;
995}
996
997
998//*** Implementation of ImplIntrospectionAdapter ***
999
1000
1001// Methods from XPropertySet
1002Reference<XPropertySetInfo> ImplIntrospectionAccess::getPropertySetInfo()
1003{
1004 return static_cast<XPropertySetInfo *>(this);
1005}
1006
1007void ImplIntrospectionAccess::setPropertyValue(const OUString& aPropertyName, const Any& aValue)
1008{
1009 mpStaticImpl->setPropertyValue( maInspectedObject, aPropertyName, aValue );
1010}
1011
1012Any ImplIntrospectionAccess::getPropertyValue(const OUString& aPropertyName)
1013{
1014 return mpStaticImpl->getPropertyValue( maInspectedObject, aPropertyName );
1015}
1016
1017void ImplIntrospectionAccess::addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
1018{
1019 if( mxIface.is() )
1020 {
1021 Reference<XPropertySet> xPropSet =
1022 Reference<XPropertySet>::query( mxIface );
1023 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1024 if( xPropSet.is() )
1025 xPropSet->addPropertyChangeListener(aPropertyName, aListener);
1026 }
1027}
1028
1029void ImplIntrospectionAccess::removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
1030{
1031 if( mxIface.is() )
1032 {
1033 Reference<XPropertySet> xPropSet =
1034 Reference<XPropertySet>::query( mxIface );
1035 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1036 if( xPropSet.is() )
1037 xPropSet->removePropertyChangeListener(aPropertyName, aListener);
1038 }
1039}
1040
1041void ImplIntrospectionAccess::addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1042{
1043 if( mxIface.is() )
1044 {
1045 Reference<XPropertySet> xPropSet =
1046 Reference<XPropertySet>::query( mxIface );
1047 //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1048 if( xPropSet.is() )
1049 xPropSet->addVetoableChangeListener(aPropertyName, aListener);
1050 }
1051}
1052
1053void ImplIntrospectionAccess::removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1054{
1055 if( mxIface.is() )
1056 {
1057 Reference<XPropertySet> xPropSet =
1058 Reference<XPropertySet>::query( mxIface );
1059 if( xPropSet.is() )
1060 xPropSet->removeVetoableChangeListener(aPropertyName, aListener);
1061 }
1062}
1063
1064
1065// Methods from XFastPropertySet
1066void ImplIntrospectionAccess::setFastPropertyValue(sal_Int32, const Any&)
1067{
1068}
1069
1070Any ImplIntrospectionAccess::getFastPropertyValue(sal_Int32)
1071{
1072 return Any();
1073}
1074
1075// Methods from XPropertySetInfo
1076Sequence< Property > ImplIntrospectionAccess::getProperties()
1077{
1078 return comphelper::containerToSequence(mpStaticImpl->getProperties());
1079}
1080
1081Property ImplIntrospectionAccess::getPropertyByName(const OUString& Name)
1082{
1083 return getProperty( Name, PropertyConcept::ALL );
1084}
1085
1086sal_Bool ImplIntrospectionAccess::hasPropertyByName(const OUString& Name)
1087{
1088 return hasProperty( Name, PropertyConcept::ALL );
1089}
1090
1091// Methods from XElementAccess
1092Type ImplIntrospectionAccess::getElementType()
1093{
1094 return getXElementAccess()->getElementType();
1095}
1096
1097sal_Bool ImplIntrospectionAccess::hasElements()
1098{
1099 return getXElementAccess()->hasElements();
1100}
1101
1102// Methods from XNameAccess
1103Any ImplIntrospectionAccess::getByName(const OUString& Name)
1104{
1105 return getXNameAccess()->getByName( Name );
1106}
1107
1108Sequence< OUString > ImplIntrospectionAccess::getElementNames()
1109{
1110 return getXNameAccess()->getElementNames();
1111}
1112
1113sal_Bool ImplIntrospectionAccess::hasByName(const OUString& Name)
1114{
1115 return getXNameAccess()->hasByName( Name );
1116}
1117
1118// Methods from XNameContainer
1119void ImplIntrospectionAccess::insertByName(const OUString& Name, const Any& Element)
1120{
1121 getXNameContainer()->insertByName( Name, Element );
1122}
1123
1124void ImplIntrospectionAccess::replaceByName(const OUString& Name, const Any& Element)
1125{
1126 getXNameReplace()->replaceByName( Name, Element );
1127}
1128
1129void ImplIntrospectionAccess::removeByName(const OUString& Name)
1130{
1131 getXNameContainer()->removeByName( Name );
1132}
1133
1134// Methods from XIndexAccess
1135// Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const
1136sal_Int32 ImplIntrospectionAccess::getCount()
1137{
1138 return getXIndexAccess()->getCount();
1139}
1140
1141Any ImplIntrospectionAccess::getByIndex(sal_Int32 Index)
1142{
1143 return getXIndexAccess()->getByIndex( Index );
1144}
1145
1146// Methods from XIndexContainer
1147void ImplIntrospectionAccess::insertByIndex(sal_Int32 Index, const Any& Element)
1148{
1149 getXIndexContainer()->insertByIndex( Index, Element );
1150}
1151
1152void ImplIntrospectionAccess::replaceByIndex(sal_Int32 Index, const Any& Element)
1153{
1154 getXIndexReplace()->replaceByIndex( Index, Element );
1155}
1156
1157void ImplIntrospectionAccess::removeByIndex(sal_Int32 Index)
1158{
1159 getXIndexContainer()->removeByIndex( Index );
1160}
1161
1162// Methods from XEnumerationAccess
1163// Already in XNameAccess: virtual Reference<XIdlClass> getElementType() const;
1164Reference<XEnumeration> ImplIntrospectionAccess::createEnumeration()
1165{
1166 return getXEnumerationAccess()->createEnumeration();
1167}
1168
1169// Methods from XIdlArray
1170void ImplIntrospectionAccess::realloc(Any& array, sal_Int32 length)
1171{
1172 getXIdlArray()->realloc( array, length );
1173}
1174
1175sal_Int32 ImplIntrospectionAccess::getLen(const Any& array)
1176{
1177 return getXIdlArray()->getLen( array );
1178}
1179
1180Any ImplIntrospectionAccess::get(const Any& array, sal_Int32 index)
1181{
1182 return getXIdlArray()->get( array, index );
1183}
1184
1185void ImplIntrospectionAccess::set(Any& array, sal_Int32 index, const Any& value)
1186{
1187 getXIdlArray()->set( array, index, value );
1188}
1189
1190// Methods from XUnoTunnel
1191sal_Int64 ImplIntrospectionAccess::getSomething( const Sequence< sal_Int8 >& aIdentifier )
1192{
1193 if (Reference<XUnoTunnel> xUnoTunnel{ mxIface, css::uno::UNO_QUERY })
1194 return xUnoTunnel->getSomething(aIdentifier);
1195 return 0;
1196}
1197
1198
1199//*** Implementation of ImplIntrospectionAccess ***
1200
1201// Methods from XIntrospectionAccess
1202sal_Int32 ImplIntrospectionAccess::getSuppliedMethodConcepts()
1203{
1204 return MethodConcept::DANGEROUS |
1205 PROPERTY |
1206 LISTENER |
1207 ENUMERATION |
1208 NAMECONTAINER |
1209 INDEXCONTAINER;
1210}
1211
1212sal_Int32 ImplIntrospectionAccess::getSuppliedPropertyConcepts()
1213{
1214 return PropertyConcept::DANGEROUS |
1215 PROPERTYSET |
1216 ATTRIBUTES |
1217 METHODS;
1218}
1219
1220Property ImplIntrospectionAccess::getProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1221{
1222 Property aRet;
1223 sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1224 bool bFound = false;
1225 if( i != -1 )
1226 {
1227 sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1228 if( (PropertyConcepts & nConcept) != 0 )
1229 {
1230 aRet = mpStaticImpl->getProperties()[ i ];
1231 bFound = true;
1232 }
1233 }
1234 if( !bFound )
1235 throw NoSuchElementException(Name);
1236 return aRet;
1237}
1238
1239sal_Bool ImplIntrospectionAccess::hasProperty(const OUString& Name, sal_Int32 PropertyConcepts)
1240{
1241 sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1242 bool bRet = false;
1243 if( i != -1 )
1244 {
1245 sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts()[ i ];
1246 if( (PropertyConcepts & nConcept) != 0 )
1247 bRet = true;
1248 }
1249 return bRet;
1250}
1251
1252Sequence< Property > ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts)
1253{
1254 // If all supported concepts are required, simply pass through the sequence
1255 sal_Int32 nAllSupportedMask = PROPERTYSET |
1256 ATTRIBUTES |
1257 METHODS;
1258 if( ( PropertyConcepts & nAllSupportedMask ) == nAllSupportedMask )
1259 {
1260 return comphelper::containerToSequence(mpStaticImpl->getProperties());
1261 }
1262
1263 // Same sequence as last time?
1264 if( mnLastPropertyConcept == PropertyConcepts )
1265 {
1266 return maLastPropertySeq;
1267 }
1268
1269 // Number of properties to be delivered
1270 sal_Int32 nCount = 0;
1271
1272 // There are currently no DANGEROUS properties
1273 // if( PropertyConcepts & DANGEROUS )
1274 // nCount += mpStaticImpl->mnDangerousPropCount;
1275 if( PropertyConcepts & PROPERTYSET )
1276 nCount += mpStaticImpl->mnPropertySetPropCount;
1277 if( PropertyConcepts & ATTRIBUTES )
1278 nCount += mpStaticImpl->mnAttributePropCount;
1279 if( PropertyConcepts & METHODS )
1280 nCount += mpStaticImpl->mnMethodPropCount;
1281
1282 // Realloc sequence according to the required number
1283 maLastPropertySeq.realloc( nCount );
1284 Property* pDestProps = maLastPropertySeq.getArray();
1285
1286 // Go through all the properties and apply according to the concept
1287 const std::vector<Property>& rPropSeq = mpStaticImpl->getProperties();
1288 const std::vector<sal_Int32>& rConcepts = mpStaticImpl->getPropertyConcepts();
1289 sal_Int32 nLen = static_cast<sal_Int32>(rPropSeq.size());
1290
1291 sal_Int32 iDest = 0;
1292 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1293 {
1294 sal_Int32 nConcept = rConcepts[ i ];
1295 if( nConcept & PropertyConcepts )
1296 pDestProps[ iDest++ ] = rPropSeq[ i ];
1297 }
1298
1299 // Remember PropertyConcept representing maLastPropertySeq
1300 mnLastPropertyConcept = PropertyConcepts;
1301
1302 // Supply assembled Sequence
1303 return maLastPropertySeq;
1304}
1305
1306Reference<XIdlMethod> ImplIntrospectionAccess::getMethod(const OUString& Name, sal_Int32 MethodConcepts)
1307{
1308 Reference<XIdlMethod> xRet;
1309 sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1310 if( i != -1 )
1311 {
1312
1313 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1314 if( (MethodConcepts & nConcept) != 0 )
1315 {
1316 xRet = mpStaticImpl->getMethods()[i];
1317 }
1318 }
1319 if( !xRet.is() )
1320 throw NoSuchMethodException(Name);
1321 return xRet;
1322}
1323
1324sal_Bool ImplIntrospectionAccess::hasMethod(const OUString& Name, sal_Int32 MethodConcepts)
1325{
1326 sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1327 bool bRet = false;
1328 if( i != -1 )
1329 {
1330 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1331 if( (MethodConcepts & nConcept) != 0 )
1332 bRet = true;
1333 }
1334 return bRet;
1335}
1336
1337Sequence< Reference<XIdlMethod> > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts)
1338{
1339 // If all supported concepts are required, simply pass through the sequence
1340 sal_Int32 nAllSupportedMask = MethodConcept::DANGEROUS |
1341 PROPERTY |
1342 LISTENER |
1343 ENUMERATION |
1344 NAMECONTAINER |
1345 INDEXCONTAINER |
1347 if( ( MethodConcepts & nAllSupportedMask ) == nAllSupportedMask )
1348 {
1349 return comphelper::containerToSequence(mpStaticImpl->getMethods());
1350 }
1351
1352 // Same sequence as last time?
1353 if( mnLastMethodConcept == MethodConcepts )
1354 {
1355 return maLastMethodSeq;
1356 }
1357
1358 // Get method sequences
1359 const std::vector< Reference<XIdlMethod> >& aMethodSeq = mpStaticImpl->getMethods();
1360 sal_Int32 nLen = static_cast<sal_Int32>(aMethodSeq.size());
1361
1362 // Realloc sequence according to the required number
1363 // Unlike Properties, the number can not be determined by counters in
1364 // inspect() beforehand, since methods can belong to several concepts
1365 maLastMethodSeq.realloc( nLen );
1366 Reference<XIdlMethod>* pDestMethods = maLastMethodSeq.getArray();
1367
1368 // Go through all the methods and apply according to the concept
1369 sal_Int32 iDest = 0;
1370 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1371 {
1372 sal_Int32 nConcept = mpStaticImpl->getMethodConcepts()[ i ];
1373 if( nConcept & MethodConcepts )
1374 pDestMethods[ iDest++ ] = aMethodSeq[ i ];
1375 }
1376
1377 // Bring to the correct length
1378 maLastMethodSeq.realloc( iDest );
1379
1380 // Remember MethodConcept representing maLastMethodSeq
1381 mnLastMethodConcept = MethodConcepts;
1382
1383 // Supply assembled Sequence
1384 return maLastMethodSeq;
1385}
1386
1387Sequence< Type > ImplIntrospectionAccess::getSupportedListeners()
1388{
1389 return comphelper::containerToSequence(mpStaticImpl->getSupportedListeners());
1390}
1391
1392Reference<XInterface> SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type& rType )
1393{
1394 Reference<XInterface> xRet;
1395 if( rType == cppu::UnoType<XInterface>::get()
1407 || rType == cppu::UnoType<XIdlArray>::get()
1408 || rType == cppu::UnoType<XUnoTunnel>::get() )
1409 {
1410 queryInterface( rType ) >>= xRet;
1411 }
1412 return xRet;
1413}
1414
1415// Methods from XMaterialHolder
1416Any ImplIntrospectionAccess::getMaterial()
1417{
1418 return maInspectedObject;
1419}
1420
1421// Methods from XExactName
1422OUString ImplIntrospectionAccess::getExactName( const OUString& rApproximateName )
1423{
1424 OUString aRetStr;
1425 LowerToExactNameMap::iterator aIt =
1426 mpStaticImpl->maLowerToExactNameMap.find( rApproximateName.toAsciiLowerCase() );
1427 if (aIt != mpStaticImpl->maLowerToExactNameMap.end())
1428 aRetStr = (*aIt).second;
1429 return aRetStr;
1430}
1431
1432struct TypeKey {
1433 TypeKey(
1434 css::uno::Reference<css::beans::XPropertySetInfo> theProperties,
1435 std::vector<css::uno::Type> const & theTypes):
1436 properties(std::move(theProperties))
1437 {
1438 //TODO: Could even sort the types lexicographically first, to increase
1439 // the chance of matches between different implementations' getTypes(),
1440 // but the old scheme of using getImplementationId() would have missed
1441 // those matches, too:
1442 OUStringBuffer b(static_cast<int>(theTypes.size() * 64));
1443 for (const css::uno::Type& rType : theTypes) {
1444 b.append(rType.getTypeName()
1445 + "*"); // arbitrary delimiter not used by type grammar
1446 }
1447 types = b.makeStringAndClear();
1448 }
1449
1450 css::uno::Reference<css::beans::XPropertySetInfo> properties;
1451 OUString types;
1452};
1453
1454struct TypeKeyLess {
1455 bool operator ()(TypeKey const & key1, TypeKey const & key2) const {
1456 if (key1.properties.get() < key2.properties.get()) {
1457 return true;
1458 }
1459 if (key1.properties.get() > key2.properties.get()) {
1460 return false;
1461 }
1462 return key1.types < key2.types;
1463 }
1464};
1465
1466template<typename Key, typename Less> class Cache {
1467public:
1469 typename Map::const_iterator i(map_.find(key));
1470 if (i == map_.end()) {
1472 } else {
1473 if (i->second.hits < std::numeric_limits<unsigned>::max()) {
1474 ++i->second.hits;
1475 }
1476 assert(i->second.access.is());
1477 return i->second.access;
1478 }
1479 }
1480
1481 void insert(
1482 Key const & key,
1484 {
1485 assert(access.is());
1486 typename Map::size_type const MAX = 100;
1487 assert(map_.size() <= MAX);
1488 if (map_.size() == MAX) {
1489 typename Map::iterator del = std::min_element(map_.begin(), map_.end(),
1490 [](const typename Map::value_type& a, const typename Map::value_type& b) {
1491 return a.second.hits < b.second.hits;
1492 });
1493 map_.erase(del);
1494 }
1495 bool ins = map_.emplace(key, Data(access)).second;
1496 assert(ins); (void)ins;
1497 }
1498
1499 void clear() { map_.clear(); }
1500
1501private:
1502 struct Data {
1503 explicit Data(
1505 access(std::move(theAccess)), hits(1)
1506 {}
1507
1509 mutable unsigned hits;
1510 };
1511
1512 typedef std::map<Key, Data, Less> Map;
1513
1514 Map map_;
1515};
1516
1517typedef
1518 cppu::WeakComponentImplHelper<
1519 css::lang::XServiceInfo, css::beans::XIntrospection>
1520 Implementation_Base;
1521
1522class Implementation: private cppu::BaseMutex, public Implementation_Base {
1523public:
1524 explicit Implementation(
1525 css::uno::Reference<css::uno::XComponentContext> const & context):
1526 Implementation_Base(m_aMutex),
1527 reflection_(css::reflection::theCoreReflection::get(context))
1528 {}
1529
1530private:
1531 virtual void SAL_CALL disposing() override {
1532 osl::MutexGuard g(m_aMutex);
1533 reflection_.clear();
1534 typeCache_.clear();
1535 }
1536
1537 virtual OUString SAL_CALL getImplementationName() override
1538 { return "com.sun.star.comp.stoc.Introspection"; }
1539
1540 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
1541 { return cppu::supportsService(this, ServiceName); }
1542
1543 virtual css::uno::Sequence<OUString> SAL_CALL
1544 getSupportedServiceNames() override
1545 {
1546 Sequence<OUString> s { "com.sun.star.beans.Introspection" };
1547 return s;
1548 }
1549
1550 virtual css::uno::Reference<css::beans::XIntrospectionAccess> SAL_CALL
1551 inspect(css::uno::Any const & aObject) override;
1552
1553 css::uno::Reference<css::reflection::XIdlReflection> reflection_;
1554 Cache<TypeKey, TypeKeyLess> typeCache_;
1555};
1556
1557css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
1558 css::uno::Any const & aObject)
1559{
1560 css::uno::Reference<css::reflection::XIdlReflection> reflection;
1561 {
1562 osl::MutexGuard g(m_aMutex);
1563 if (rBHelper.bDisposed || rBHelper.bInDispose) {
1564 throw css::lang::DisposedException(
1565 getImplementationName(), getXWeak());
1566 }
1567 reflection = reflection_;
1568 }
1569 css::uno::Any aToInspectObj;
1570 css::uno::Type t;
1571 if (aObject >>= t) {
1572 css::uno::Reference<css::reflection::XIdlClass> c(
1573 reflection->forName(t.getTypeName()));
1574 if (!c.is()) {
1575 SAL_WARN("stoc", "cannot reflect type " << t.getTypeName());
1576 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1577 }
1578 aToInspectObj <<= c;
1579 } else {
1580 aToInspectObj = aObject;
1581 }
1582
1583 // Examine object
1584 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1585 if( eType != TypeClass_INTERFACE && eType != TypeClass_STRUCT && eType != TypeClass_EXCEPTION )
1586 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1587
1588 if( auto x = o3tl::tryAccess<Reference<XInterface>>(aToInspectObj) )
1589 {
1590 if( !x->is() )
1591 return css::uno::Reference<css::beans::XIntrospectionAccess>();
1592 }
1593
1594 // Pointer to possibly needed new IntrospectionAccessStatic_Impl instance
1596
1597 // Check: Is a matching access object already cached?
1598 std::vector< Reference<XIdlClass> > SupportedClassSeq;
1599 std::vector< Type > SupportedTypesSeq;
1600 Reference<XTypeProvider> xTypeProvider;
1601 Reference<XPropertySetInfo> xPropSetInfo;
1602 Reference<XPropertySet> xPropSet;
1603
1604 // Look for interfaces XTypeProvider and PropertySet
1605 if( eType == TypeClass_INTERFACE )
1606 {
1607 xTypeProvider.set( aToInspectObj, UNO_QUERY );
1608 if( xTypeProvider.is() )
1609 {
1610 SupportedTypesSeq = comphelper::sequenceToContainer<std::vector<Type>>(xTypeProvider->getTypes());
1611 } else {
1612 SAL_WARN(
1613 "stoc",
1614 "object of type \"" << aToInspectObj.getValueTypeName()
1615 << "\" lacks XTypeProvider");
1616 SupportedTypesSeq = { aToInspectObj.getValueType() };
1617 }
1618 // Now try to get the PropertySetInfo
1619 xPropSet.set( aToInspectObj, UNO_QUERY );
1620 if( xPropSet.is() )
1621 xPropSetInfo = xPropSet->getPropertySetInfo();
1622
1623 } else {
1624 SupportedTypesSeq = { aToInspectObj.getValueType() };
1625 }
1626
1627 {
1628 osl::MutexGuard g(m_aMutex);
1629 if (rBHelper.bDisposed || rBHelper.bInDispose) {
1630 throw css::lang::DisposedException(
1631 getImplementationName(), getXWeak());
1632 }
1633 TypeKey key(xPropSetInfo, SupportedTypesSeq);
1634 pAccess = typeCache_.find(key);
1635 if (pAccess.is()) {
1636 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
1637 }
1638 pAccess = new IntrospectionAccessStatic_Impl(reflection);
1639 typeCache_.insert(key, pAccess);
1640 }
1641
1642 // No access cached -> create new
1643 std::vector<Property>& rAllPropArray = pAccess->maAllPropertySeq;
1644 std::vector<Reference<XInterface>>& rInterfaces1 = pAccess->aInterfaceSeq1;
1645 std::vector<Reference<XInterface>>& rInterfaces2 = pAccess->aInterfaceSeq2;
1646 std::vector<sal_Int16>& rMapTypeArray = pAccess->maMapTypeSeq;
1647 std::vector<sal_Int32>& rPropertyConceptArray = pAccess->maPropertyConceptSeq;
1648
1649 // References to important data from pAccess
1650 sal_Int32& rPropCount = pAccess->mnPropCount;
1651 IntrospectionNameMap& rPropNameMap = pAccess->maPropertyNameMap;
1652 IntrospectionNameMap& rMethodNameMap = pAccess->maMethodNameMap;
1653 LowerToExactNameMap& rLowerToExactNameMap = pAccess->maLowerToExactNameMap;
1654
1655
1656 //*** Perform analysis ***
1657
1658 if( eType == TypeClass_INTERFACE )
1659 {
1660 size_t nTypeCount = SupportedTypesSeq.size();
1661 if( nTypeCount )
1662 {
1663 SupportedClassSeq.resize( nTypeCount );
1664
1665 for( size_t i = 0 ; i < nTypeCount ; i++ )
1666 SupportedClassSeq[i] = reflection->forName( SupportedTypesSeq[i].getTypeName() );
1667 }
1668
1669 // First look for particular interfaces that are of particular
1670 // importance to the introspection
1671
1672 // Is XPropertySet present?
1673 if( xPropSet.is() && xPropSetInfo.is() )
1674 {
1675 // Is there also a FastPropertySet?
1676 Reference<XFastPropertySet> xDummy( aToInspectObj, UNO_QUERY );
1677 bool bFast = pAccess->mbFastPropSet = xDummy.is();
1678
1679 Sequence<Property> aPropSeq = xPropSetInfo->getProperties();
1680 const Property* pProps = aPropSeq.getConstArray();
1681 sal_Int32 nLen = aPropSeq.getLength();
1682
1683 // For a FastPropertySet we must remember the original handles
1684 if( bFast )
1685 pAccess->mpOrgPropertyHandleArray.reset( new sal_Int32[ nLen ] );
1686
1687 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1688 {
1689 // Put property in its own list
1690 pAccess->checkPropertyArraysSize( rPropCount );
1691 Property& rProp = rAllPropArray[ rPropCount ];
1692 rProp = pProps[ i ];
1693
1694 if( bFast )
1695 pAccess->mpOrgPropertyHandleArray[ i ] = rProp.Handle;
1696
1697 // Enter PropCount as a handle for its own FastPropertySet
1698 rProp.Handle = rPropCount;
1699
1700 // Remember type of property
1701 rMapTypeArray[ rPropCount ] = MAP_PROPERTY_SET;
1702 rPropertyConceptArray[ rPropCount ] = PROPERTYSET;
1703 pAccess->mnPropertySetPropCount++;
1704
1705 // Enter name in hash table if not already known
1706 OUString aPropName = rProp.Name;
1707
1708 // Do we already have the name?
1709 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1710 if( aIt == rPropNameMap.end() )
1711 {
1712 // New entry in the hash table
1713 rPropNameMap[ aPropName ] = rPropCount;
1714
1715 // Maintain table for XExactName
1716 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1717 }
1718 else
1719 {
1720 SAL_WARN( "stoc", "Introspection: Property \"" <<
1721 aPropName << "\" found more than once in PropertySet" );
1722 }
1723
1724 // Adjust count
1725 rPropCount++;
1726 }
1727 }
1728
1729 // Indices in the export table
1730 sal_Int32 iAllExportedMethod = 0;
1731 sal_Int32 iAllSupportedListener = 0;
1732
1733 std::set<OUString> seen;
1734
1735 // Flag, whether XInterface methods should be recorded
1736 // (this must be done only once, allowed initially)
1737 bool bXInterfaceIsInvalid = false;
1738
1739 // Flag whether the XInterface methods have already been recorded. If
1740 // sal_True, bXInterfaceIsInvalid is activated at the end of the interface
1741 // loop, and XInterface methods are cut off thereafter.
1742 bool bFoundXInterface = false;
1743
1744 size_t nClassCount = SupportedClassSeq.size();
1745 for( size_t nIdx = 0 ; nIdx < nClassCount; nIdx++ )
1746 {
1747 Reference<XIdlClass> xImplClass2 = SupportedClassSeq[nIdx];
1748 while( xImplClass2.is() )
1749 {
1750 // Fetch interfaces from the implementation
1751 Sequence< Reference<XIdlClass> > aClassSeq = xImplClass2->getInterfaces();
1752 sal_Int32 nIfaceCount = aClassSeq.getLength();
1753
1754 aClassSeq.realloc( nIfaceCount + 1 );
1755 aClassSeq.getArray()[ nIfaceCount ] = xImplClass2;
1756
1757 for( const Reference<XIdlClass>& rxIfaceClass : std::as_const(aClassSeq) )
1758 {
1759 if (!seen.insert(rxIfaceClass->getName()).second) {
1760 continue;
1761 }
1762
1763 // 2. Register fields as properties
1764
1765 // Get fields
1766 const Sequence< Reference<XIdlField> > fields = rxIfaceClass->getFields();
1767
1768 for( const Reference<XIdlField>& xField : fields )
1769 {
1770 Reference<XIdlClass> xPropType = xField->getType();
1771
1772 // Is the property sequence big enough?
1773 pAccess->checkPropertyArraysSize( rPropCount );
1774
1775 // Enter in own property array
1776 Property& rProp = rAllPropArray[ rPropCount ];
1777 OUString aFieldName = xField->getName();
1778 rProp.Name = aFieldName;
1779 rProp.Handle = rPropCount;
1780 Type aFieldType( xPropType->getTypeClass(), xPropType->getName() );
1781 rProp.Type = aFieldType;
1782 FieldAccessMode eAccessMode = xField->getAccessMode();
1783 rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
1784 eAccessMode == FieldAccessMode_CONST)
1785 ? READONLY : 0;
1786
1787 // Enter name in hash table
1788 OUString aPropName = rProp.Name;
1789
1790 // Do we have the name already?
1791 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1792 if (aIt != rPropNameMap.end())
1793 continue;
1794
1795 // New entry in the hash table
1796 rPropNameMap[ aPropName ] = rPropCount;
1797
1798 // Maintain table for XExactName
1799 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1800
1801 // Remember field
1802 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
1803 rInterfaces1, rPropCount );
1804 rInterfaces1[ rPropCount ] = xField;
1805
1806 // Remember type of property
1807 rMapTypeArray[ rPropCount ] = MAP_FIELD;
1808 rPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
1809 pAccess->mnAttributePropCount++;
1810
1811 // Adjust count
1812 rPropCount++;
1813 }
1814
1815
1816 // 3. Methods
1817
1818 // Get and remember all methods
1819 Sequence< Reference<XIdlMethod> > methods = rxIfaceClass->getMethods();
1820 const Reference<XIdlMethod>* pSourceMethods = methods.getConstArray();
1821 sal_Int32 nSourceMethodCount = methods.getLength();
1822
1823 // 3. a) Search get/set and listener methods
1824
1825 // Create field for information about the methods, so that methods which are not
1826 // related to properties or listeners can easily be found later.
1827 // New: initialise MethodConceptArray
1828 enum MethodType
1829 {
1830 STANDARD_METHOD, // normal method, not related to properties or listeners
1831 GETSET_METHOD, // belongs to a get/set property
1832 ADD_LISTENER_METHOD, // add method of a listener interface
1833 REMOVE_LISTENER_METHOD, // remove method of a listener interface
1834 INVALID_METHOD // method whose class is not considered, e.g. XPropertySet
1835 };
1836 std::unique_ptr<MethodType[]> pMethodTypes( new MethodType[ nSourceMethodCount ] );
1837 std::unique_ptr<sal_Int32[]> pLocalMethodConcepts( new sal_Int32[ nSourceMethodCount ] );
1838 for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
1839 {
1840 pMethodTypes[ i ] = STANDARD_METHOD;
1841 pLocalMethodConcepts[ i ] = 0;
1842 }
1843
1844 for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
1845 {
1846 // Address method
1847 const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
1848 sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
1849
1850 // Fetch name
1851 OUString aMethName = rxMethod_i->getName();
1852
1853 // Catalogue methods
1854 // Filter all (?) methods of XInterface so e.g. acquire and release
1855 // can not be called from scripting
1856 OUString className(
1857 rxMethod_i->getDeclaringClass()->getName());
1858 if (className == "com.sun.star.uno.XInterface") {
1859 bFoundXInterface = true;
1860
1861 if( bXInterfaceIsInvalid )
1862 {
1863 pMethodTypes[ i ] = INVALID_METHOD;
1864 continue;
1865 }
1866 else
1867 {
1868 if( aMethName != "queryInterface" )
1869 {
1870 rMethodConcept_i |= MethodConcept::DANGEROUS;
1871 continue;
1872 }
1873 }
1874 } else if (className == "com.sun.star.uno.XAggregation")
1875 {
1876 if( aMethName == "setDelegator" )
1877 {
1878 rMethodConcept_i |= MethodConcept::DANGEROUS;
1879 continue;
1880 }
1881 } else if (className
1882 == "com.sun.star.container.XElementAccess")
1883 {
1884 rMethodConcept_i |= ( NAMECONTAINER |
1885 INDEXCONTAINER |
1886 ENUMERATION );
1887 pAccess->mbElementAccess = true;
1888 } else if (className
1889 == "com.sun.star.container.XNameContainer")
1890 {
1891 rMethodConcept_i |= NAMECONTAINER;
1892 pAccess->mbNameContainer = true;
1893 pAccess->mbNameReplace = true;
1894 pAccess->mbNameAccess = true;
1895 pAccess->mbElementAccess = true;
1896 } else if (className
1897 == "com.sun.star.container.XNameReplace")
1898 {
1899 rMethodConcept_i |= NAMECONTAINER;
1900 pAccess->mbNameReplace = true;
1901 pAccess->mbNameAccess = true;
1902 pAccess->mbElementAccess = true;
1903 } else if (className
1904 == "com.sun.star.container.XNameAccess")
1905 {
1906 rMethodConcept_i |= NAMECONTAINER;
1907 pAccess->mbNameAccess = true;
1908 pAccess->mbElementAccess = true;
1909 } else if (className
1910 == "com.sun.star.container.XIndexContainer")
1911 {
1912 rMethodConcept_i |= INDEXCONTAINER;
1913 pAccess->mbIndexContainer = true;
1914 pAccess->mbIndexReplace = true;
1915 pAccess->mbIndexAccess = true;
1916 pAccess->mbElementAccess = true;
1917 } else if (className
1918 == "com.sun.star.container.XIndexReplace")
1919 {
1920 rMethodConcept_i |= INDEXCONTAINER;
1921 pAccess->mbIndexReplace = true;
1922 pAccess->mbIndexAccess = true;
1923 pAccess->mbElementAccess = true;
1924 } else if (className
1925 == "com.sun.star.container.XIndexAccess")
1926 {
1927 rMethodConcept_i |= INDEXCONTAINER;
1928 pAccess->mbIndexAccess = true;
1929 pAccess->mbElementAccess = true;
1930 } else if (className
1931 == "com.sun.star.container.XEnumerationAccess")
1932 {
1933 rMethodConcept_i |= ENUMERATION;
1934 pAccess->mbEnumerationAccess = true;
1935 pAccess->mbElementAccess = true;
1936 } else if (className
1937 == "com.sun.star.reflection.XIdlArray")
1938 {
1939 pAccess->mbIdlArray = true;
1940 } else if (className
1941 == "com.sun.star.lang.XUnoTunnel")
1942 {
1943 pAccess->mbUnoTunnel = true;
1944 }
1945
1946 // If the name is too short, it isn't anything
1947 if( aMethName.getLength() <= 3 )
1948 continue;
1949
1950 // Is it a get method?
1951 OUString aPropName;
1952 if( aMethName.startsWith("get", &aPropName) )
1953 {
1954 // Get methods must not have any parameters
1955 Sequence< Reference<XIdlClass> > getParams = rxMethod_i->getParameterTypes();
1956 if( getParams.hasElements() )
1957 {
1958 continue;
1959 }
1960
1961 // Do we have the name already?
1962 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
1963 if (aIt != rPropNameMap.end())
1964 {
1965 /* TODO
1966 SAL_INFO("stoc",(
1967 String( "Introspection: Property \"" ) +
1968 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
1969 String( "\" found more than once" ) );
1970 */
1971 continue;
1972 }
1973
1974 // It is already at least a read-only property
1975 rMethodConcept_i |= PROPERTY;
1976
1977 pMethodTypes[i] = GETSET_METHOD;
1978 Reference<XIdlClass> xGetRetType = rxMethod_i->getReturnType();
1979
1980 // Is the property sequence big enough?
1981 pAccess->checkPropertyArraysSize( rPropCount );
1982
1983 // Write it in its property array
1984 Property& rProp = rAllPropArray[ rPropCount ];
1985 rProp.Name = aPropName;
1986 rProp.Handle = rPropCount;
1987 rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
1988 rProp.Attributes = READONLY;
1989
1990 // New entry in the hash table
1991 rPropNameMap[ aPropName ] = rPropCount;
1992
1993 // Maintain table for XExactName
1994 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
1995
1996 // Remember get method
1997 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
1998 rInterfaces1, rPropCount );
1999 rInterfaces1[ rPropCount ] = rxMethod_i;
2000
2001 // Remember type of property
2002 rMapTypeArray[ rPropCount ] = MAP_GETSET;
2003 rPropertyConceptArray[ rPropCount ] = METHODS;
2004 pAccess->mnMethodPropCount++;
2005
2006 // Search for matching set method
2007 sal_Int32 k;
2008 for( k = 0 ; k < nSourceMethodCount ; k++ )
2009 {
2010 // Address method
2011 const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k];
2012
2013 // Accept only methods that are not already assigned
2014 if( k == i || pMethodTypes[k] != STANDARD_METHOD )
2015 continue;
2016
2017 // Get name and evaluate
2018 OUString aMethName2 = rxMethod_k->getName();
2019 OUString aPropName2;
2020 if (!(aMethName2.startsWith("set", &aPropName2)
2021 && aPropName2 == aPropName))
2022 continue;
2023
2024 // A set method must return void
2025 Reference<XIdlClass> xSetRetType = rxMethod_k->getReturnType();
2026 if( xSetRetType->getTypeClass() != TypeClass_VOID )
2027 {
2028 continue;
2029 }
2030
2031 // A set method may only have one parameter
2032 Sequence< Reference<XIdlClass> > setParams = rxMethod_k->getParameterTypes();
2033 sal_Int32 nParamCount = setParams.getLength();
2034 if( nParamCount != 1 )
2035 {
2036 continue;
2037 }
2038
2039 // Next, the return type must correspond to the parameter type
2040 const Reference<XIdlClass>* pParamArray2 = setParams.getConstArray();
2041 Reference<XIdlClass> xParamType = pParamArray2[ 0 ];
2042 if( xParamType->equals( xGetRetType ) )
2043 {
2044 pLocalMethodConcepts[ k ] = PROPERTY;
2045
2046 pMethodTypes[k] = GETSET_METHOD;
2047
2048 // Delete read-only flag again
2049 rProp.Attributes &= ~READONLY;
2050
2051 // Remember set method
2052 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2053 rInterfaces2, rPropCount );
2054 rInterfaces2[ rPropCount ] = rxMethod_k;
2055 }
2056 }
2057
2058 // Adjust count
2059 rPropCount++;
2060 }
2061
2062 // Is it an add listener method?
2063 else if( aMethName.startsWith("add", &aPropName) )
2064 {
2065 // Does it end with "Listener"?
2066 OUString aListenerName;
2067 if( !aPropName.endsWith("Listener", &aListenerName) )
2068 continue;
2069
2070 // TODO: More accurate tests could still be carried out here
2071 // - Return type
2072 // - Number and type of parameters
2073
2074
2075 // Search for matching remove method, otherwise not applicable
2076 sal_Int32 k;
2077 for( k = 0 ; k < nSourceMethodCount ; k++ )
2078 {
2079 // Address method
2080 const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k];
2081
2082 // Accept only methods that are not already assigned
2083 if( k == i || pMethodTypes[k] != STANDARD_METHOD )
2084 continue;
2085
2086 // Get name and evaluate
2087 OUString aMethName2 = rxMethod_k->getName();
2088 OUString aListenerName2;
2089 if (!(aMethName2.startsWith(
2090 "remove", &aPropName)
2091 && aPropName.endsWith(
2092 "Listener", &aListenerName2)
2093 && aListenerName2 == aListenerName))
2094 continue;
2095
2096 // TODO: More accurate tests could still be carried out here
2097 // - Return type
2098 // - Number and type of parameters
2099
2100
2101 // Methods are recognised as a listener interface
2102 rMethodConcept_i |= LISTENER;
2103 pLocalMethodConcepts[ k ] |= LISTENER;
2104
2105 pMethodTypes[i] = ADD_LISTENER_METHOD;
2106 pMethodTypes[k] = REMOVE_LISTENER_METHOD;
2107 }
2108 }
2109 }
2110
2111
2112 // A set method could still exist without a corresponding get method,
2113 // this must be a write-only property
2114 for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
2115 {
2116 // Address method
2117 const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
2118
2119 // Accept only methods that are not already assigned
2120 if( pMethodTypes[i] != STANDARD_METHOD )
2121 continue;
2122
2123 // Get name
2124 OUString aMethName = rxMethod_i->getName();
2125
2126 // If the name is too short, it isn't anything
2127 if( aMethName.getLength() <= 3 )
2128 continue;
2129
2130 // Is it a set method without associated get method?
2131 OUString aPropName;
2132 if( aMethName.startsWith("set", &aPropName) )
2133 {
2134 // A set method must return void
2135 Reference<XIdlClass> xSetRetType = rxMethod_i->getReturnType();
2136 if( xSetRetType->getTypeClass() != TypeClass_VOID )
2137 {
2138 continue;
2139 }
2140
2141 // A set method may only have one parameter
2142 Sequence< Reference<XIdlClass> > setParams = rxMethod_i->getParameterTypes();
2143 sal_Int32 nParamCount = setParams.getLength();
2144 if( nParamCount != 1 )
2145 {
2146 continue;
2147 }
2148
2149 // Do we have the name already?
2150 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2151 if (aIt != rPropNameMap.end())
2152 {
2153 /* TODO:
2154 SAL_INFO("stoc",(
2155 String( "Introspection: Property \"" ) +
2156 OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2157 String( "\" found more than once" ) );
2158 */
2159 continue;
2160 }
2161
2162 // Now we know it's a write only property
2163 pLocalMethodConcepts[ i ] = PROPERTY;
2164
2165 pMethodTypes[i] = GETSET_METHOD;
2166 Reference<XIdlClass> xGetRetType = setParams.getConstArray()[0];
2167
2168 // Is the property sequence big enough?
2169 pAccess->checkPropertyArraysSize( rPropCount );
2170
2171 // Write it in its property array
2172 Property& rProp = rAllPropArray[ rPropCount ];
2173 rProp.Name = aPropName;
2174 rProp.Handle = rPropCount;
2175 rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
2176 rProp.Attributes = 0; // PROPERTY_WRITEONLY ???
2177
2178 // New entry in the hash table
2179 rPropNameMap[ aPropName ] = rPropCount;
2180
2181 // Maintain table for XExactName
2182 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2183
2184 // Remember set method
2185 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2186 rInterfaces2, rPropCount );
2187 rInterfaces2[ rPropCount ] = rxMethod_i;
2188
2189 // Remember type of property
2190 rMapTypeArray[ rPropCount ] = MAP_SETONLY;
2191 rPropertyConceptArray[ rPropCount ] = METHODS;
2192 pAccess->mnMethodPropCount++;
2193
2194 // Adjust count
2195 rPropCount++;
2196 }
2197 }
2198
2199
2200 // 4. Place methods in overall sequence
2201
2202 // How many methods in the method sequence
2203 sal_Int32 nExportedMethodCount = 0;
2204 sal_Int32 nSupportedListenerCount = 0;
2205 for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
2206 {
2207 if( pMethodTypes[ i ] != INVALID_METHOD )
2208 {
2209 nExportedMethodCount++;
2210 }
2211 if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2212 {
2213 nSupportedListenerCount++;
2214 }
2215 }
2216
2217 // Enlarge sequences in the access object accordingly
2218 pAccess->maAllMethodSeq.resize( nExportedMethodCount + iAllExportedMethod );
2219 pAccess->maMethodConceptSeq.resize( nExportedMethodCount + iAllExportedMethod );
2220 pAccess->maSupportedListenerSeq.resize( nSupportedListenerCount + iAllSupportedListener );
2221
2222 // Write in methods
2223 for( sal_Int32 i = 0 ; i < nSourceMethodCount ; i++ )
2224 {
2225 if( pMethodTypes[ i ] != INVALID_METHOD )
2226 {
2227 // Address method
2228 const Reference<XIdlMethod>& rxMethod = pSourceMethods[i];
2229
2230 // Enter name in hash table if not already known
2231 OUString aMethName2 = rxMethod->getName();
2232 IntrospectionNameMap::iterator aIt = rMethodNameMap.find( aMethName2 );
2233 if( aIt == rMethodNameMap.end() )
2234 {
2235 // Enter
2236 rMethodNameMap[ aMethName2 ] = iAllExportedMethod;
2237
2238 // Maintain table for XExactName
2239 rLowerToExactNameMap[ aMethName2.toAsciiLowerCase() ] = aMethName2;
2240 }
2241 else
2242 {
2243 sal_Int32 iHashResult = aIt->second;
2244
2245 Reference<XIdlMethod> xExistingMethod = pAccess->maAllMethodSeq[iHashResult];
2246
2247 Reference< XIdlClass > xExistingMethClass =
2248 xExistingMethod->getDeclaringClass();
2249 Reference< XIdlClass > xNewMethClass = rxMethod->getDeclaringClass();
2250 if( xExistingMethClass->equals( xNewMethClass ) )
2251 continue;
2252 }
2253
2254 pAccess->maAllMethodSeq[iAllExportedMethod] = rxMethod;
2255
2256 // If a concept has been set, is the method "normal"?
2257 sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
2258 if( !rMethodConcept_i )
2259 rMethodConcept_i = MethodConcept_NORMAL_IMPL;
2260 pAccess->maMethodConceptSeq[ iAllExportedMethod ] = rMethodConcept_i;
2261 iAllExportedMethod++;
2262 }
2263 if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2264 {
2265 // Determine class of listener
2266 const Reference<XIdlMethod>& rxMethod = pSourceMethods[i];
2267
2268 // Enter void as default class
2269 css::uno::Reference<css::reflection::XIdlClass>
2270 xListenerClass(
2271 reflection->forName(
2273 .getTypeName()));
2274 // Old: Reference<XIdlClass> xListenerClass = Void_getReflection()->getIdlClass();
2275
2276 // Option 1: Search for parameters for a listener class
2277 // Disadvantage: Superclasses should be searched recursively
2278 const Sequence< Reference<XIdlClass> > aParams = rxMethod->getParameterTypes();
2279
2280 css::uno::Reference<css::reflection::XIdlClass>
2281 xEventListenerClass(
2282 reflection->forName(
2284 css::lang::XEventListener>::get()
2285 .getTypeName()));
2286 // Old: Reference<XIdlClass> xEventListenerClass = XEventListener_getReflection()->getIdlClass();
2287 auto pParam = std::find_if(aParams.begin(), aParams.end(),
2288 [&xEventListenerClass](const Reference<XIdlClass>& rxClass) {
2289 // Are we derived from a listener?
2290 return rxClass->equals( xEventListenerClass )
2291 || isDerivedFrom( rxClass, xEventListenerClass );
2292 });
2293 if (pParam != aParams.end())
2294 {
2295 xListenerClass = *pParam;
2296 }
2297
2298 // Option 2: Unload the name of the method
2299 // Disadvantage: Does not work with test listeners, where it does not exist
2300 //aMethName = rxMethod->getName();
2301 //aListenerName = aMethName.Copy( 3, aMethName.Len()-8-3 );
2302 //Reference<XIdlClass> xListenerClass = reflection->forName( aListenerName );
2303 Type aListenerType( TypeClass_INTERFACE, xListenerClass->getName() );
2304 pAccess->maSupportedListenerSeq[ iAllSupportedListener ] = aListenerType;
2305 iAllSupportedListener++;
2306 }
2307 }
2308
2309 // When there were XInterface methods in this run,
2310 // ignore them in the future
2311 if( bFoundXInterface )
2312 bXInterfaceIsInvalid = true;
2313 }
2314
2315 // Do superclasses exist? Then continue here
2316 Sequence< Reference<XIdlClass> > aSuperClassSeq = xImplClass2->getSuperclasses();
2317
2318 // Currently only one superclass is considered
2319 if( aSuperClassSeq.getLength() >= 1 )
2320 {
2321 xImplClass2 = aSuperClassSeq.getConstArray()[0];
2322 OSL_ENSURE( xImplClass2.is(), "super class null" );
2323 }
2324 else
2325 {
2326 xImplClass2 = nullptr;
2327 }
2328 }
2329 }
2330
2331 // Apply number of exported methods and adapt Sequences
2332 // (can be different because duplicate methods are thrown
2333 // out only after the determination of nExportedMethodCount)
2334 sal_Int32& rMethCount = pAccess->mnMethCount;
2335 rMethCount = iAllExportedMethod;
2336 pAccess->maAllMethodSeq.resize( rMethCount );
2337 pAccess->maMethodConceptSeq.resize( rMethCount );
2338
2339 // Resize the property sequences
2340 pAccess->maAllPropertySeq.resize( rPropCount );
2341 pAccess->maPropertyConceptSeq.resize( rPropCount );
2342 pAccess->maMapTypeSeq.resize( rPropCount );
2343 }
2344 // Register struct fields as properties
2345 else //if( eType == TypeClass_STRUCT )
2346 {
2347 // Is it an interface or a struct?
2348 //Reference<XIdlClass> xClassRef = aToInspectObj.getReflection()->getIdlClass();
2349 css::uno::Reference<css::reflection::XIdlClass> xClassRef(
2350 reflection->forName(aToInspectObj.getValueTypeName()));
2351 if( !xClassRef.is() )
2352 {
2353 SAL_WARN( "stoc", "Can't get XIdlClass from Reflection" );
2354 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
2355 }
2356
2357 // Get fields
2358 const Sequence< Reference<XIdlField> > fields = xClassRef->getFields();
2359
2360 for( const Reference<XIdlField>& xField : fields )
2361 {
2362 Reference<XIdlClass> xPropType = xField->getType();
2363 OUString aPropName = xField->getName();
2364
2365 // Is the property sequence big enough?
2366 pAccess->checkPropertyArraysSize( rPropCount );
2367
2368 // Write it in its property array
2369 Property& rProp = rAllPropArray[ rPropCount ];
2370 rProp.Name = aPropName;
2371 rProp.Handle = rPropCount;
2372 rProp.Type = Type( xPropType->getTypeClass(), xPropType->getName() );
2373 FieldAccessMode eAccessMode = xField->getAccessMode();
2374 rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
2375 eAccessMode == FieldAccessMode_CONST)
2376 ? READONLY : 0;
2377
2378 //FieldAccessMode eAccessMode = xField->getAccessMode();
2379 //rProp.Attributes = (eAccessMode == FieldAccessMode::READONLY || eAccessMode == CONST)
2380 //? PropertyAttribute::READONLY : 0;
2381
2382 // Write name in hash table
2383 rPropNameMap[ aPropName ] = rPropCount;
2384
2385 // Maintain table for XExactName
2386 rLowerToExactNameMap[ aPropName.toAsciiLowerCase() ] = aPropName;
2387
2388 // Remember field
2389 IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq1,
2390 rInterfaces1, rPropCount );
2391 rInterfaces1[ rPropCount ] = xField;
2392
2393 // Remember type of property
2394 rMapTypeArray[ rPropCount ] = MAP_FIELD;
2395 rPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
2396 pAccess->mnAttributePropCount++;
2397
2398 // Adjust count
2399 rPropCount++;
2400 }
2401 }
2402
2403 // Set property sequence to the correct length
2404 pAccess->maAllPropertySeq.resize( pAccess->mnPropCount );
2405
2406 return new ImplIntrospectionAccess(aToInspectObj, pAccess);
2407}
2408
2409}
2410
2411extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
2413 css::uno::XComponentContext * context,
2414 css::uno::Sequence<css::uno::Any> const & arguments)
2415{
2417 arguments.hasElements(), "stoc", "unexpected singleton arguments");
2418 return cppu::acquire(new Implementation(context));
2419}
2420
2421/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
struct _ADOIndex Index
XPropertyListType t
SbMethodRef xMethod
bool is() const
int nCount
const bool READONLY
float x
Reference< XIdlReflection > mxCoreReflection
DocumentType eType
std::mutex m_aMutex
#define MAP_GETSET
#define MAP_SETONLY
#define MAP_FIELD
#define ARRAY_SIZE_STEP
#define MAP_PROPERTY_SET
#define MethodConcept_NORMAL_IMPL
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_stoc_Introspection_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &arguments)
sal_Int32 nIndex
Definition: invocation.cxx:697
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
aStr
void set(css::uno::UnoInterfaceReference const &value)
class SAL_NO_VTABLE XPropertySet
bool hasProperty(const OUString &_rName, const Reference< XPropertySet > &_rxSet)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
Type
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator &first, const OSQLColumns::const_iterator &last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual &_rCase)
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
OUString aPropName
std::enable_if<!(detail::IsDerivedReference< T >::value||detail::IsUnoSequenceType< T >::value||std::is_base_of< css::uno::XInterface, T >::value), typenamedetail::Optional< T >::type >::type tryAccess(css::uno::Any const &any)
VBAHELPER_DLLPUBLIC bool setPropertyValue(css::uno::Sequence< css::beans::PropertyValue > &aProp, const OUString &aName, const css::uno::Any &aValue)
args
bool getPropertyValue(ValueType &rValue, css::uno::Reference< css::beans::XPropertySet > const &xPropSet, OUString const &propName)
SVX_DLLPUBLIC OUString getProperty(css::uno::Reference< css::beans::XPropertyContainer > const &rxPropertyContainer, OUString const &rName)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
def inspect(obj, out)
std::map< OUString, rtl::Reference< Entity > > const & map_
PROPERTY
unsigned char sal_Bool