xref: /trunk/main/stoc/source/inspect/introspection.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_stoc.hxx"
30 
31 #include <string.h>
32 
33 // Schalter fuer Introspection-Caching
34 #ifndef OS2
35 #define USE_INTROSPECTION_CACHE
36 #endif
37 
38 #ifdef USE_INTROSPECTION_CACHE
39 #define INTROSPECTION_CACHE_MAX_SIZE 100
40 #endif
41 #include <osl/diagnose.h>
42 #include <osl/mutex.hxx>
43 #include <osl/thread.h>
44 #include <cppuhelper/queryinterface.hxx>
45 #include <cppuhelper/weak.hxx>
46 #include <cppuhelper/component.hxx>
47 #include <cppuhelper/factory.hxx>
48 #include <cppuhelper/implbase3.hxx>
49 #include <cppuhelper/typeprovider.hxx>
50 
51 #include <com/sun/star/uno/DeploymentException.hpp>
52 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
53 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
54 #include <com/sun/star/lang/XServiceInfo.hpp>
55 #include <com/sun/star/lang/XEventListener.hpp>
56 #include <com/sun/star/reflection/XIdlReflection.hpp>
57 #include <com/sun/star/reflection/XIdlClassProvider.hpp>
58 #include <com/sun/star/reflection/XIdlClass.hpp>
59 #include <com/sun/star/reflection/XIdlField2.hpp>
60 #include <com/sun/star/beans/UnknownPropertyException.hpp>
61 #include <com/sun/star/beans/Property.hpp>
62 #include <com/sun/star/beans/XPropertySet.hpp>
63 #include <com/sun/star/beans/XFastPropertySet.hpp>
64 #include <com/sun/star/beans/XIntrospection.hpp>
65 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
66 #include <com/sun/star/beans/XMaterialHolder.hpp>
67 #include <com/sun/star/beans/XExactName.hpp>
68 #include <com/sun/star/beans/PropertyAttribute.hpp>
69 #include <com/sun/star/beans/PropertyConcept.hpp>
70 #include <com/sun/star/beans/MethodConcept.hpp>
71 #include <com/sun/star/container/XNameContainer.hpp>
72 #include <com/sun/star/container/XIndexContainer.hpp>
73 #include <com/sun/star/container/XEnumerationAccess.hpp>
74 
75 #include <rtl/ustrbuf.hxx>
76 #include <rtl/ref.hxx>
77 #include <rtl/strbuf.hxx>
78 #include <hash_map>
79 
80 using namespace com::sun::star::uno;
81 using namespace com::sun::star::lang;
82 using namespace com::sun::star::reflection;
83 using namespace com::sun::star::container;
84 using namespace com::sun::star::registry;
85 using namespace com::sun::star::beans;
86 using namespace com::sun::star::beans::PropertyAttribute;
87 using namespace com::sun::star::beans::PropertyConcept;
88 using namespace com::sun::star::beans::MethodConcept;
89 using namespace cppu;
90 using namespace osl;
91 
92 #define IMPLEMENTATION_NAME "com.sun.star.comp.stoc.Introspection"
93 #define SERVICE_NAME        "com.sun.star.beans.Introspection"
94 
95 namespace stoc_inspect
96 {
97 
98 typedef WeakImplHelper3< XIntrospectionAccess, XMaterialHolder, XExactName > IntrospectionAccessHelper;
99 
100 
101 //==================================================================================================
102 
103 // Spezial-Wert fuer Method-Concept, um "normale" Funktionen kennzeichnen zu koennen
104 #define  MethodConcept_NORMAL_IMPL      0x80000000
105 
106 
107 // Methode zur Feststellung, ob eine Klasse von einer anderen abgeleitet ist
108 sal_Bool isDerivedFrom( Reference<XIdlClass> xToTestClass, Reference<XIdlClass> xDerivedFromClass )
109 {
110     Sequence< Reference<XIdlClass> > aClassesSeq = xToTestClass->getSuperclasses();
111     const Reference<XIdlClass>* pClassesArray = aClassesSeq.getConstArray();
112     sal_Int32 nSuperClassCount = aClassesSeq.getLength();
113     sal_Int32 i;
114     for( i = 0 ; i < nSuperClassCount ; i++ )
115     {
116         const Reference<XIdlClass>& rxClass = pClassesArray[i];
117         if( xDerivedFromClass->equals( rxClass ) )
118         {
119             // Treffer
120             return sal_True;
121         }
122         else
123         {
124             // Rekursiv weitersuchen
125             return isDerivedFrom( rxClass, xDerivedFromClass );
126         }
127     }
128     return sal_False;
129 }
130 
131 //========================================================================
132 
133 // *** Klassifizierung der Properties (kein enum, um Sequence verwenden zu koennen) ***
134 // Properties aus einem PropertySet-Interface
135 #define MAP_PROPERTY_SET    0
136 // Properties aus Fields
137 #define MAP_FIELD           1
138 // Properties, die durch get/set-Methoden beschrieben werden
139 #define MAP_GETSET          2
140 // Properties, die nur eine set-Methode haben
141 #define MAP_SETONLY         3
142 
143 
144 // Schrittweite, in der die Groesse der Sequences angepasst wird
145 #define ARRAY_SIZE_STEP     20
146 
147 
148 
149 //**************************************
150 //*** IntrospectionAccessStatic_Impl ***
151 //**************************************
152 // Entspricht dem alten IntrospectionAccessImpl, bildet jetzt den statischen
153 // Anteil des neuen Instanz-bezogenen ImplIntrospectionAccess
154 
155 // ACHTUNG !!! Von Hand refcounten !!!
156 
157 
158 // Hashtable fuer die Suche nach Namen
159 struct hashName_Impl
160 {
161     size_t operator()(const ::rtl::OUString Str) const
162     {
163         return (size_t)Str.hashCode();
164     }
165 };
166 
167 struct eqName_Impl
168 {
169     sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const
170     {
171         return ( Str1 == Str2 );
172     }
173 };
174 
175 typedef std::hash_map
176 <
177     ::rtl::OUString,
178     sal_Int32,
179     hashName_Impl,
180     eqName_Impl
181 >
182 IntrospectionNameMap;
183 
184 
185 // Hashtable zur Zuordnung der exakten Namen zu den zu Lower-Case
186 // konvertierten Namen, dient zur Unterst�tzung von XExactName
187 typedef std::hash_map
188 <
189     ::rtl::OUString,
190     ::rtl::OUString,
191     hashName_Impl,
192     eqName_Impl
193 >
194 LowerToExactNameMap;
195 
196 
197 class ImplIntrospectionAccess;
198 class IntrospectionAccessStatic_Impl
199 {
200     friend class ImplIntrospection;
201     friend class ImplIntrospectionAccess;
202 
203     // CoreReflection halten
204     Reference< XIdlReflection > mxCoreReflection;
205 
206     // InterfaceSequences, um Zusatz-Infos zu einer Property speichern zu koennen.
207     // z.B. das Field bei MAP_FIELD, die get/set-Methoden bei MAP_GETSET usw.
208     Sequence< Reference<XInterface> > aInterfaceSeq1;
209     Sequence< Reference<XInterface> > aInterfaceSeq2;
210 
211     // Hashtables fuer die Namen
212     IntrospectionNameMap maPropertyNameMap;
213     IntrospectionNameMap maMethodNameMap;
214     LowerToExactNameMap  maLowerToExactNameMap;
215 
216     // Sequence aller Properties, auch zum Liefern aus getProperties()
217     Sequence<Property> maAllPropertySeq;
218 
219     // Mapping der Properties auf Zugriffs-Arten
220     Sequence<sal_Int16> maMapTypeSeq;
221 
222     // Klassifizierung der gefundenen Methoden
223     Sequence<sal_Int32> maPropertyConceptSeq;
224 
225     // Anzahl der Properties
226     sal_Int32 mnPropCount;
227 
228     // Anzahl der Properties, die den jeweiligen Konzepten zugeordnet sind
229     //sal_Int32 mnDangerousPropCount;
230     sal_Int32 mnPropertySetPropCount;
231     sal_Int32 mnAttributePropCount;
232     sal_Int32 mnMethodPropCount;
233 
234     // Flag, ob ein FastPropertySet unterstuetzt wird
235     sal_Bool mbFastPropSet;
236 
237     // Original-Handles eines FastPropertySets
238     sal_Int32* mpOrgPropertyHandleArray;
239 
240     // MethodSequence, die alle Methoden aufnimmt
241     Sequence< Reference<XIdlMethod> > maAllMethodSeq;
242 
243     // Klassifizierung der gefundenen Methoden
244     Sequence<sal_Int32> maMethodConceptSeq;
245 
246     // Anzahl der Methoden
247     sal_Int32 mnMethCount;
248 
249     // Sequence der Listener, die angemeldet werden koennen
250     Sequence< Type > maSupportedListenerSeq;
251 
252     // BaseInit (soll spaeter in der Applikation erfolgen!)
253     void BaseInit( void );
254 
255     // Hilfs-Methoden zur Groessen-Anpassung der Sequences
256     void checkPropertyArraysSize
257     (
258         Property*& rpAllPropArray,
259         sal_Int16*& rpMapTypeArray,
260         sal_Int32*& rpPropertyConceptArray,
261         sal_Int32 iNextIndex
262     );
263     void checkInterfaceArraySize( Sequence< Reference<XInterface> >& rSeq, Reference<XInterface>*& rpInterfaceArray,
264         sal_Int32 iNextIndex );
265 
266     // RefCount
267     sal_Int32 nRefCount;
268 
269 
270 public:
271     IntrospectionAccessStatic_Impl( Reference< XIdlReflection > xCoreReflection_ );
272     ~IntrospectionAccessStatic_Impl()
273     {
274         delete[] mpOrgPropertyHandleArray;
275     }
276     sal_Int32 getPropertyIndex( const ::rtl::OUString& aPropertyName ) const;
277     sal_Int32 getMethodIndex( const ::rtl::OUString& aMethodName ) const;
278 
279     void acquire() { nRefCount++; }
280     void release()
281     {
282         nRefCount--;
283         if( nRefCount <= 0 )
284             delete this;
285     }
286 
287     // Methoden von XIntrospectionAccess (ALT, jetzt nur Impl)
288     void setPropertyValue(const Any& obj, const ::rtl::OUString& aPropertyName, const Any& aValue) const;
289 //  void setPropertyValue(Any& obj, const ::rtl::OUString& aPropertyName, const Any& aValue) const;
290     Any getPropertyValue(const Any& obj, const ::rtl::OUString& aPropertyName) const;
291     void setPropertyValueByIndex(const Any& obj, sal_Int32 nIndex, const Any& aValue) const;
292 //  void setPropertyValueByIndex(Any& obj, sal_Int32 nIndex, const Any& aValue) const;
293     Any getPropertyValueByIndex(const Any& obj, sal_Int32 nIndex) const;
294 
295     Sequence<Property> getProperties(void) const                        { return maAllPropertySeq; }
296     Sequence< Reference<XIdlMethod> > getMethods(void) const            { return maAllMethodSeq; }
297     Sequence< Type > getSupportedListeners(void) const                  { return maSupportedListenerSeq; }
298     Sequence<sal_Int32> getPropertyConcepts(void) const                 { return maPropertyConceptSeq; }
299     Sequence<sal_Int32> getMethodConcepts(void) const                   { return maMethodConceptSeq; }
300 };
301 
302 
303 // Ctor
304 IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlReflection > xCoreReflection_ )
305     : mxCoreReflection( xCoreReflection_ )
306 {
307     aInterfaceSeq1.realloc( ARRAY_SIZE_STEP );
308     aInterfaceSeq2.realloc( ARRAY_SIZE_STEP );
309 
310     // Property-Daten
311     maAllPropertySeq.realloc( ARRAY_SIZE_STEP );
312     maMapTypeSeq.realloc( ARRAY_SIZE_STEP );
313     maPropertyConceptSeq.realloc( ARRAY_SIZE_STEP );
314 
315     mbFastPropSet = sal_False;
316     mpOrgPropertyHandleArray = NULL;
317 
318     mnPropCount = 0;
319     //mnDangerousPropCount = 0;
320     mnPropertySetPropCount = 0;
321     mnAttributePropCount = 0;
322     mnMethodPropCount = 0;
323 
324     // Method-Daten
325     mnMethCount = 0;
326 
327     // Eigenens RefCounting
328     nRefCount = 0;
329 }
330 
331 // Von Hand refcounten !!!
332 
333 
334 sal_Int32 IntrospectionAccessStatic_Impl::getPropertyIndex( const ::rtl::OUString& aPropertyName ) const
335 {
336     sal_Int32 iHashResult = -1;
337     IntrospectionAccessStatic_Impl* pThis = (IntrospectionAccessStatic_Impl*)this;
338     IntrospectionNameMap::iterator aIt = pThis->maPropertyNameMap.find( aPropertyName );
339     if( !( aIt == pThis->maPropertyNameMap.end() ) )
340         iHashResult = (*aIt).second;
341     return iHashResult;
342 }
343 
344 sal_Int32 IntrospectionAccessStatic_Impl::getMethodIndex( const ::rtl::OUString& aMethodName ) const
345 {
346     sal_Int32 iHashResult = -1;
347     IntrospectionAccessStatic_Impl* pThis = (IntrospectionAccessStatic_Impl*)this;
348     IntrospectionNameMap::iterator aIt = pThis->maMethodNameMap.find( aMethodName );
349     if( !( aIt == pThis->maMethodNameMap.end() ) )
350     {
351         iHashResult = (*aIt).second;
352     }
353     // #95159 Check if full qualified name matches
354     else
355     {
356         sal_Int32 nSearchFrom = aMethodName.getLength();
357         nSearchFrom = aMethodName.getLength();
358         while( true )
359         {
360             // Strategy: Search back until the first '_' is found
361             sal_Int32 nFound = aMethodName.lastIndexOf( '_', nSearchFrom );
362             if( nFound == -1 )
363                 break;
364 
365             ::rtl::OUString aPureMethodName = aMethodName.copy( nFound + 1 );
366 
367             aIt = pThis->maMethodNameMap.find( aPureMethodName );
368             if( !( aIt == pThis->maMethodNameMap.end() ) )
369             {
370                 // Check if it can be a type?
371                 // Problem: Does not work if package names contain _ ?!
372                 ::rtl::OUString aStr = aMethodName.copy( 0, nFound );
373                 ::rtl::OUString aTypeName = aStr.replace( '_', '.' );
374                 Reference< XIdlClass > xClass = mxCoreReflection->forName( aTypeName );
375                 if( xClass.is() )
376                 {
377                     // If this is a valid class it could be the right method
378 
379                     // Could be the right method, type has to be checked
380                     iHashResult = (*aIt).second;
381 
382                     const Reference<XIdlMethod>* pMethods = maAllMethodSeq.getConstArray();
383                     const Reference<XIdlMethod> xMethod = pMethods[ iHashResult ];
384 
385                     Reference< XIdlClass > xMethClass = xMethod->getDeclaringClass();
386                     if( xClass->equals( xMethClass ) )
387                     {
388                         break;
389                     }
390                     else
391                     {
392                         iHashResult = -1;
393 
394                         // Could also be another method with the same name
395                         // Iterate over all methods
396                         sal_Int32 nLen = maAllMethodSeq.getLength();
397                         for( int i = 0 ; i < nLen ; ++i )
398                         {
399                             const Reference<XIdlMethod> xMethod2 = pMethods[ i ];
400 
401                             ::rtl::OUString aTestClassName = xMethod2->getDeclaringClass()->getName();
402                             ::rtl::OUString aTestMethodName = xMethod2->getName();
403 
404                             if( xMethod2->getName() == aPureMethodName )
405                             {
406                                 Reference< XIdlClass > xMethClass2 = xMethod2->getDeclaringClass();
407 
408                                 if( xClass->equals( xMethClass2 ) )
409                                 {
410                                     iHashResult = i;
411                                     break;
412                                 }
413                             }
414                         }
415 
416                         if( iHashResult != -1 )
417                             break;
418                     }
419                 }
420             }
421 
422             nSearchFrom = nFound - 1;
423             if( nSearchFrom < 0 )
424                 break;
425         }
426     }
427     return iHashResult;
428 }
429 
430 void IntrospectionAccessStatic_Impl::setPropertyValue( const Any& obj, const ::rtl::OUString& aPropertyName, const Any& aValue ) const
431 //void IntrospectionAccessStatic_Impl::setPropertyValue( Any& obj, const ::rtl::OUString& aPropertyName, const Any& aValue ) const
432 {
433     sal_Int32 i = getPropertyIndex( aPropertyName );
434     if( i != -1 )
435         setPropertyValueByIndex( obj, (sal_Int32)i, aValue );
436     else
437         throw UnknownPropertyException();
438 }
439 
440 void IntrospectionAccessStatic_Impl::setPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
441 //void IntrospectionAccessStatic_Impl::setPropertyValueByIndex( Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const
442 {
443     // Handelt es sich bei dem uebergebenen Objekt ueberhaupt um was passendes?
444     TypeClass eObjType = obj.getValueType().getTypeClass();
445 
446     Reference<XInterface> xInterface;
447     if( eObjType == TypeClass_INTERFACE )
448     {
449         xInterface = *( Reference<XInterface>*)obj.getValue();
450     }
451     else if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) )
452     {
453         throw IllegalArgumentException();
454     }
455 
456     // Flags pruefen
457     const Property* pProps = maAllPropertySeq.getConstArray();
458     if( (pProps[ nSequenceIndex ].Attributes & READONLY) != 0 )
459     {
460         throw UnknownPropertyException();
461     }
462 
463     const sal_Int16* pMapTypeArray = maMapTypeSeq.getConstArray();
464     switch( pMapTypeArray[ nSequenceIndex ] )
465     {
466         case MAP_PROPERTY_SET:
467         {
468             // Property besorgen
469             const Property& rProp = maAllPropertySeq.getConstArray()[ nSequenceIndex ];
470 
471             // Interface-Parameter auf den richtigen Typ bringen
472             sal_Bool bUseCopy = sal_False;
473             Any aRealValue;
474 
475             TypeClass eValType = aValue.getValueType().getTypeClass();
476             if( eValType == TypeClass_INTERFACE )
477             {
478                 Type aPropType = rProp.Type;
479                 ::rtl::OUString aTypeName( aPropType.getTypeName() );
480                 Reference< XIdlClass > xPropClass = mxCoreReflection->forName( aTypeName );
481                 //Reference<XIdlClass> xPropClass = rProp.Type;
482                 if( xPropClass.is() && xPropClass->getTypeClass() == TypeClass_INTERFACE )
483                 {
484                     Reference<XInterface> valInterface = *(Reference<XInterface>*)aValue.getValue();
485                     if( valInterface.is() )
486                     {
487                         //Any queryInterface( const Type& rType );
488                         aRealValue = valInterface->queryInterface( aPropType );
489                         if( aRealValue.hasValue() )
490                             bUseCopy = sal_True;
491                     }
492                 }
493             }
494 
495             // Haben wir ein FastPropertySet und ein gueltiges Handle?
496             // ACHTUNG: An dieser Stelle wird ausgenutzt, dass das PropertySet
497             // zu Beginn des Introspection-Vorgangs abgefragt wird.
498             sal_Int32 nOrgHandle;
499             if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
500             {
501                 // PropertySet-Interface holen
502                 Reference<XFastPropertySet> xFastPropSet =
503                     Reference<XFastPropertySet>::query( xInterface );
504                 if( xFastPropSet.is() )
505                 {
506                     xFastPropSet->setFastPropertyValue( nOrgHandle, bUseCopy ? aRealValue : aValue );
507                 }
508                 else
509                 {
510                     // throw UnknownPropertyException
511                 }
512             }
513             // sonst eben das normale nehmen
514             else
515             {
516                 // PropertySet-Interface holen
517                 Reference<XPropertySet> xPropSet =
518                     Reference<XPropertySet>::query( xInterface );
519                 if( xPropSet.is() )
520                 {
521                     xPropSet->setPropertyValue( rProp.Name, bUseCopy ? aRealValue : aValue );
522                 }
523                 else
524                 {
525                     // throw UnknownPropertyException
526                 }
527             }
528         }
529         break;
530 
531         case MAP_FIELD:
532         {
533             Reference<XIdlField> xField = (XIdlField*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get());
534             Reference<XIdlField2> xField2(xField, UNO_QUERY);
535             if( xField2.is() )
536             {
537                 xField2->set( (Any&)obj, aValue );
538                 // IllegalArgumentException
539                 // NullPointerException
540             } else
541             if( xField.is() )
542             {
543                 xField->set( obj, aValue );
544                 // IllegalArgumentException
545                 // NullPointerException
546             }
547             else
548             {
549                 // throw IllegalArgumentException();
550             }
551         }
552         break;
553 
554         case MAP_GETSET:
555         case MAP_SETONLY:
556         {
557             // set-Methode holen
558             Reference<XIdlMethod> xMethod = (XIdlMethod*)(aInterfaceSeq2.getConstArray()[ nSequenceIndex ].get());
559             if( xMethod.is() )
560             {
561                 Sequence<Any> args( 1 );
562                 args.getArray()[0] = aValue;
563                 xMethod->invoke( obj, args );
564             }
565             else
566             {
567                 // throw IllegalArgumentException();
568             }
569         }
570         break;
571     }
572 }
573 
574 Any IntrospectionAccessStatic_Impl::getPropertyValue( const Any& obj, const ::rtl::OUString& aPropertyName ) const
575 {
576     sal_Int32 i = getPropertyIndex( aPropertyName );
577     if( i != -1 )
578         return getPropertyValueByIndex( obj, i );
579 
580     throw UnknownPropertyException();
581 }
582 
583 Any IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex) const
584 {
585     Any aRet;
586 
587     // Handelt es sich bei dem uebergebenen Objekt ueberhaupt um was passendes?
588     TypeClass eObjType = obj.getValueType().getTypeClass();
589 
590     Reference<XInterface> xInterface;
591     if( eObjType == TypeClass_INTERFACE )
592     {
593         xInterface = *(Reference<XInterface>*)obj.getValue();
594     }
595     else if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) )
596     {
597         // throw IllegalArgumentException();
598         return aRet;
599     }
600 
601     const sal_Int16* pMapTypeArray = maMapTypeSeq.getConstArray();
602     switch( pMapTypeArray[ nSequenceIndex ] )
603     {
604         case MAP_PROPERTY_SET:
605         {
606             // Property besorgen
607             const Property& rProp = maAllPropertySeq.getConstArray()[ nSequenceIndex ];
608 
609             // Haben wir ein FastPropertySet und ein gueltiges Handle?
610             // ACHTUNG: An dieser Stelle wird ausgenutzt, dass das PropertySet
611             // zu Beginn des Introspection-Vorgangs abgefragt wird.
612             sal_Int32 nOrgHandle;
613             if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
614             {
615                 // PropertySet-Interface holen
616                 Reference<XFastPropertySet> xFastPropSet =
617                     Reference<XFastPropertySet>::query( xInterface );
618                 if( xFastPropSet.is() )
619                 {
620                     aRet = xFastPropSet->getFastPropertyValue( nOrgHandle);
621                 }
622                 else
623                 {
624                     // throw UnknownPropertyException
625                     return aRet;
626                 }
627             }
628             // sonst eben das normale nehmen
629             else
630             {
631                 // PropertySet-Interface holen
632                 Reference<XPropertySet> xPropSet =
633                     Reference<XPropertySet>::query( xInterface );
634                 if( xPropSet.is() )
635                 {
636                     aRet = xPropSet->getPropertyValue( rProp.Name );
637                 }
638                 else
639                 {
640                     // throw UnknownPropertyException
641                     return aRet;
642                 }
643             }
644         }
645         break;
646 
647         case MAP_FIELD:
648         {
649             Reference<XIdlField> xField = (XIdlField*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get());
650             if( xField.is() )
651             {
652                 aRet = xField->get( obj );
653                 // IllegalArgumentException
654                 // NullPointerException
655             }
656             else
657             {
658                 // throw IllegalArgumentException();
659                 return aRet;
660             }
661         }
662         break;
663 
664         case MAP_GETSET:
665         {
666             // get-Methode holen
667             Reference<XIdlMethod> xMethod = (XIdlMethod*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get());
668             if( xMethod.is() )
669             {
670                 Sequence<Any> args;
671                 aRet = xMethod->invoke( obj, args );
672             }
673             else
674             {
675                 // throw IllegalArgumentException();
676                 return aRet;
677             }
678         }
679         break;
680 
681         case MAP_SETONLY:
682             // get-Methode gibt es nicht
683             // throw WriteOnlyPropertyException();
684             return aRet;
685     }
686     return aRet;
687 }
688 
689 
690 // Hilfs-Methoden zur Groessen-Anpassung der Sequences
691 void IntrospectionAccessStatic_Impl::checkPropertyArraysSize
692 (
693     Property*& rpAllPropArray,
694     sal_Int16*& rpMapTypeArray,
695     sal_Int32*& rpPropertyConceptArray,
696     sal_Int32 iNextIndex
697 )
698 {
699     sal_Int32 nLen = maAllPropertySeq.getLength();
700     if( iNextIndex >= nLen )
701     {
702         maAllPropertySeq.realloc( nLen + ARRAY_SIZE_STEP );
703         rpAllPropArray = maAllPropertySeq.getArray();
704 
705         maMapTypeSeq.realloc( nLen + ARRAY_SIZE_STEP );
706         rpMapTypeArray = maMapTypeSeq.getArray();
707 
708         maPropertyConceptSeq.realloc( nLen + ARRAY_SIZE_STEP );
709         rpPropertyConceptArray = maPropertyConceptSeq.getArray();
710     }
711 }
712 
713 void IntrospectionAccessStatic_Impl::checkInterfaceArraySize( Sequence< Reference<XInterface> >& rSeq,
714     Reference<XInterface>*& rpInterfaceArray, sal_Int32 iNextIndex )
715 {
716     sal_Int32 nLen = rSeq.getLength();
717     if( iNextIndex >= nLen )
718     {
719         // Neue Groesse mit ARRAY_SIZE_STEP abgleichen
720         sal_Int32 nMissingSize = iNextIndex - nLen + 1;
721         sal_Int32 nSteps = nMissingSize / ARRAY_SIZE_STEP + 1;
722         sal_Int32 nNewSize = nLen + nSteps * ARRAY_SIZE_STEP;
723 
724         rSeq.realloc( nNewSize );
725         rpInterfaceArray = rSeq.getArray();
726     }
727 }
728 
729 
730 //*******************************
731 //*** ImplIntrospectionAccess ***
732 //*******************************
733 
734 // Neue Impl-Klasse im Rahmen der Introspection-Umstellung auf Instanz-gebundene
735 // Introspection mit Property-Zugriff ueber XPropertySet. Die alte Klasse
736 // ImplIntrospectionAccess lebt als IntrospectionAccessStatic_Impl
737 class ImplIntrospectionAccess : public IntrospectionAccessHelper
738 {
739     friend class ImplIntrospection;
740 
741     // Untersuchtes Objekt
742     Any maInspectedObject;
743 
744     // Als Interface
745     Reference<XInterface> mxIface;
746 
747     // Statische Daten der Introspection
748     IntrospectionAccessStatic_Impl* mpStaticImpl;
749 
750     // Adapter-Implementation
751     WeakReference< XInterface > maAdapter;
752 
753     // Letzte Sequence, die bei getProperties geliefert wurde (Optimierung)
754     Sequence<Property> maLastPropertySeq;
755     sal_Int32 mnLastPropertyConcept;
756 
757     // Letzte Sequence, die bei getMethods geliefert wurde (Optimierung)
758     Sequence<Reference<XIdlMethod> > maLastMethodSeq;
759     sal_Int32 mnLastMethodConcept;
760 
761 public:
762     ImplIntrospectionAccess( const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ );
763     ~ImplIntrospectionAccess();
764 
765     // Methoden von XIntrospectionAccess
766     virtual sal_Int32 SAL_CALL getSuppliedMethodConcepts(void)
767         throw( RuntimeException );
768     virtual sal_Int32 SAL_CALL getSuppliedPropertyConcepts(void)
769         throw( RuntimeException );
770     virtual Property SAL_CALL getProperty(const ::rtl::OUString& Name, sal_Int32 PropertyConcepts)
771         throw( NoSuchElementException, RuntimeException );
772     virtual sal_Bool SAL_CALL hasProperty(const ::rtl::OUString& Name, sal_Int32 PropertyConcepts)
773         throw( RuntimeException );
774     virtual Sequence< Property > SAL_CALL getProperties(sal_Int32 PropertyConcepts)
775         throw( RuntimeException );
776     virtual Reference<XIdlMethod> SAL_CALL getMethod(const ::rtl::OUString& Name, sal_Int32 MethodConcepts)
777         throw( NoSuchMethodException, RuntimeException );
778     virtual sal_Bool SAL_CALL hasMethod(const ::rtl::OUString& Name, sal_Int32 MethodConcepts)
779         throw( RuntimeException );
780     virtual Sequence< Reference<XIdlMethod> > SAL_CALL getMethods(sal_Int32 MethodConcepts)
781         throw( RuntimeException );
782     virtual Sequence< Type > SAL_CALL getSupportedListeners(void)
783         throw( RuntimeException );
784     using OWeakObject::queryAdapter;
785     virtual Reference<XInterface> SAL_CALL queryAdapter( const Type& rType )
786         throw( IllegalTypeException, RuntimeException );
787 
788     // Methoden von XMaterialHolder
789     virtual Any SAL_CALL getMaterial(void) throw(RuntimeException);
790 
791     // Methoden von XExactName
792     virtual ::rtl::OUString SAL_CALL getExactName( const ::rtl::OUString& rApproximateName ) throw( RuntimeException );
793 };
794 
795 ImplIntrospectionAccess::ImplIntrospectionAccess
796     ( const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ )
797         : maInspectedObject( obj ), mpStaticImpl( pStaticImpl_ ), maAdapter()
798 {
799     mpStaticImpl->acquire();
800 
801     // Objekt als Interface merken, wenn moeglich
802     TypeClass eType = maInspectedObject.getValueType().getTypeClass();
803     if( eType == TypeClass_INTERFACE )
804         mxIface = *(Reference<XInterface>*)maInspectedObject.getValue();
805 
806     mnLastPropertyConcept = -1;
807     mnLastMethodConcept = -1;
808 }
809 
810 ImplIntrospectionAccess::~ImplIntrospectionAccess()
811 {
812     mpStaticImpl->release();
813 }
814 
815 
816 //*******************************
817 //*** ImplIntrospectionAdapter ***
818 //*******************************
819 
820 // Neue Impl-Klasse im Rahmen der Introspection-Umstellung auf Instanz-gebundene
821 // Introspection mit Property-Zugriff ueber XPropertySet. Die alte Klasse
822 // ImplIntrospectionAccess lebt als IntrospectionAccessStatic_Impl
823 class ImplIntrospectionAdapter :
824     public XPropertySet, public XFastPropertySet, public XPropertySetInfo,
825     public XNameContainer, public XIndexContainer,
826     public XEnumerationAccess, public  XIdlArray,
827     public OWeakObject
828 {
829     // Parent-Objekt
830     ::rtl::Reference< ImplIntrospectionAccess > mpAccess;
831 
832     // Untersuchtes Objekt
833     const Any& mrInspectedObject;
834 
835     // Statische Daten der Introspection
836     IntrospectionAccessStatic_Impl* mpStaticImpl;
837 
838     // Objekt als Interface
839     Reference<XInterface> mxIface;
840 
841     // Original-Interfaces des Objekts
842     Reference<XElementAccess>       mxObjElementAccess;
843     Reference<XNameContainer>       mxObjNameContainer;
844     Reference<XNameAccess>          mxObjNameAccess;
845     Reference<XIndexAccess>         mxObjIndexAccess;
846     Reference<XIndexContainer>      mxObjIndexContainer;
847     Reference<XEnumerationAccess>   mxObjEnumerationAccess;
848     Reference<XIdlArray>            mxObjIdlArray;
849 
850 public:
851     ImplIntrospectionAdapter( ImplIntrospectionAccess* pAccess_,
852         const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ );
853     ~ImplIntrospectionAdapter();
854 
855     // Methoden von XInterface
856     virtual Any SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException );
857     virtual void        SAL_CALL acquire() throw() { OWeakObject::acquire(); }
858     virtual void        SAL_CALL release() throw() { OWeakObject::release(); }
859 
860     // Methoden von XPropertySet
861     virtual Reference<XPropertySetInfo> SAL_CALL getPropertySetInfo() throw( RuntimeException );
862     virtual void SAL_CALL setPropertyValue(const ::rtl::OUString& aPropertyName, const Any& aValue)
863         throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException );
864     virtual Any SAL_CALL getPropertyValue(const ::rtl::OUString& aPropertyName)
865         throw( UnknownPropertyException, WrappedTargetException, RuntimeException );
866     virtual void SAL_CALL addPropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
867         throw( UnknownPropertyException, WrappedTargetException, RuntimeException );
868     virtual void SAL_CALL removePropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
869         throw( UnknownPropertyException, WrappedTargetException, RuntimeException );
870     virtual void SAL_CALL addVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
871         throw( UnknownPropertyException, WrappedTargetException, RuntimeException );
872     virtual void SAL_CALL removeVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
873         throw( UnknownPropertyException, WrappedTargetException, RuntimeException );
874 
875     // Methoden von XFastPropertySet
876     virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const Any& aValue)
877         throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException );
878     virtual Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle)
879         throw( UnknownPropertyException, WrappedTargetException, RuntimeException );
880 
881     // Methoden von XPropertySetInfo
882     virtual Sequence< Property > SAL_CALL getProperties(void) throw( RuntimeException );
883     virtual Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException );
884     virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException );
885 
886     // Methoden von XElementAccess
887     virtual Type SAL_CALL getElementType(void) throw( RuntimeException );
888     virtual sal_Bool SAL_CALL hasElements(void) throw( RuntimeException );
889 
890     // Methoden von XNameAccess
891     virtual Any SAL_CALL getByName(const ::rtl::OUString& Name)
892         throw( NoSuchElementException, WrappedTargetException, RuntimeException );
893     virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames(void) throw( RuntimeException );
894     virtual sal_Bool SAL_CALL hasByName(const ::rtl::OUString& Name) throw( RuntimeException );
895 
896     // Methoden von XNameContainer
897     virtual void SAL_CALL insertByName(const ::rtl::OUString& Name, const Any& Element)
898         throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException );
899     virtual void SAL_CALL replaceByName(const ::rtl::OUString& Name, const Any& Element)
900         throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException );
901     virtual void SAL_CALL removeByName(const ::rtl::OUString& Name)
902         throw( NoSuchElementException, WrappedTargetException, RuntimeException );
903 
904     // Methoden von XIndexAccess
905     virtual sal_Int32 SAL_CALL getCount(void) throw( RuntimeException );
906     virtual Any SAL_CALL getByIndex(sal_Int32 Index)
907         throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException );
908 
909     // Methoden von XIndexContainer
910     virtual void SAL_CALL insertByIndex(sal_Int32 Index, const Any& Element)
911         throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException );
912     virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element)
913         throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException );
914     virtual void SAL_CALL removeByIndex(sal_Int32 Index)
915         throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException );
916 
917     // Methoden von XEnumerationAccess
918     virtual Reference<XEnumeration> SAL_CALL createEnumeration(void) throw( RuntimeException );
919 
920     // Methoden von XIdlArray
921     virtual void SAL_CALL realloc(Any& array, sal_Int32 length)
922         throw( IllegalArgumentException, RuntimeException );
923     virtual sal_Int32 SAL_CALL getLen(const Any& array) throw( IllegalArgumentException, RuntimeException );
924     virtual Any SAL_CALL get(const Any& array, sal_Int32 index)
925         throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException );
926     virtual void SAL_CALL set(Any& array, sal_Int32 index, const Any& value)
927         throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException );
928 };
929 
930 ImplIntrospectionAdapter::ImplIntrospectionAdapter( ImplIntrospectionAccess* pAccess_,
931     const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ )
932         : mpAccess( pAccess_), mrInspectedObject( obj ), mpStaticImpl( pStaticImpl_ )
933 {
934     mpStaticImpl->acquire();
935 
936     // Objekt als Interfaceholen
937     TypeClass eType = mrInspectedObject.getValueType().getTypeClass();
938     if( eType == TypeClass_INTERFACE )
939     {
940         mxIface = *( Reference< XInterface >*)mrInspectedObject.getValue();
941 
942         mxObjElementAccess = Reference<XElementAccess>::query( mxIface );
943         mxObjNameAccess = Reference<XNameAccess>::query( mxIface );
944         mxObjNameContainer = Reference<XNameContainer>::query( mxIface );
945         mxObjIndexAccess = Reference<XIndexAccess>::query( mxIface );
946         mxObjIndexContainer = Reference<XIndexContainer>::query( mxIface );
947         mxObjEnumerationAccess = Reference<XEnumerationAccess>::query( mxIface );
948         mxObjIdlArray = Reference<XIdlArray>::query( mxIface );
949     }
950 }
951 
952 ImplIntrospectionAdapter::~ImplIntrospectionAdapter()
953 {
954     mpStaticImpl->release();
955 }
956 
957 // Methoden von XInterface
958 Any SAL_CALL ImplIntrospectionAdapter::queryInterface( const Type& rType )
959     throw( RuntimeException )
960 {
961     Any aRet( ::cppu::queryInterface(
962         rType,
963         static_cast< XPropertySet * >( this ),
964         static_cast< XFastPropertySet * >( this ),
965         static_cast< XPropertySetInfo * >( this ) ) );
966     if( !aRet.hasValue() )
967         aRet = OWeakObject::queryInterface( rType );
968 
969     if( !aRet.hasValue() )
970     {
971         // Wrapper fuer die Objekt-Interfaces
972         if(   ( mxObjElementAccess.is() && (aRet = ::cppu::queryInterface
973                     ( rType, static_cast< XElementAccess* >( static_cast< XNameAccess* >( this ) ) ) ).hasValue() )
974             || ( mxObjNameAccess.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() )
975             || ( mxObjNameContainer.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() )
976             || ( mxObjIndexAccess.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() )
977             || ( mxObjIndexContainer.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() )
978             || ( mxObjEnumerationAccess .is() && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() )
979             || ( mxObjIdlArray.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() )
980           )
981         {
982         }
983     }
984     return aRet;
985 }
986 
987 
988 //***************************************************
989 //*** Implementation von ImplIntrospectionAdapter ***
990 //***************************************************
991 
992 // Methoden von XPropertySet
993 Reference<XPropertySetInfo> ImplIntrospectionAdapter::getPropertySetInfo(void)
994     throw( RuntimeException )
995 {
996     return (XPropertySetInfo *)this;
997 }
998 
999 void ImplIntrospectionAdapter::setPropertyValue(const ::rtl::OUString& aPropertyName, const Any& aValue)
1000     throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException )
1001 {
1002     mpStaticImpl->setPropertyValue( mrInspectedObject, aPropertyName, aValue );
1003 }
1004 
1005 Any ImplIntrospectionAdapter::getPropertyValue(const ::rtl::OUString& aPropertyName)
1006     throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
1007 {
1008     return mpStaticImpl->getPropertyValue( mrInspectedObject, aPropertyName );
1009 }
1010 
1011 void ImplIntrospectionAdapter::addPropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
1012     throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
1013 {
1014     if( mxIface.is() )
1015     {
1016         Reference<XPropertySet> xPropSet =
1017             Reference<XPropertySet>::query( mxIface );
1018         //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1019         if( xPropSet.is() )
1020             xPropSet->addPropertyChangeListener(aPropertyName, aListener);
1021     }
1022 }
1023 
1024 void ImplIntrospectionAdapter::removePropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
1025     throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
1026 {
1027     if( mxIface.is() )
1028     {
1029         Reference<XPropertySet> xPropSet =
1030             Reference<XPropertySet>::query( mxIface );
1031         //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1032         if( xPropSet.is() )
1033             xPropSet->removePropertyChangeListener(aPropertyName, aListener);
1034     }
1035 }
1036 
1037 void ImplIntrospectionAdapter::addVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1038     throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
1039 {
1040     if( mxIface.is() )
1041     {
1042         Reference<XPropertySet> xPropSet =
1043             Reference<XPropertySet>::query( mxIface );
1044         //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY );
1045         if( xPropSet.is() )
1046             xPropSet->addVetoableChangeListener(aPropertyName, aListener);
1047     }
1048 }
1049 
1050 void ImplIntrospectionAdapter::removeVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
1051     throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
1052 {
1053     if( mxIface.is() )
1054     {
1055         Reference<XPropertySet> xPropSet =
1056             Reference<XPropertySet>::query( mxIface );
1057         if( xPropSet.is() )
1058             xPropSet->removeVetoableChangeListener(aPropertyName, aListener);
1059     }
1060 }
1061 
1062 
1063 // Methoden von XFastPropertySet
1064 void ImplIntrospectionAdapter::setFastPropertyValue(sal_Int32, const Any&)
1065     throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException )
1066 {
1067 }
1068 
1069 Any ImplIntrospectionAdapter::getFastPropertyValue(sal_Int32)
1070     throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
1071 {
1072     return Any();
1073 }
1074 
1075 // Methoden von XPropertySetInfo
1076 Sequence< Property > ImplIntrospectionAdapter::getProperties(void) throw( RuntimeException )
1077 {
1078     return mpStaticImpl->getProperties();
1079 }
1080 
1081 Property ImplIntrospectionAdapter::getPropertyByName(const ::rtl::OUString& Name)
1082     throw( RuntimeException )
1083 {
1084     return mpAccess->getProperty( Name, PropertyConcept::ALL );
1085 }
1086 
1087 sal_Bool ImplIntrospectionAdapter::hasPropertyByName(const ::rtl::OUString& Name)
1088     throw( RuntimeException )
1089 {
1090     return mpAccess->hasProperty( Name, PropertyConcept::ALL );
1091 }
1092 
1093 // Methoden von XElementAccess
1094 Type ImplIntrospectionAdapter::getElementType(void) throw( RuntimeException )
1095 {
1096     return mxObjElementAccess->getElementType();
1097 }
1098 
1099 sal_Bool ImplIntrospectionAdapter::hasElements(void) throw( RuntimeException )
1100 {
1101     return mxObjElementAccess->hasElements();
1102 }
1103 
1104 // Methoden von XNameAccess
1105 Any ImplIntrospectionAdapter::getByName(const ::rtl::OUString& Name)
1106     throw( NoSuchElementException, WrappedTargetException, RuntimeException )
1107 {
1108     return mxObjNameAccess->getByName( Name );
1109 }
1110 
1111 Sequence< ::rtl::OUString > ImplIntrospectionAdapter::getElementNames(void)
1112     throw( RuntimeException )
1113 {
1114     return mxObjNameAccess->getElementNames();
1115 }
1116 
1117 sal_Bool ImplIntrospectionAdapter::hasByName(const ::rtl::OUString& Name)
1118     throw( RuntimeException )
1119 {
1120     return mxObjNameAccess->hasByName( Name );
1121 }
1122 
1123 // Methoden von XNameContainer
1124 void ImplIntrospectionAdapter::insertByName(const ::rtl::OUString& Name, const Any& Element)
1125     throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException )
1126 {
1127     mxObjNameContainer->insertByName( Name, Element );
1128 }
1129 
1130 void ImplIntrospectionAdapter::replaceByName(const ::rtl::OUString& Name, const Any& Element)
1131     throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException )
1132 {
1133     mxObjNameContainer->replaceByName( Name, Element );
1134 }
1135 
1136 void ImplIntrospectionAdapter::removeByName(const ::rtl::OUString& Name)
1137     throw( NoSuchElementException, WrappedTargetException, RuntimeException )
1138 {
1139     mxObjNameContainer->removeByName( Name );
1140 }
1141 
1142 // Methoden von XIndexAccess
1143 // Schon in XNameAccess: virtual Reference<XIdlClass> getElementType(void) const
1144 sal_Int32 ImplIntrospectionAdapter::getCount(void) throw( RuntimeException )
1145 {
1146     return mxObjIndexAccess->getCount();
1147 }
1148 
1149 Any ImplIntrospectionAdapter::getByIndex(sal_Int32 Index)
1150     throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
1151 {
1152     return mxObjIndexAccess->getByIndex( Index );
1153 }
1154 
1155 // Methoden von XIndexContainer
1156 void ImplIntrospectionAdapter::insertByIndex(sal_Int32 Index, const Any& Element)
1157     throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
1158 {
1159     mxObjIndexContainer->insertByIndex( Index, Element );
1160 }
1161 
1162 void ImplIntrospectionAdapter::replaceByIndex(sal_Int32 Index, const Any& Element)
1163     throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
1164 {
1165     mxObjIndexContainer->replaceByIndex( Index, Element );
1166 }
1167 
1168 void ImplIntrospectionAdapter::removeByIndex(sal_Int32 Index)
1169     throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
1170 {
1171     mxObjIndexContainer->removeByIndex( Index );
1172 }
1173 
1174 // Methoden von XEnumerationAccess
1175 // Schon in XNameAccess: virtual Reference<XIdlClass> getElementType(void) const;
1176 Reference<XEnumeration> ImplIntrospectionAdapter::createEnumeration(void) throw( RuntimeException )
1177 {
1178     return mxObjEnumerationAccess->createEnumeration();
1179 }
1180 
1181 // Methoden von XIdlArray
1182 void ImplIntrospectionAdapter::realloc(Any& array, sal_Int32 length)
1183     throw( IllegalArgumentException, RuntimeException )
1184 {
1185     mxObjIdlArray->realloc( array, length );
1186 }
1187 
1188 sal_Int32 ImplIntrospectionAdapter::getLen(const Any& array)
1189     throw( IllegalArgumentException, RuntimeException )
1190 {
1191     return mxObjIdlArray->getLen( array );
1192 }
1193 
1194 Any ImplIntrospectionAdapter::get(const Any& array, sal_Int32 index)
1195     throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException )
1196 {
1197     return mxObjIdlArray->get( array, index );
1198 }
1199 
1200 void ImplIntrospectionAdapter::set(Any& array, sal_Int32 index, const Any& value)
1201     throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException )
1202 {
1203     mxObjIdlArray->set( array, index, value );
1204 }
1205 
1206 
1207 //**************************************************
1208 //*** Implementation von ImplIntrospectionAccess ***
1209 //**************************************************
1210 
1211 // Methoden von XIntrospectionAccess
1212 sal_Int32 ImplIntrospectionAccess::getSuppliedMethodConcepts(void)
1213     throw( RuntimeException )
1214 {
1215     return  MethodConcept::DANGEROUS |
1216             PROPERTY |
1217             LISTENER |
1218             ENUMERATION |
1219             NAMECONTAINER |
1220             INDEXCONTAINER;
1221 }
1222 
1223 sal_Int32 ImplIntrospectionAccess::getSuppliedPropertyConcepts(void)
1224     throw( RuntimeException )
1225 {
1226     return  PropertyConcept::DANGEROUS |
1227             PROPERTYSET |
1228             ATTRIBUTES |
1229             METHODS;
1230 }
1231 
1232 Property ImplIntrospectionAccess::getProperty(const ::rtl::OUString& Name, sal_Int32 PropertyConcepts)
1233     throw( NoSuchElementException, RuntimeException )
1234 {
1235     Property aRet;
1236     sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1237     sal_Bool bFound = sal_False;
1238     if( i != -1 )
1239     {
1240         sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts().getConstArray()[ i ];
1241         if( (PropertyConcepts & nConcept) != 0 )
1242         {
1243             const Property* pProps = mpStaticImpl->getProperties().getConstArray();
1244             aRet = pProps[ i ];
1245             bFound = sal_True;
1246         }
1247     }
1248     if( !bFound )
1249         throw NoSuchElementException() ;
1250     return aRet;
1251 }
1252 
1253 sal_Bool ImplIntrospectionAccess::hasProperty(const ::rtl::OUString& Name, sal_Int32 PropertyConcepts)
1254     throw( RuntimeException )
1255 {
1256     sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
1257     sal_Bool bRet = sal_False;
1258     if( i != -1 )
1259     {
1260         sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts().getConstArray()[ i ];
1261         if( (PropertyConcepts & nConcept) != 0 )
1262             bRet = sal_True;
1263     }
1264     return bRet;
1265 }
1266 
1267 Sequence< Property > ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts)
1268     throw( RuntimeException )
1269 {
1270     // Wenn alle unterstuetzten Konzepte gefordert werden, Sequence einfach durchreichen
1271     sal_Int32 nAllSupportedMask =   PROPERTYSET |
1272                                     ATTRIBUTES |
1273                                     METHODS;
1274     if( ( PropertyConcepts & nAllSupportedMask ) == nAllSupportedMask )
1275     {
1276         return mpStaticImpl->getProperties();
1277     }
1278 
1279     // Gleiche Sequence wie beim vorigen mal?
1280     if( mnLastPropertyConcept == PropertyConcepts )
1281     {
1282         return maLastPropertySeq;
1283     }
1284 
1285     // Anzahl der zu liefernden Properties
1286     sal_Int32 nCount = 0;
1287 
1288     // Es gibt zur Zeit keine DANGEROUS-Properties
1289     // if( PropertyConcepts & DANGEROUS )
1290     //  nCount += mpStaticImpl->mnDangerousPropCount;
1291     if( PropertyConcepts & PROPERTYSET )
1292         nCount += mpStaticImpl->mnPropertySetPropCount;
1293     if( PropertyConcepts & ATTRIBUTES )
1294         nCount += mpStaticImpl->mnAttributePropCount;
1295     if( PropertyConcepts & METHODS )
1296         nCount += mpStaticImpl->mnMethodPropCount;
1297 
1298     // Sequence entsprechend der geforderten Anzahl reallocieren
1299     ImplIntrospectionAccess* pThis = (ImplIntrospectionAccess*)this;    // const umgehen
1300     pThis->maLastPropertySeq.realloc( nCount );
1301     Property* pDestProps = pThis->maLastPropertySeq.getArray();
1302 
1303     // Alle Properties durchgehen und entsprechend der Concepte uebernehmen
1304     Sequence<Property> aPropSeq = mpStaticImpl->getProperties();
1305     const Property* pSourceProps = aPropSeq.getConstArray();
1306     const sal_Int32* pConcepts = mpStaticImpl->getPropertyConcepts().getConstArray();
1307     sal_Int32 nLen = aPropSeq.getLength();
1308 
1309     sal_Int32 iDest = 0;
1310     for( sal_Int32 i = 0 ; i < nLen ; i++ )
1311     {
1312         sal_Int32 nConcept = pConcepts[ i ];
1313         if( nConcept & PropertyConcepts )
1314             pDestProps[ iDest++ ] = pSourceProps[ i ];
1315 
1316         /*
1317         // Property mit Concepts ausgeben
1318         ::rtl::OUString aPropName = pSourceProps[ i ].Name;
1319         String aNameStr = OOUStringToString(aPropName, CHARSET_SYSTEM);
1320         String ConceptStr;
1321         if( nConcept & PROPERTYSET )
1322             ConceptStr += "PROPERTYSET";
1323         if( nConcept & ATTRIBUTES )
1324             ConceptStr += "ATTRIBUTES";
1325         if( nConcept & METHODS )
1326             ConceptStr += "METHODS";
1327         printf( "Property %ld: %s, Concept = %s\n", i, aNameStr.GetStr(), ConceptStr.GetStr() );
1328         */
1329     }
1330 
1331     // PropertyConcept merken, dies entspricht maLastPropertySeq
1332     pThis->mnLastPropertyConcept = PropertyConcepts;
1333 
1334     // Zusammengebastelte Sequence liefern
1335     return maLastPropertySeq;
1336 }
1337 
1338 Reference<XIdlMethod> ImplIntrospectionAccess::getMethod(const ::rtl::OUString& Name, sal_Int32 MethodConcepts)
1339     throw( NoSuchMethodException, RuntimeException )
1340 {
1341     Reference<XIdlMethod> xRet;
1342     sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1343     if( i != -1 )
1344     {
1345 
1346         sal_Int32 nConcept = mpStaticImpl->getMethodConcepts().getConstArray()[ i ];
1347         if( (MethodConcepts & nConcept) != 0 )
1348         {
1349             const Reference<XIdlMethod>* pMethods = mpStaticImpl->getMethods().getConstArray();
1350             xRet = pMethods[i];
1351         }
1352     }
1353     if( !xRet.is() )
1354         throw NoSuchMethodException();
1355     return xRet;
1356 }
1357 
1358 sal_Bool ImplIntrospectionAccess::hasMethod(const ::rtl::OUString& Name, sal_Int32 MethodConcepts)
1359     throw( RuntimeException )
1360 {
1361     sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
1362     sal_Bool bRet = sal_False;
1363     if( i != -1 )
1364     {
1365         sal_Int32 nConcept = mpStaticImpl->getMethodConcepts().getConstArray()[ i ];
1366         if( (MethodConcepts & nConcept) != 0 )
1367             bRet = sal_True;
1368     }
1369     return bRet;
1370 }
1371 
1372 Sequence< Reference<XIdlMethod> > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts)
1373     throw( RuntimeException )
1374 {
1375     ImplIntrospectionAccess* pThis = (ImplIntrospectionAccess*)this;    // const umgehen
1376 
1377     // Wenn alle unterstuetzten Konzepte gefordert werden, Sequence einfach durchreichen
1378     sal_Int32 nAllSupportedMask =   MethodConcept::DANGEROUS |
1379                                     PROPERTY |
1380                                     LISTENER |
1381                                     ENUMERATION |
1382                                     NAMECONTAINER |
1383                                     INDEXCONTAINER |
1384                                     MethodConcept_NORMAL_IMPL;
1385     if( ( MethodConcepts & nAllSupportedMask ) == nAllSupportedMask )
1386     {
1387         return mpStaticImpl->getMethods();
1388     }
1389 
1390     // Gleiche Sequence wie beim vorigen mal?
1391     if( mnLastMethodConcept == MethodConcepts )
1392     {
1393         return maLastMethodSeq;
1394     }
1395 
1396     // Methoden-Sequences besorgen
1397     Sequence< Reference<XIdlMethod> > aMethodSeq = mpStaticImpl->getMethods();
1398     const Reference<XIdlMethod>* pSourceMethods = aMethodSeq.getConstArray();
1399     const sal_Int32* pConcepts = mpStaticImpl->getMethodConcepts().getConstArray();
1400     sal_Int32 nLen = aMethodSeq.getLength();
1401 
1402     // Sequence entsprechend der geforderten Anzahl reallocieren
1403     // Anders als bei den Properties kann die Anzahl nicht durch
1404     // Zaehler in inspect() vorher ermittelt werden, da Methoden
1405     // mehreren Konzepten angehoeren koennen
1406     pThis->maLastMethodSeq.realloc( nLen );
1407     Reference<XIdlMethod>* pDestMethods = pThis->maLastMethodSeq.getArray();
1408 
1409     // Alle Methods durchgehen und entsprechend der Concepte uebernehmen
1410     sal_Int32 iDest = 0;
1411     for( sal_Int32 i = 0 ; i < nLen ; i++ )
1412     {
1413         sal_Int32 nConcept = pConcepts[ i ];
1414         if( nConcept & MethodConcepts )
1415             pDestMethods[ iDest++ ] = pSourceMethods[ i ];
1416 
1417     #if OSL_DEBUG_LEVEL > 0
1418         static bool debug = false;
1419         if ( debug )
1420         {
1421             // Methode mit Concepts ausgeben
1422             const Reference< XIdlMethod >& rxMethod = pSourceMethods[ i ];
1423             ::rtl::OString aNameStr = ::rtl::OUStringToOString( rxMethod->getName(), osl_getThreadTextEncoding() );
1424             ::rtl::OString ConceptStr;
1425             if( nConcept & MethodConcept::DANGEROUS )
1426                 ConceptStr += "DANGEROUS |";
1427             if( nConcept & MethodConcept::PROPERTY )
1428                 ConceptStr += "PROPERTY |";
1429             if( nConcept & MethodConcept::LISTENER )
1430                 ConceptStr += "LISTENER |";
1431             if( nConcept & MethodConcept::ENUMERATION )
1432                 ConceptStr += "ENUMERATION |";
1433             if( nConcept & MethodConcept::NAMECONTAINER )
1434                 ConceptStr += "NAMECONTAINER |";
1435             if( nConcept & MethodConcept::INDEXCONTAINER )
1436                 ConceptStr += "INDEXCONTAINER |";
1437             OSL_TRACE( "Method %ld: %s, Concepts = %s", i, aNameStr.getStr(), ConceptStr.getStr() );
1438         }
1439     #endif
1440     }
1441 
1442     // Auf die richtige Laenge bringen
1443     pThis->maLastMethodSeq.realloc( iDest );
1444 
1445     // MethodConcept merken, dies entspricht maLastMethodSeq
1446     pThis->mnLastMethodConcept = MethodConcepts;
1447 
1448     // Zusammengebastelte Sequence liefern
1449     return maLastMethodSeq;
1450 }
1451 
1452 Sequence< Type > ImplIntrospectionAccess::getSupportedListeners(void)
1453     throw( RuntimeException )
1454 {
1455     return mpStaticImpl->getSupportedListeners();
1456 }
1457 
1458 Reference<XInterface> SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type& rType )
1459     throw( IllegalTypeException, RuntimeException )
1460 {
1461     // Gibt es schon einen Adapter?
1462     Reference< XInterface > xAdapter( maAdapter );
1463     if( !xAdapter.is() )
1464     {
1465         xAdapter = *( new ImplIntrospectionAdapter( this, maInspectedObject, mpStaticImpl ) );
1466         maAdapter = xAdapter;
1467     }
1468 
1469     Reference<XInterface> xRet;
1470     xAdapter->queryInterface( rType ) >>= xRet;
1471     return xRet;
1472 }
1473 
1474 // Methoden von XMaterialHolder
1475 Any ImplIntrospectionAccess::getMaterial(void) throw(RuntimeException)
1476 {
1477     return maInspectedObject;
1478 }
1479 
1480 // Hilfs-Funktion zur LowerCase-Wandlung eines ::rtl::OUString
1481 ::rtl::OUString toLower( ::rtl::OUString aUStr )
1482 {
1483     // Tabelle fuer XExactName pflegen
1484     ::rtl::OUString aOWStr( aUStr.getStr() );
1485     ::rtl::OUString aOWLowerStr = aOWStr.toAsciiLowerCase();
1486     ::rtl::OUString aLowerUStr( aOWLowerStr.getStr() );
1487     return aLowerUStr;
1488 }
1489 
1490 // Methoden von XExactName
1491 ::rtl::OUString ImplIntrospectionAccess::getExactName( const ::rtl::OUString& rApproximateName ) throw( RuntimeException )
1492 {
1493     ::rtl::OUString aRetStr;
1494     LowerToExactNameMap::iterator aIt =
1495         mpStaticImpl->maLowerToExactNameMap.find( toLower( rApproximateName ) );
1496     if( !( aIt == mpStaticImpl->maLowerToExactNameMap.end() ) )
1497         aRetStr = (*aIt).second;
1498     return aRetStr;
1499 }
1500 
1501 
1502 //-----------------------------------------------------------------------------
1503 
1504 #ifdef USE_INTROSPECTION_CACHE
1505 
1506 struct hashIntrospectionKey_Impl
1507 {
1508     Sequence< Reference<XIdlClass> >    aIdlClasses;
1509     Reference<XPropertySetInfo>         xPropInfo;
1510     Reference<XIdlClass>                xImplClass;
1511     sal_Int32                           nHitCount;
1512 
1513     void    IncHitCount() const { ((hashIntrospectionKey_Impl*)this)->nHitCount++; }
1514     hashIntrospectionKey_Impl() : nHitCount( 0 ) {}
1515     hashIntrospectionKey_Impl( const Sequence< Reference<XIdlClass> > & rIdlClasses,
1516                                         const Reference<XPropertySetInfo> & rxPropInfo,
1517                                         const Reference<XIdlClass> & rxImplClass );
1518 };
1519 
1520 hashIntrospectionKey_Impl::hashIntrospectionKey_Impl
1521 (
1522     const Sequence< Reference<XIdlClass> > & rIdlClasses,
1523     const Reference<XPropertySetInfo> & rxPropInfo,
1524     const Reference<XIdlClass> & rxImplClass
1525 )
1526         : aIdlClasses( rIdlClasses )
1527         , xPropInfo( rxPropInfo )
1528         , xImplClass( rxImplClass )
1529         , nHitCount( 0 )
1530 {}
1531 
1532 
1533 struct hashIntrospectionAccessCache_Impl
1534 {
1535     size_t operator()(const hashIntrospectionKey_Impl & rObj ) const
1536     {
1537         return (size_t)rObj.xImplClass.get() ^ (size_t)rObj.xPropInfo.get();
1538     }
1539 
1540     bool operator()( const hashIntrospectionKey_Impl & rObj1,
1541                      const hashIntrospectionKey_Impl & rObj2 ) const
1542     {
1543         if( rObj1.xPropInfo != rObj2.xPropInfo
1544           || rObj1.xImplClass != rObj2.xImplClass )
1545             return sal_False;
1546 
1547         sal_Int32 nCount1 = rObj1.aIdlClasses.getLength();
1548         sal_Int32 nCount2 = rObj2.aIdlClasses.getLength();
1549         if( nCount1 != nCount2 )
1550             return sal_False;
1551 
1552         const Reference<XIdlClass>* pRefs1 = rObj1.aIdlClasses.getConstArray();
1553         const Reference<XIdlClass>* pRefs2 = rObj2.aIdlClasses.getConstArray();
1554         return memcmp( pRefs1, pRefs2, nCount1 * sizeof( Reference<XIdlClass> ) ) == 0;
1555     }
1556 
1557 };
1558 
1559 typedef std::hash_map
1560 <
1561     hashIntrospectionKey_Impl,
1562     IntrospectionAccessStatic_Impl*,
1563     hashIntrospectionAccessCache_Impl,
1564     hashIntrospectionAccessCache_Impl
1565 >
1566 IntrospectionAccessCacheMap_Impl;
1567 
1568 class IntrospectionAccessCacheMap : public IntrospectionAccessCacheMap_Impl
1569 {
1570 public:
1571     ~IntrospectionAccessCacheMap()
1572     {
1573         IntrospectionAccessCacheMap::iterator iter = begin();
1574         IntrospectionAccessCacheMap::iterator stop = this->end();
1575         while( iter != stop )
1576         {
1577 
1578             (*iter).second->release();
1579             (*iter).second = NULL;
1580             iter++;
1581         }
1582     }
1583 };
1584 
1585 
1586 // For XTypeProvider
1587 struct hashTypeProviderKey_Impl
1588 {
1589     Reference<XPropertySetInfo>         xPropInfo;
1590     Sequence< sal_Int8 >                maImpIdSeq;
1591     sal_Int32                           nHitCount;
1592 
1593     void    IncHitCount() const { ((hashTypeProviderKey_Impl*)this)->nHitCount++; }
1594     hashTypeProviderKey_Impl() : nHitCount( 0 ) {}
1595     hashTypeProviderKey_Impl( const Reference<XPropertySetInfo> & rxPropInfo, const Sequence< sal_Int8 > & aImpIdSeq_ );
1596 };
1597 
1598 hashTypeProviderKey_Impl::hashTypeProviderKey_Impl
1599 (
1600     const Reference<XPropertySetInfo> & rxPropInfo,
1601     const Sequence< sal_Int8 > & aImpIdSeq_
1602 )
1603     : xPropInfo( rxPropInfo )
1604     , maImpIdSeq( aImpIdSeq_ )
1605     , nHitCount( 0 )
1606 {}
1607 
1608 
1609 struct TypeProviderAccessCache_Impl
1610 {
1611     size_t operator()(const hashTypeProviderKey_Impl & rObj ) const;
1612 
1613     bool operator()( const hashTypeProviderKey_Impl & rObj1,
1614                      const hashTypeProviderKey_Impl & rObj2 ) const
1615     {
1616         if( rObj1.xPropInfo != rObj2.xPropInfo )
1617             return sal_False;
1618 
1619         bool bEqual = false;
1620         sal_Int32 nLen1 = rObj1.maImpIdSeq.getLength();
1621         sal_Int32 nLen2 = rObj2.maImpIdSeq.getLength();
1622         if( nLen1 == nLen2 && nLen1 > 0 )
1623         {
1624             const sal_Int8* pId1 = rObj1.maImpIdSeq.getConstArray();
1625             const sal_Int8* pId2 = rObj2.maImpIdSeq.getConstArray();
1626             bEqual = (memcmp( pId1, pId2, nLen1 * sizeof( sal_Int8 ) ) == 0 );
1627         }
1628         return bEqual;
1629     }
1630 };
1631 
1632 size_t TypeProviderAccessCache_Impl::operator()(const hashTypeProviderKey_Impl & rObj ) const
1633 {
1634     const sal_Int32* pBytesAsInt32Array = (const sal_Int32*)rObj.maImpIdSeq.getConstArray();
1635     sal_Int32 nLen = rObj.maImpIdSeq.getLength();
1636     sal_Int32 nCount32 = nLen / 4;
1637     sal_Int32 nMod32 = nLen % 4;
1638 
1639     // XOR with full 32 bit values
1640     sal_Int32 nId32 = 0;
1641     sal_Int32 i;
1642     for( i = 0 ; i < nCount32 ; i++ )
1643         nId32 ^= *(pBytesAsInt32Array++);
1644 
1645     // XOR with remaining byte values
1646     if( nMod32 )
1647     {
1648         const sal_Int8* pBytes = (const sal_Int8*)pBytesAsInt32Array;
1649         sal_Int8* pInt8_Id32 = (sal_Int8*)&nId32;
1650         for( i = 0 ; i < nMod32 ; i++ )
1651             *(pInt8_Id32++) ^= *(pBytes++);
1652     }
1653 
1654     return (size_t)nId32;
1655 }
1656 
1657 
1658 typedef std::hash_map
1659 <
1660     hashTypeProviderKey_Impl,
1661     IntrospectionAccessStatic_Impl*,
1662     TypeProviderAccessCache_Impl,
1663     TypeProviderAccessCache_Impl
1664 >
1665 TypeProviderAccessCacheMap_Impl;
1666 
1667 class TypeProviderAccessCacheMap : public TypeProviderAccessCacheMap_Impl
1668 {
1669 public:
1670     ~TypeProviderAccessCacheMap()
1671     {
1672         TypeProviderAccessCacheMap::iterator iter = begin();
1673         TypeProviderAccessCacheMap::iterator stop = this->end();
1674         while( iter != stop )
1675         {
1676             (*iter).second->release();
1677             (*iter).second = NULL;
1678             iter++;
1679         }
1680     }
1681 };
1682 
1683 #endif
1684 
1685 
1686 //*************************
1687 //*** ImplIntrospection ***
1688 //*************************
1689 
1690 struct OIntrospectionMutex
1691 {
1692     Mutex                           m_mutex;
1693 };
1694 
1695 class ImplIntrospection : public XIntrospection
1696                         , public XServiceInfo
1697                         , public OIntrospectionMutex
1698                         , public OComponentHelper
1699 {
1700     friend class ImplMergeIntrospection;
1701     friend class ImplMVCIntrospection;
1702 
1703     // Implementation der Introspection.
1704     // ACHTUNG: RefCounting von Hand !!!
1705     IntrospectionAccessStatic_Impl* implInspect(const Any& aToInspectObj);
1706 
1707     // Save XMultiServiceFactory from createComponent
1708     Reference<XMultiServiceFactory> m_xSMgr;
1709 
1710     // CoreReflection halten
1711     Reference< XIdlReflection > mxCoreReflection;
1712 
1713     // Klassen, deren Methoden eine spezielle Rolle spielen
1714     Reference<XIdlClass> mxElementAccessClass;
1715     Reference<XIdlClass> mxNameContainerClass;
1716     Reference<XIdlClass> mxNameAccessClass;
1717     Reference<XIdlClass> mxIndexContainerClass;
1718     Reference<XIdlClass> mxIndexAccessClass;
1719     Reference<XIdlClass> mxEnumerationAccessClass;
1720     Reference<XIdlClass> mxInterfaceClass;
1721     Reference<XIdlClass> mxAggregationClass;
1722     sal_Bool mbDisposed;
1723 
1724 #ifdef USE_INTROSPECTION_CACHE
1725     sal_uInt16 mnCacheEntryCount;
1726     sal_uInt16 mnTPCacheEntryCount;
1727     IntrospectionAccessCacheMap* mpCache;
1728     TypeProviderAccessCacheMap* mpTypeProviderCache;
1729 #endif
1730 
1731 public:
1732     ImplIntrospection( const Reference<XMultiServiceFactory> & rXSMgr );
1733 
1734     // Methoden von XInterface
1735     virtual Any         SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException );
1736     virtual void        SAL_CALL acquire() throw() { OComponentHelper::acquire(); }
1737     virtual void        SAL_CALL release() throw() { OComponentHelper::release(); }
1738 
1739     // XTypeProvider
1740     Sequence< Type >    SAL_CALL getTypes(  ) throw( RuntimeException );
1741     Sequence<sal_Int8>  SAL_CALL getImplementationId(  ) throw( RuntimeException );
1742 
1743     // XServiceInfo
1744     ::rtl::OUString                     SAL_CALL getImplementationName() throw();
1745     sal_Bool                    SAL_CALL supportsService(const ::rtl::OUString& ServiceName) throw();
1746     Sequence< ::rtl::OUString >         SAL_CALL getSupportedServiceNames(void) throw();
1747     static ::rtl::OUString SAL_CALL getImplementationName_Static(  );
1748     static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(void) throw();
1749 
1750     // Methoden von XIntrospection
1751     virtual Reference<XIntrospectionAccess> SAL_CALL inspect(const Any& aToInspectObj)
1752                 throw( RuntimeException );
1753 
1754 protected:
1755     // some XComponent part from OComponentHelper
1756     virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
1757 };
1758 
1759 enum MethodType
1760 {
1761     STANDARD_METHOD,            // normale Methode, kein Bezug zu Properties oder Listenern
1762     GETSET_METHOD,              // gehoert zu einer get/set-Property
1763     ADD_LISTENER_METHOD,        // add-Methode einer Listener-Schnittstelle
1764     REMOVE_LISTENER_METHOD,     // remove-Methode einer Listener-Schnittstelle
1765     INVALID_METHOD              // Methode, deren Klasse nicht beruecksichtigt wird, z.B. XPropertySet
1766 };
1767 
1768 // Ctor
1769 ImplIntrospection::ImplIntrospection( const Reference<XMultiServiceFactory> & rXSMgr )
1770     : OComponentHelper( m_mutex )
1771     , m_xSMgr( rXSMgr )
1772 {
1773 #ifdef USE_INTROSPECTION_CACHE
1774     mnCacheEntryCount = 0;
1775     mnTPCacheEntryCount = 0;
1776     mpCache = NULL;
1777     mpTypeProviderCache = NULL;
1778 #endif
1779 
1780     // Spezielle Klassen holen
1781 //  Reference< XInterface > xServiceIface = m_xSMgr->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.CoreReflection")) );
1782 //  if( xServiceIface.is() )
1783 //      mxCoreReflection = Reference< XIdlReflection >::query( xServiceIface );
1784     Reference< XPropertySet > xProps( rXSMgr, UNO_QUERY );
1785     OSL_ASSERT( xProps.is() );
1786     if (xProps.is())
1787     {
1788         Reference< XComponentContext > xContext;
1789         xProps->getPropertyValue(
1790             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext;
1791         OSL_ASSERT( xContext.is() );
1792         if (xContext.is())
1793         {
1794             xContext->getValueByName(
1795                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection") ) ) >>= mxCoreReflection;
1796             OSL_ENSURE( mxCoreReflection.is(), "### CoreReflection singleton not accessible!?" );
1797         }
1798     }
1799     if (! mxCoreReflection.is())
1800     {
1801         throw DeploymentException(
1802             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessible") ),
1803             Reference< XInterface >() );
1804     }
1805 
1806     mxElementAccessClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XElementAccess")) );
1807     mxNameContainerClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XNameContainer")) );
1808     mxNameAccessClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XNameAccess")) );
1809     mxIndexContainerClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XIndexContainer")) );
1810     mxIndexAccessClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XIndexAccess")) );
1811     mxEnumerationAccessClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XEnumerationAccess")) );
1812     mxInterfaceClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XInterface")) );
1813     mxAggregationClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XAggregation")) );
1814     mbDisposed = sal_False;
1815 }
1816 
1817 // XComponent
1818 void ImplIntrospection::dispose() throw(::com::sun::star::uno::RuntimeException)
1819 {
1820     OComponentHelper::dispose();
1821 
1822 #ifdef USE_INTROSPECTION_CACHE
1823     // Cache loeschen
1824     delete mpCache;
1825     mpCache = NULL;
1826     delete mpTypeProviderCache;
1827     mpTypeProviderCache = NULL;
1828 #endif
1829 
1830     mxElementAccessClass = NULL;
1831     mxNameContainerClass = NULL;
1832     mxNameAccessClass = NULL;
1833     mxIndexContainerClass = NULL;
1834     mxIndexAccessClass = NULL;
1835     mxEnumerationAccessClass = NULL;
1836     mxInterfaceClass = NULL;
1837     mxAggregationClass = NULL;
1838     mbDisposed = sal_True;
1839 }
1840 
1841 
1842 //-----------------------------------------------------------------------------
1843 
1844 // XInterface
1845 Any ImplIntrospection::queryInterface( const Type & rType )
1846     throw(::com::sun::star::uno::RuntimeException)
1847 {
1848     Any aRet( ::cppu::queryInterface(
1849         rType,
1850         static_cast< XIntrospection * >( this ),
1851         static_cast< XServiceInfo * >( this ) ) );
1852 
1853     return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType ));
1854 }
1855 
1856 // XTypeProvider
1857 Sequence< Type > ImplIntrospection::getTypes()
1858     throw( RuntimeException )
1859 {
1860     static OTypeCollection * s_pTypes = 0;
1861     if (! s_pTypes)
1862     {
1863         MutexGuard aGuard( Mutex::getGlobalMutex() );
1864         if (! s_pTypes)
1865         {
1866             static OTypeCollection s_aTypes(
1867                 ::getCppuType( (const Reference< XIntrospection > *)0 ),
1868                 ::getCppuType( (const Reference< XServiceInfo > *)0 ),
1869                 OComponentHelper::getTypes() );
1870             s_pTypes = &s_aTypes;
1871         }
1872     }
1873     return s_pTypes->getTypes();
1874 }
1875 
1876 Sequence< sal_Int8 > ImplIntrospection::getImplementationId()
1877     throw( RuntimeException )
1878 {
1879     static OImplementationId * s_pId = 0;
1880     if (! s_pId)
1881     {
1882         MutexGuard aGuard( Mutex::getGlobalMutex() );
1883         if (! s_pId)
1884         {
1885             static OImplementationId s_aId;
1886             s_pId = &s_aId;
1887         }
1888     }
1889     return s_pId->getImplementationId();
1890 }
1891 
1892 
1893 // XServiceInfo
1894 ::rtl::OUString ImplIntrospection::getImplementationName() throw()
1895 {
1896     return getImplementationName_Static();
1897 }
1898 
1899 // XServiceInfo
1900 sal_Bool ImplIntrospection::supportsService(const ::rtl::OUString& ServiceName) throw()
1901 {
1902     Sequence< ::rtl::OUString > aSNL = getSupportedServiceNames();
1903     const ::rtl::OUString * pArray = aSNL.getConstArray();
1904     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
1905         if( pArray[i] == ServiceName )
1906             return sal_True;
1907     return sal_False;
1908 }
1909 
1910 // XServiceInfo
1911 Sequence< ::rtl::OUString > ImplIntrospection::getSupportedServiceNames(void) throw()
1912 {
1913     return getSupportedServiceNames_Static();
1914 }
1915 
1916 //*************************************************************************
1917 // Helper XServiceInfo
1918 ::rtl::OUString ImplIntrospection::getImplementationName_Static(  )
1919 {
1920     return ::rtl::OUString::createFromAscii( IMPLEMENTATION_NAME );
1921 }
1922 
1923 // ORegistryServiceManager_Static
1924 Sequence< ::rtl::OUString > ImplIntrospection::getSupportedServiceNames_Static(void) throw()
1925 {
1926     Sequence< ::rtl::OUString > aSNS( 1 );
1927     aSNS.getArray()[0] = ::rtl::OUString::createFromAscii( SERVICE_NAME );
1928     return aSNS;
1929 }
1930 
1931 //*************************************************************************
1932 
1933 // Methoden von XIntrospection
1934 Reference<XIntrospectionAccess> ImplIntrospection::inspect(const Any& aToInspectObj)
1935     throw( RuntimeException )
1936 {
1937     Reference<XIntrospectionAccess> xAccess;
1938 
1939     if ( aToInspectObj.getValueType().getTypeClass() == TypeClass_TYPE )
1940     {
1941         Type aType;
1942         aToInspectObj >>= aType;
1943 
1944         Reference< XIdlClass > xIdlClass = mxCoreReflection->forName(((Type*)(aToInspectObj.getValue()))->getTypeName());
1945 
1946         if ( xIdlClass.is() )
1947         {
1948             Any aRealInspectObj;
1949             aRealInspectObj <<= xIdlClass;
1950 
1951             IntrospectionAccessStatic_Impl* pStaticImpl = implInspect( aRealInspectObj );
1952             if( pStaticImpl )
1953                 xAccess = new ImplIntrospectionAccess( aRealInspectObj, pStaticImpl );
1954         }
1955     }
1956     else
1957     {
1958         IntrospectionAccessStatic_Impl* pStaticImpl = implInspect( aToInspectObj );
1959         if( pStaticImpl )
1960             xAccess = new ImplIntrospectionAccess( aToInspectObj, pStaticImpl );
1961     }
1962 
1963     return xAccess;
1964 }
1965 
1966 //-----------------------------------------------------------------------------
1967 
1968 // Hashtable fuer Pruefung auf mehrfache Beruecksichtigung von Interfaces
1969 struct hashInterface_Impl
1970 {
1971     size_t operator()(const void* p) const
1972     {
1973         return (size_t)p;
1974     }
1975 };
1976 
1977 struct eqInterface_Impl
1978 {
1979     bool operator()(const void* p1, const void* p2) const
1980     {
1981         return ( p1 == p2 );
1982     }
1983 };
1984 
1985 typedef std::hash_map
1986 <
1987     void*,
1988     void*,
1989     hashInterface_Impl,
1990     eqInterface_Impl
1991 >
1992 CheckedInterfacesMap;
1993 
1994 
1995 
1996 // TODO: Spaeter auslagern
1997 Reference<XIdlClass> TypeToIdlClass( const Type& rType, const Reference< XMultiServiceFactory > & xMgr )
1998 {
1999     static Reference< XIdlReflection > xRefl;
2000 
2001     // void als Default-Klasse eintragen
2002     Reference<XIdlClass> xRetClass;
2003     typelib_TypeDescription * pTD = 0;
2004     rType.getDescription( &pTD );
2005     if( pTD )
2006     {
2007         ::rtl::OUString sOWName( pTD->pTypeName );
2008         if( !xRefl.is() )
2009         {
2010             xRefl = Reference< XIdlReflection >( xMgr->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.CoreReflection")) ), UNO_QUERY );
2011             OSL_ENSURE( xRefl.is(), "### no corereflection!" );
2012         }
2013         xRetClass = xRefl->forName( sOWName );
2014     }
2015     return xRetClass;
2016 }
2017 
2018 // Implementation der Introspection.
2019 IntrospectionAccessStatic_Impl* ImplIntrospection::implInspect(const Any& aToInspectObj)
2020 {
2021     MutexGuard aGuard( m_mutex );
2022 
2023     // Wenn die Introspection schon disposed ist, wird nur ein leeres Ergebnis geliefert
2024     if( mbDisposed )
2025         return NULL;
2026 
2027     // Objekt untersuchen
2028     TypeClass eType = aToInspectObj.getValueType().getTypeClass();
2029     if( eType != TypeClass_INTERFACE && eType != TypeClass_STRUCT  && eType != TypeClass_EXCEPTION )
2030         return NULL;
2031 
2032     Reference<XInterface> x;
2033     if( eType == TypeClass_INTERFACE )
2034     {
2035         // Interface aus dem Any besorgen
2036         x = *(Reference<XInterface>*)aToInspectObj.getValue();
2037         if( !x.is() )
2038             return NULL;
2039     }
2040 
2041 #ifdef USE_INTROSPECTION_CACHE
2042     // Haben wir schon eine Cache-Instanz
2043     if( !mpCache )
2044         mpCache = new IntrospectionAccessCacheMap;
2045     if( !mpTypeProviderCache )
2046         mpTypeProviderCache = new TypeProviderAccessCacheMap;
2047     IntrospectionAccessCacheMap& aCache = *mpCache;
2048     TypeProviderAccessCacheMap& aTPCache = *mpTypeProviderCache;
2049 
2050     // Pointer auf ggf. noetige neue IntrospectionAccess-Instanz
2051     IntrospectionAccessStatic_Impl* pAccess = NULL;
2052 #else
2053     // Pointer auf ggf. noetige neue IntrospectionAccess-Instanz
2054     IntrospectionAccessStatic_Impl* pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection );
2055 #endif
2056 
2057     // Pruefen: Ist schon ein passendes Access-Objekt gecached?
2058     Sequence< Reference<XIdlClass> >    SupportedClassSeq;
2059     Sequence< Type >                    SupportedTypesSeq;
2060     Reference<XIdlClassProvider>        xClassProvider;
2061     Reference<XTypeProvider>            xTypeProvider;
2062     Reference<XIdlClass>                xImplClass;
2063     Reference<XPropertySetInfo>         xPropSetInfo;
2064     Reference<XPropertySet>             xPropSet;
2065 
2066     // Bei Interfaces XTypeProvider / XIdlClassProvider- und PropertySet-Interface anfordern
2067     if( eType == TypeClass_INTERFACE )
2068     {
2069         // XIdlClassProvider
2070         xTypeProvider = Reference<XTypeProvider>::query( x );
2071         if( xTypeProvider.is() )
2072         {
2073             SupportedTypesSeq = xTypeProvider->getTypes();
2074             sal_Int32 nTypeCount = SupportedTypesSeq.getLength();
2075             if( nTypeCount )
2076             {
2077                 SupportedClassSeq.realloc( nTypeCount );
2078                 Reference<XIdlClass>* pClasses = SupportedClassSeq.getArray();
2079 
2080                 const Type* pTypes = SupportedTypesSeq.getConstArray();
2081                 for( sal_Int32 i = 0 ; i < nTypeCount ; i++ )
2082                 {
2083                     pClasses[ i ] = TypeToIdlClass( pTypes[ i ], m_xSMgr );
2084                 }
2085                 // TODO: Caching!
2086             }
2087         }
2088         else
2089         {
2090             // XIdlClassProvider
2091             xClassProvider = Reference<XIdlClassProvider>::query( x );
2092             if( xClassProvider.is() )
2093             {
2094                 SupportedClassSeq = xClassProvider->getIdlClasses();
2095                 if( SupportedClassSeq.getLength() )
2096                     xImplClass = SupportedClassSeq.getConstArray()[0];
2097             }
2098         }
2099         // #70197, fuer InvocationAdapter: Interface-Typ im Any auch ohne
2100         // ClassProvider unterstuetzen
2101         if( !xClassProvider.is() && !xTypeProvider.is() )
2102         {
2103             xImplClass = TypeToIdlClass( aToInspectObj.getValueType(), m_xSMgr );
2104             SupportedClassSeq.realloc( 1 );
2105             SupportedClassSeq.getArray()[ 0 ] = xImplClass;
2106         }
2107 
2108         xPropSet = Reference<XPropertySet>::query( x );
2109         // Jetzt versuchen, das PropertySetInfo zu bekommen
2110         if( xPropSet.is() )
2111             xPropSetInfo = xPropSet->getPropertySetInfo();
2112     }
2113     else
2114     {
2115         xImplClass = TypeToIdlClass( aToInspectObj.getValueType(), m_xSMgr );
2116     }
2117 
2118 #ifdef USE_INTROSPECTION_CACHE
2119     if( xTypeProvider.is() )
2120     {
2121         Sequence< sal_Int8 > aImpIdSeq = xTypeProvider->getImplementationId();
2122         sal_Int32 nIdLen = aImpIdSeq.getLength();
2123 
2124         if( nIdLen )
2125         {
2126             // cache only, if the descriptor class is set
2127             hashTypeProviderKey_Impl aKeySeq( xPropSetInfo, aImpIdSeq );
2128 
2129             TypeProviderAccessCacheMap::iterator aIt = aTPCache.find( aKeySeq );
2130             if( aIt == aTPCache.end() )
2131             {
2132                 // not found
2133                 // Neue Instanz anlegen und unter dem gegebenen Key einfuegen
2134                 pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection );
2135 
2136                 // RefCount von Hand erhoehen, muss beim Entfernen
2137                 // aus der Hashtable wieder released werden
2138                 pAccess->acquire();
2139 
2140                 // Groesse begrenzen, alten Eintrag wieder rausschmeissen
2141                 if( mnTPCacheEntryCount > INTROSPECTION_CACHE_MAX_SIZE )
2142                 {
2143                     // Access mit dem kleinsten HitCount suchen
2144                     TypeProviderAccessCacheMap::iterator iter = aTPCache.begin();
2145                     TypeProviderAccessCacheMap::iterator end = aTPCache.end();
2146                     TypeProviderAccessCacheMap::iterator toDelete = iter;
2147                     while( iter != end )
2148                     {
2149                         if( (*iter).first.nHitCount < (*toDelete).first.nHitCount )
2150                             toDelete = iter;
2151                         ++iter;
2152                     }
2153 
2154                     // Gefundenen Eintrag entfernen
2155                     if( (*toDelete).second )
2156                         (*toDelete).second->release();
2157                     (*toDelete).second = NULL;
2158                     aTPCache.erase( toDelete );
2159                 }
2160                 else
2161                     mnTPCacheEntryCount++;
2162 
2163                 // Neuer Eintrage rein in die Table
2164                 aKeySeq.nHitCount = 1;
2165                 aTPCache[ aKeySeq ] = pAccess;
2166 
2167             }
2168             else
2169             {
2170                 // Hit-Count erhoehen
2171                 (*aIt).first.IncHitCount();
2172                 return (*aIt).second;
2173             }
2174         }
2175     }
2176     else if( xImplClass.is() )
2177     {
2178         // cache only, if the descriptor class is set
2179         hashIntrospectionKey_Impl   aKeySeq( SupportedClassSeq, xPropSetInfo, xImplClass );
2180 
2181         IntrospectionAccessCacheMap::iterator aIt = aCache.find( aKeySeq );
2182         if( aIt == aCache.end() )
2183         {
2184             // not found
2185             // Neue Instanz anlegen und unter dem gegebenen Key einfuegen
2186             pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection );
2187 
2188             // RefCount von Hand erhoehen, muss beim Entfernen
2189             // aus der Hashtable wieder released werden
2190             pAccess->acquire();
2191 
2192             // Groesse begrenzen, alten Eintrag wieder rausschmeissen
2193             if( mnCacheEntryCount > INTROSPECTION_CACHE_MAX_SIZE )
2194             {
2195                 // Access mit dem kleinsten HitCount suchen
2196                 IntrospectionAccessCacheMap::iterator iter = aCache.begin();
2197                 IntrospectionAccessCacheMap::iterator end = aCache.end();
2198                 IntrospectionAccessCacheMap::iterator toDelete = iter;
2199                 while( iter != end )
2200                 {
2201                     if( (*iter).first.nHitCount < (*toDelete).first.nHitCount )
2202                         toDelete = iter;
2203                     ++iter;
2204                 }
2205 
2206                 // Gefundenen Eintrag entfernen
2207                 if( (*toDelete).second )
2208                     (*toDelete).second->release();
2209                 (*toDelete).second = NULL;
2210                 aCache.erase( toDelete );
2211             }
2212             else
2213                 mnCacheEntryCount++;
2214 
2215             // Neuer Eintrage rein in die Table
2216             aKeySeq.nHitCount = 1;
2217             aCache[ aKeySeq ] = pAccess;
2218 
2219         }
2220         else
2221         {
2222             // Hit-Count erhoehen
2223             (*aIt).first.IncHitCount();
2224             return (*aIt).second;
2225         }
2226     }
2227 #endif
2228 
2229     // Kein Access gecached -> neu anlegen
2230     Property* pAllPropArray;
2231     Reference<XInterface>* pInterfaces1;
2232     Reference<XInterface>* pInterfaces2;
2233     sal_Int16* pMapTypeArray;
2234     sal_Int32* pPropertyConceptArray;
2235     sal_Int32 i;
2236 
2237     if( !pAccess )
2238         pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection );
2239 
2240     // Referenzen auf wichtige Daten von pAccess
2241     sal_Int32& rPropCount = pAccess->mnPropCount;
2242     IntrospectionNameMap& rPropNameMap = pAccess->maPropertyNameMap;
2243     IntrospectionNameMap& rMethodNameMap = pAccess->maMethodNameMap;
2244     LowerToExactNameMap& rLowerToExactNameMap = pAccess->maLowerToExactNameMap;
2245 
2246     // Schon mal Pointer auf das eigene Property-Feld holen
2247     pAllPropArray = pAccess->maAllPropertySeq.getArray();
2248     pInterfaces1 = pAccess->aInterfaceSeq1.getArray();
2249     pInterfaces2 = pAccess->aInterfaceSeq2.getArray();
2250     pMapTypeArray = pAccess->maMapTypeSeq.getArray();
2251     pPropertyConceptArray = pAccess->maPropertyConceptSeq.getArray();
2252 
2253     //*************************
2254     //*** Analyse vornehmen ***
2255     //*************************
2256     if( eType == TypeClass_INTERFACE )
2257     {
2258         // Zunaechst nach speziellen Interfaces suchen, die fuer
2259         // die Introspection von besonderer Bedeutung sind.
2260 
2261         // XPropertySet vorhanden?
2262         if( xPropSet.is() && xPropSetInfo.is() )
2263         {
2264             // Gibt es auch ein FastPropertySet?
2265             Reference<XFastPropertySet> xDummy = Reference<XFastPropertySet>::query( x );
2266             sal_Bool bFast = pAccess->mbFastPropSet = xDummy.is();
2267 
2268             Sequence<Property> aPropSeq = xPropSetInfo->getProperties();
2269             const Property* pProps = aPropSeq.getConstArray();
2270             sal_Int32 nLen = aPropSeq.getLength();
2271 
2272             // Bei FastPropertySet muessen wir uns die Original-Handles merken
2273             if( bFast )
2274                 pAccess->mpOrgPropertyHandleArray = new sal_Int32[ nLen ];
2275 
2276             for( i = 0 ; i < nLen ; i++ )
2277             {
2278                 // Property in eigene Liste uebernehmen
2279                 pAccess->checkPropertyArraysSize
2280                     ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount );
2281                 Property& rProp = pAllPropArray[ rPropCount ];
2282                 rProp = pProps[ i ];
2283 
2284                 if( bFast )
2285                     pAccess->mpOrgPropertyHandleArray[ i ] = rProp.Handle;
2286 
2287                 // PropCount als Handle fuer das eigene FastPropertySet eintragen
2288                 rProp.Handle = rPropCount;
2289 
2290                 // Art der Property merken
2291                 pMapTypeArray[ rPropCount ] = MAP_PROPERTY_SET;
2292                 pPropertyConceptArray[ rPropCount ] = PROPERTYSET;
2293                 pAccess->mnPropertySetPropCount++;
2294 
2295                 // Namen in Hashtable eintragen, wenn nicht schon bekannt
2296                 ::rtl::OUString aPropName = rProp.Name;
2297 
2298                 // Haben wir den Namen schon?
2299                 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2300                 if( aIt == rPropNameMap.end() )
2301                 {
2302                     // Neuer Eintrag in die Hashtable
2303                     rPropNameMap[ aPropName ] = rPropCount;
2304 
2305                     // Tabelle fuer XExactName pflegen
2306                     rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName;
2307                 }
2308                 else
2309                 {
2310                     OSL_ENSURE( sal_False,
2311                         ::rtl::OString( "Introspection: Property \"" ) +
2312                         ::rtl::OUStringToOString( aPropName, RTL_TEXTENCODING_ASCII_US ) +
2313                         ::rtl::OString( "\" found more than once in PropertySet" ) );
2314                 }
2315 
2316                 // Count pflegen
2317                 rPropCount++;
2318             }
2319         }
2320 
2321 
2322         // Jetzt alle weiteren implementierten Interfaces durchgehen
2323         // Diese muessen durch das XIdlClassProvider-Interface geliefert werden.
2324         // #70197, fuer InvocationAdapter: Interface-Typ im Any auch ohne
2325         // ClassProvider unterstuetzen
2326         //if( xClassProvider.is() )
2327         {
2328             // Indizes in die Export-Tabellen
2329             sal_Int32 iAllExportedMethod = 0;
2330             sal_Int32 iAllSupportedListener = 0;
2331 
2332             // Hashtable fuer Pruefung auf mehrfache Beruecksichtigung von Interfaces
2333             CheckedInterfacesMap aCheckedInterfacesMap;
2334 
2335             // Flag, ob XInterface-Methoden erfasst werden sollen
2336             // (das darf nur einmal erfolgen, initial zulassen)
2337             sal_Bool bXInterfaceIsInvalid = sal_False;
2338 
2339             // Flag, ob die XInterface-Methoden schon erfasst wurden. Wenn sal_True,
2340             // wird bXInterfaceIsInvalid am Ende der Iface-Schleife aktiviert und
2341             // XInterface-Methoden werden danach abgeklemmt.
2342             sal_Bool bFoundXInterface = sal_False;
2343 
2344             // Schleife ueber alle vom ClassProvider angegebenen Klassen
2345             sal_Int32 nClassCount = SupportedClassSeq.getLength();
2346             for( sal_Int32 nIdx = 0 ; nIdx < nClassCount; nIdx++ )
2347             {
2348                 Reference<XIdlClass> xImplClass2 = SupportedClassSeq.getConstArray()[nIdx];
2349                 while( xImplClass2.is() )
2350                 {
2351                     // Interfaces der Implementation holen
2352                     Sequence< Reference<XIdlClass> > aClassSeq = xImplClass2->getInterfaces();
2353                     sal_Int32 nIfaceCount = aClassSeq.getLength();
2354 
2355                     aClassSeq.realloc( nIfaceCount + 1 );
2356                     aClassSeq.getArray()[ nIfaceCount ] = xImplClass2;
2357                     nIfaceCount++;
2358 
2359                     const Reference<XIdlClass>* pParamArray = aClassSeq.getConstArray();
2360 
2361                     for( sal_Int32 j = 0 ; j < nIfaceCount ; j++ )
2362                     {
2363                         const Reference<XIdlClass>& rxIfaceClass = pParamArray[j];
2364 
2365                         // Pruefen, ob das Interface schon beruecksichtigt wurde.
2366                         XInterface* pIface = SAL_STATIC_CAST( XInterface*, rxIfaceClass.get() );
2367                         if( aCheckedInterfacesMap.count( pIface ) > 0 )
2368                         {
2369                             // Kennen wir schon
2370                             continue;
2371                         }
2372                         else
2373                         {
2374                             // Sonst eintragen
2375                             aCheckedInterfacesMap[ pIface ] = pIface;
2376                         }
2377 
2378                         //********************************************************************
2379 
2380                         // 2. Fields als Properties registrieren
2381 
2382                         // Felder holen
2383                         Sequence< Reference<XIdlField> > fields = rxIfaceClass->getFields();
2384                         const Reference<XIdlField>* pFields = fields.getConstArray();
2385                         sal_Int32 nLen = fields.getLength();
2386 
2387                         for( i = 0 ; i < nLen ; i++ )
2388                         {
2389                             Reference<XIdlField> xField = pFields[i];
2390                             Reference<XIdlClass> xPropType = xField->getType();
2391 
2392                             // Ist die PropertySequence gross genug?
2393                             pAccess->checkPropertyArraysSize
2394                                 ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount );
2395 
2396                             // In eigenes Property-Array eintragen
2397                             Property& rProp = pAllPropArray[ rPropCount ];
2398                             ::rtl::OUString aFieldName = xField->getName();
2399                             rProp.Name = aFieldName;
2400                             rProp.Handle = rPropCount;
2401                             Type aFieldType( xPropType->getTypeClass(), xPropType->getName() );
2402                             rProp.Type = aFieldType;
2403                             FieldAccessMode eAccessMode = xField->getAccessMode();
2404                             rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
2405                                                 eAccessMode == FieldAccessMode_CONST)
2406                                                 ? READONLY : 0;
2407 
2408                             // Namen in Hashtable eintragen
2409                             ::rtl::OUString aPropName = rProp.Name;
2410 
2411                             // Haben wir den Namen schon?
2412                             IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2413                             if( !( aIt == rPropNameMap.end() ) )
2414                             {
2415                                 /* TODO
2416                                 OSL_TRACE(
2417                                     String( "Introspection: Property \"" ) +
2418                                     OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2419                                     String( "\" found more than once" ) );
2420                                     */
2421                                 continue;
2422                             }
2423 
2424                             // Neuer Eintrag in die Hashtable
2425                             rPropNameMap[ aPropName ] = rPropCount;
2426 
2427                             // Tabelle fuer XExactName pflegen
2428                             rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName;
2429 
2430                             // Field merken
2431                             pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq1,
2432                                 pInterfaces1, rPropCount );
2433                             pInterfaces1[ rPropCount ] = xField;
2434 
2435                             // Art der Property merken
2436                             pMapTypeArray[ rPropCount ] = MAP_FIELD;
2437                             pPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
2438                             pAccess->mnAttributePropCount++;
2439 
2440                             // Count pflegen
2441                             rPropCount++;
2442                         }
2443 
2444                         //********************************************************************
2445 
2446                         // 3. Methoden
2447 
2448                         // Zaehler fuer die gefundenen Listener
2449                         sal_Int32 nListenerCount = 0;
2450 
2451                         // Alle Methoden holen und merken
2452                         Sequence< Reference<XIdlMethod> > methods = rxIfaceClass->getMethods();
2453                         const Reference<XIdlMethod>* pSourceMethods = methods.getConstArray();
2454                         sal_Int32 nSourceMethodCount = methods.getLength();
2455 
2456                         // 3. a) get/set- und Listener-Methoden suchen
2457 
2458                         // Feld fuer Infos ueber die Methoden anlegen, damit spaeter leicht die Methoden
2459                         // gefunden werden koennen, die nicht im Zusammenhang mit Properties oder Listenern
2460                         // stehen. NEU: auch MethodConceptArray initialisieren
2461                         MethodType* pMethodTypes = new MethodType[ nSourceMethodCount ];
2462                         sal_Int32* pLocalMethodConcepts = new sal_Int32[ nSourceMethodCount ];
2463                         for( i = 0 ; i < nSourceMethodCount ; i++ )
2464                         {
2465                             pMethodTypes[ i ] = STANDARD_METHOD;
2466                             pLocalMethodConcepts[ i ] = 0;
2467                         }
2468 
2469                         ::rtl::OUString aMethName;
2470                         ::rtl::OUString aPropName;
2471                         ::rtl::OUString aStartStr;
2472                         for( i = 0 ; i < nSourceMethodCount ; i++ )
2473                         {
2474                             // Methode ansprechen
2475                             const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
2476                             sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
2477 
2478                             // Namen besorgen
2479                             aMethName = rxMethod_i->getName();
2480 
2481                             // Methoden katalogisieren
2482                             // Alle (?) Methoden von XInterface filtern, damit z.B. nicht
2483                             // vom Scripting aus aquire oder release gerufen werden kann
2484                             if( rxMethod_i->getDeclaringClass()->equals( mxInterfaceClass ) )
2485                             {
2486                                 // XInterface-Methoden sind hiermit einmal beruecksichtigt
2487                                 bFoundXInterface = sal_True;
2488 
2489                                 if( bXInterfaceIsInvalid )
2490                                 {
2491                                     pMethodTypes[ i ] = INVALID_METHOD;
2492                                     continue;
2493                                 }
2494                                 else
2495                                 {
2496                                     if( aMethName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("queryInterface")) )
2497                                     {
2498                                         rMethodConcept_i |= MethodConcept::DANGEROUS;
2499                                         continue;
2500                                     }
2501                                 }
2502                             }
2503                             else if( rxMethod_i->getDeclaringClass()->equals( mxAggregationClass ) )
2504                             {
2505                                 if( aMethName == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("setDelegator")) )
2506                                 {
2507                                     rMethodConcept_i |= MethodConcept::DANGEROUS;
2508                                     continue;
2509                                 }
2510                             }
2511                             else if( rxMethod_i->getDeclaringClass()->equals( mxElementAccessClass ) )
2512                             {
2513                                 rMethodConcept_i |= ( NAMECONTAINER  |
2514                                                       INDEXCONTAINER |
2515                                                       ENUMERATION );
2516                             }
2517                             else if( rxMethod_i->getDeclaringClass()->equals( mxNameContainerClass ) ||
2518                                      rxMethod_i->getDeclaringClass()->equals( mxNameAccessClass ) )
2519                             {
2520                                 rMethodConcept_i |= NAMECONTAINER;
2521                             }
2522                             else if( rxMethod_i->getDeclaringClass()->equals( mxIndexContainerClass ) ||
2523                                      rxMethod_i->getDeclaringClass()->equals( mxIndexAccessClass ) )
2524                             {
2525                                 rMethodConcept_i |= INDEXCONTAINER;
2526                             }
2527                             else if( rxMethod_i->getDeclaringClass()->equals( mxEnumerationAccessClass ) )
2528                             {
2529                                 rMethodConcept_i |= ENUMERATION;
2530                             }
2531 
2532                             // Wenn der Name zu kurz ist, wird's sowieso nichts
2533                             if( aMethName.getLength() <= 3 )
2534                                 continue;
2535 
2536                             // Ist es eine get-Methode?
2537                             aStartStr = aMethName.copy( 0, 3 );
2538                             if( aStartStr == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("get")) )
2539                             {
2540                                 // Namen der potentiellen Property
2541                                 aPropName = aMethName.copy( 3 );
2542 
2543                                 // get-Methode darf keinen Parameter haben
2544                                 Sequence< Reference<XIdlClass> > getParams = rxMethod_i->getParameterTypes();
2545                                 if( getParams.getLength() > 0 )
2546                                 {
2547                                     continue;
2548                                 }
2549 
2550                                 // Haben wir den Namen schon?
2551                                 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2552                                 if( !( aIt == rPropNameMap.end() ) )
2553                                 {
2554                                     /* TODO
2555                                     OSL_TRACE(
2556                                         String( "Introspection: Property \"" ) +
2557                                         OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2558                                         String( "\" found more than once" ) );
2559                                         */
2560                                     continue;
2561                                 }
2562 
2563                                 // Eine readonly-Property ist es jetzt mindestens schon
2564                                 rMethodConcept_i |= PROPERTY;
2565 
2566                                 pMethodTypes[i] = GETSET_METHOD;
2567                                 Reference<XIdlClass> xGetRetType = rxMethod_i->getReturnType();
2568 
2569                                 // Ist die PropertySequence gross genug?
2570                                 pAccess->checkPropertyArraysSize
2571                                     ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount );
2572 
2573                                 // In eigenes Property-Array eintragen
2574                                 Property& rProp = pAllPropArray[ rPropCount ];
2575                                 rProp.Name = aPropName;
2576                                 rProp.Handle = rPropCount;
2577                                 rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
2578                                 rProp.Attributes = READONLY;
2579 
2580                                 // Neuer Eintrag in die Hashtable
2581                                 rPropNameMap[ aPropName ] = rPropCount;
2582 
2583                                 // Tabelle fuer XExactName pflegen
2584                                 rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName;
2585 
2586                                 // get-Methode merken
2587                                 pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq1,
2588                                     pInterfaces1, rPropCount );
2589                                 pInterfaces1[ rPropCount ] = rxMethod_i;
2590 
2591                                 // Art der Property merken
2592                                 pMapTypeArray[ rPropCount ] = MAP_GETSET;
2593                                 pPropertyConceptArray[ rPropCount ] = METHODS;
2594                                 pAccess->mnMethodPropCount++;
2595 
2596                                 // Passende set-Methode suchen
2597                                 sal_Int32 k;
2598                                 for( k = 0 ; k < nSourceMethodCount ; k++ )
2599                                 {
2600                                     // Methode ansprechen
2601                                     const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k];
2602 
2603                                     // Nur Methoden nehmen, die nicht schon zugeordnet sind
2604                                     if( k == i || pMethodTypes[k] != STANDARD_METHOD )
2605                                         continue;
2606 
2607                                     // Name holen und auswerten
2608                                     ::rtl::OUString aMethName2 = rxMethod_k->getName();
2609                                     ::rtl::OUString aStartStr2 = aMethName2.copy( 0, 3 );
2610                                     // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!!
2611                                     if( !( aStartStr2 == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("set")) ) )
2612                                         continue;
2613 
2614                                     // Ist es denn der gleiche Name?
2615                                     ::rtl::OUString aPropName2 = aMethName2.copy( 3 );
2616                                     // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!!
2617                                     if( !( aPropName == aPropName2 ) )
2618                                         continue;
2619 
2620                                     // set-Methode muss void returnen
2621                                     Reference<XIdlClass> xSetRetType = rxMethod_k->getReturnType();
2622                                     if( xSetRetType->getTypeClass() != TypeClass_VOID )
2623                                     {
2624                                         continue;
2625                                     }
2626 
2627                                     // set-Methode darf nur einen Parameter haben
2628                                     Sequence< Reference<XIdlClass> > setParams = rxMethod_k->getParameterTypes();
2629                                     sal_Int32 nParamCount = setParams.getLength();
2630                                     if( nParamCount != 1 )
2631                                     {
2632                                         continue;
2633                                     }
2634 
2635                                     // Jetzt muss nur noch der return-Typ dem Parameter-Typ entsprechen
2636                                     const Reference<XIdlClass>* pParamArray2 = setParams.getConstArray();
2637                                     Reference<XIdlClass> xParamType = pParamArray2[ 0 ];
2638                                     if( xParamType->equals( xGetRetType ) )
2639                                     {
2640                                         pLocalMethodConcepts[ k ] = PROPERTY;
2641 
2642                                         pMethodTypes[k] = GETSET_METHOD;
2643 
2644                                         // ReadOnly-Flag wieder loschen
2645                                         rProp.Attributes &= ~READONLY;
2646 
2647                                         // set-Methode merken
2648                                         pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2649                                             pInterfaces2, rPropCount );
2650                                         pInterfaces2[ rPropCount ] = rxMethod_k;
2651                                     }
2652                                 }
2653 
2654                                 // Count pflegen
2655                                 rPropCount++;
2656                             }
2657 
2658                             // Ist es eine addListener-Methode?
2659                             else if( aStartStr == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("add")) )
2660                             {
2661                                 ::rtl::OUString aListenerStr( RTL_CONSTASCII_USTRINGPARAM("Listener" ) );
2662 
2663                                 // Namen der potentiellen Property
2664                                 sal_Int32 nStrLen = aMethName.getLength();
2665                                 sal_Int32 nCopyLen = nStrLen - aListenerStr.getLength();
2666                                 ::rtl::OUString aEndStr = aMethName.copy( nCopyLen > 0 ? nCopyLen : 0 );
2667 
2668                                 // Endet das Teil auf Listener?
2669                                 // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!!
2670                                 if( !( aEndStr == aListenerStr ) )
2671                                     continue;
2672 
2673                                 // Welcher Listener?
2674                                 ::rtl::OUString aListenerName = aMethName.copy( 3, nStrLen - aListenerStr.getLength() - 3 );
2675 
2676                                 // TODO: Hier koennten noch genauere Pruefungen vorgenommen werden
2677                                 // - Rueckgabe-Typ
2678                                 // - Anzahl und Art der Parameter
2679 
2680 
2681                                 // Passende remove-Methode suchen, sonst gilt's nicht
2682                                 sal_Int32 k;
2683                                 for( k = 0 ; k < nSourceMethodCount ; k++ )
2684                                 {
2685                                     // Methode ansprechen
2686                                     const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k];
2687 
2688                                     // Nur Methoden nehmen, die nicht schon zugeordnet sind
2689                                     if( k == i || pMethodTypes[k] != STANDARD_METHOD )
2690                                         continue;
2691 
2692                                     // Name holen und auswerten
2693                                     ::rtl::OUString aMethName2 = rxMethod_k->getName();
2694                                     sal_Int32 nNameLen = aMethName2.getLength();
2695                                     sal_Int32 nCopyLen2 = (nNameLen < 6) ? nNameLen : 6;
2696                                     ::rtl::OUString aStartStr2 = aMethName2.copy( 0, nCopyLen2 );
2697                                     ::rtl::OUString aRemoveStr( RTL_CONSTASCII_USTRINGPARAM("remove" ) );
2698                                     // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!!
2699                                     if( !( aStartStr2 == aRemoveStr ) )
2700                                         continue;
2701 
2702                                     // Ist es denn der gleiche Listener?
2703                                     if( aMethName2.getLength() - aRemoveStr.getLength() <= aListenerStr.getLength() )
2704                                         continue;
2705                                     ::rtl::OUString aListenerName2 = aMethName2.copy
2706                                         ( 6, aMethName2.getLength() - aRemoveStr.getLength() - aListenerStr.getLength() );
2707                                     // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!!
2708                                     if( !( aListenerName == aListenerName2 ) )
2709                                         continue;
2710 
2711                                     // TODO: Hier koennten noch genauere Pruefungen vorgenommen werden
2712                                     // - Rueckgabe-Typ
2713                                     // - Anzahl und Art der Parameter
2714 
2715 
2716                                     // Methoden sind als Listener-Schnittstelle erkannt
2717                                     rMethodConcept_i |= LISTENER;
2718                                     pLocalMethodConcepts[ k ] |= LISTENER;
2719 
2720                                     pMethodTypes[i] = ADD_LISTENER_METHOD;
2721                                     pMethodTypes[k] = REMOVE_LISTENER_METHOD;
2722                                     nListenerCount++;
2723                                 }
2724                             }
2725                         }
2726 
2727 
2728                         // Jetzt koennen noch SET-Methoden ohne zugehoerige GET-Methode existieren,
2729                         // diese muessen zu Write-Only-Properties gemachte werden.
2730                         for( i = 0 ; i < nSourceMethodCount ; i++ )
2731                         {
2732                             // Methode ansprechen
2733                             const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i];
2734 
2735                             // Nur Methoden nehmen, die nicht schon zugeordnet sind
2736                             if( pMethodTypes[i] != STANDARD_METHOD )
2737                                 continue;
2738 
2739                             // Namen besorgen
2740                             aMethName = rxMethod_i->getName();
2741 
2742                             // Wenn der Name zu kurz ist, wird's sowieso nichts
2743                             if( aMethName.getLength() <= 3 )
2744                                 continue;
2745 
2746                             // Ist es eine set-Methode ohne zugehoerige get-Methode?
2747                             aStartStr = aMethName.copy( 0, 3 );
2748                             if( aStartStr == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("set")) )
2749                             {
2750                                 // Namen der potentiellen Property
2751                                 aPropName = aMethName.copy( 3 );
2752 
2753                                 // set-Methode muss void returnen
2754                                 Reference<XIdlClass> xSetRetType = rxMethod_i->getReturnType();
2755                                 if( xSetRetType->getTypeClass() != TypeClass_VOID )
2756                                 {
2757                                     continue;
2758                                 }
2759 
2760                                 // set-Methode darf nur einen Parameter haben
2761                                 Sequence< Reference<XIdlClass> > setParams = rxMethod_i->getParameterTypes();
2762                                 sal_Int32 nParamCount = setParams.getLength();
2763                                 if( nParamCount != 1 )
2764                                 {
2765                                     continue;
2766                                 }
2767 
2768                                 // Haben wir den Namen schon?
2769                                 IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
2770                                 if( !( aIt == rPropNameMap.end() ) )
2771                                 {
2772                                     /* TODO:
2773                                     OSL_TRACE(
2774                                         String( "Introspection: Property \"" ) +
2775                                         OOUStringToString( aPropName, CHARSET_SYSTEM ) +
2776                                         String( "\" found more than once" ) );
2777                                         */
2778                                     continue;
2779                                 }
2780 
2781                                 // Alles klar, es ist eine Write-Only-Property
2782                                 pLocalMethodConcepts[ i ] = PROPERTY;
2783 
2784                                 pMethodTypes[i] = GETSET_METHOD;
2785                                 Reference<XIdlClass> xGetRetType = setParams.getConstArray()[0];
2786 
2787                                 // Ist die PropertySequence gross genug?
2788                                 pAccess->checkPropertyArraysSize
2789                                     ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount );
2790 
2791                                 // In eigenes Property-Array eintragen
2792                                 Property& rProp = pAllPropArray[ rPropCount ];
2793                                 rProp.Name = aPropName;
2794                                 rProp.Handle = rPropCount;
2795                                 rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() );
2796                                 rProp.Attributes = 0;   // PROPERTY_WRITEONLY ???
2797 
2798                                 // Neuer Eintrag in die Hashtable
2799                                 rPropNameMap[ aPropName ] = rPropCount;
2800 
2801                                 // Tabelle fuer XExactName pflegen
2802                                 rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName;
2803 
2804                                 // set-Methode merken
2805                                 pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq2,
2806                                     pInterfaces2, rPropCount );
2807                                 pInterfaces2[ rPropCount ] = rxMethod_i;
2808 
2809                                 // Art der Property merken
2810                                 pMapTypeArray[ rPropCount ] = MAP_SETONLY;
2811                                 pPropertyConceptArray[ rPropCount ] = METHODS;
2812                                 pAccess->mnMethodPropCount++;
2813 
2814                                 // Count pflegen
2815                                 rPropCount++;
2816                             }
2817                         }
2818 
2819 
2820                         //********************************************************************
2821 
2822                         // 4. Methoden in die Gesamt-Sequence uebernehmen
2823 
2824                         // Wieviele Methoden muessen in die Method-Sequence?
2825                         sal_Int32 nExportedMethodCount = 0;
2826                         sal_Int32 nSupportedListenerCount = 0;
2827                         for( i = 0 ; i < nSourceMethodCount ; i++ )
2828                         {
2829                             if( pMethodTypes[ i ] != INVALID_METHOD )
2830                             {
2831                                 nExportedMethodCount++;
2832                             }
2833                             if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2834                             {
2835                                 nSupportedListenerCount++;
2836                             }
2837                         }
2838 
2839                         // Sequences im Access-Objekt entsprechend aufbohren
2840                         pAccess->maAllMethodSeq.realloc( nExportedMethodCount + iAllExportedMethod );
2841                         pAccess->maMethodConceptSeq.realloc( nExportedMethodCount + iAllExportedMethod );
2842                         pAccess->maSupportedListenerSeq.realloc( nSupportedListenerCount + iAllSupportedListener );
2843 
2844                         // Methoden reinschreiben
2845                         Reference<XIdlMethod>* pDestMethods = pAccess->maAllMethodSeq.getArray();
2846                         sal_Int32* pMethodConceptArray = pAccess->maMethodConceptSeq.getArray();
2847                         Type* pListenerClassRefs = pAccess->maSupportedListenerSeq.getArray();
2848                         for( i = 0 ; i < nSourceMethodCount ; i++ )
2849                         {
2850                             if( pMethodTypes[ i ] != INVALID_METHOD )
2851                             {
2852                                 // Methode ansprechen
2853                                 const Reference<XIdlMethod>& rxMethod = pSourceMethods[i];
2854 
2855                                 // Namen in Hashtable eintragen, wenn nicht schon bekannt
2856                                 ::rtl::OUString aMethName2 = rxMethod->getName();
2857                                 IntrospectionNameMap::iterator aIt = rMethodNameMap.find( aMethName2 );
2858                                 if( aIt == rMethodNameMap.end() )
2859                                 {
2860                                     // Eintragen
2861                                     rMethodNameMap[ aMethName2 ] = iAllExportedMethod;
2862 
2863                                     // Tabelle fuer XExactName pflegen
2864                                     rLowerToExactNameMap[ toLower( aMethName2 ) ] = aMethName2;
2865                                 }
2866                                 else
2867                                 {
2868                                     sal_Int32 iHashResult = (*aIt).second;
2869 
2870                                     Reference<XIdlMethod> xExistingMethod = pDestMethods[ iHashResult ];
2871 
2872                                     Reference< XIdlClass > xExistingMethClass =
2873                                         xExistingMethod->getDeclaringClass();
2874                                     Reference< XIdlClass > xNewMethClass = rxMethod->getDeclaringClass();
2875                                     if( xExistingMethClass->equals( xNewMethClass ) )
2876                                         continue;
2877                                 }
2878 
2879                                 pDestMethods[ iAllExportedMethod ] = rxMethod;
2880 
2881                                 // Wenn kein Concept gesetzt wurde, ist die Methode "normal"
2882                                 sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ];
2883                                 if( !rMethodConcept_i )
2884                                     rMethodConcept_i = MethodConcept_NORMAL_IMPL;
2885                                 pMethodConceptArray[ iAllExportedMethod ] = rMethodConcept_i;
2886                                 iAllExportedMethod++;
2887                             }
2888                             if( pMethodTypes[ i ] == ADD_LISTENER_METHOD )
2889                             {
2890                                 // Klasse des Listeners ermitteln
2891                                 const Reference<XIdlMethod>& rxMethod = pSourceMethods[i];
2892 
2893                                 // void als Default-Klasse eintragen
2894                                 Reference<XIdlClass> xListenerClass = TypeToIdlClass( getCppuVoidType(), m_xSMgr );
2895                                 // ALT: Reference<XIdlClass> xListenerClass = Void_getReflection()->getIdlClass();
2896 
2897                                 // 1. Moeglichkeit: Parameter nach einer Listener-Klasse durchsuchen
2898                                 // Nachteil: Superklassen muessen rekursiv durchsucht werden
2899                                 Sequence< Reference<XIdlClass> > aParams = rxMethod->getParameterTypes();
2900                                 const Reference<XIdlClass>* pParamArray2 = aParams.getConstArray();
2901 
2902                                 Reference<XIdlClass> xEventListenerClass = TypeToIdlClass( getCppuType( (Reference<XEventListener>*) NULL ), m_xSMgr );
2903                                 // ALT: Reference<XIdlClass> xEventListenerClass = XEventListener_getReflection()->getIdlClass();
2904                                 sal_Int32 nParamCount = aParams.getLength();
2905                                 sal_Int32 k;
2906                                 for( k = 0 ; k < nParamCount ; k++ )
2907                                 {
2908                                     const Reference<XIdlClass>& rxClass = pParamArray2[k];
2909 
2910                                     // Sind wir von einem Listener abgeleitet?
2911                                     if( rxClass->equals( xEventListenerClass ) ||
2912                                         isDerivedFrom( rxClass, xEventListenerClass ) )
2913                                     {
2914                                         xListenerClass = rxClass;
2915                                         break;
2916                                     }
2917                                 }
2918 
2919                                 // 2. Moeglichkeit: Namen der Methode auswerden
2920                                 // Nachteil: geht nicht bei Test-Listenern, die es nicht gibt
2921                                 //aMethName = rxMethod->getName();
2922                                 //aListenerName = aMethName.Copy( 3, aMethName.Len()-8-3 );
2923                                 //Reference<XIdlClass> xListenerClass = reflection->forName( aListenerName );
2924                                 Type aListenerType( TypeClass_INTERFACE, xListenerClass->getName() );
2925                                 pListenerClassRefs[ iAllSupportedListener ] = aListenerType;
2926                                 iAllSupportedListener++;
2927                             }
2928                         }
2929 
2930                         // Wenn in diesem Durchlauf XInterface-Methoden
2931                         // dabei waren, diese zukuenftig ignorieren
2932                         if( bFoundXInterface )
2933                             bXInterfaceIsInvalid = sal_True;
2934 
2935                         delete[] pMethodTypes;
2936                         delete[] pLocalMethodConcepts;
2937                     }
2938 
2939                     // Super-Klasse(n) vorhanden? Dann dort fortsetzen
2940                     Sequence< Reference<XIdlClass> > aSuperClassSeq = xImplClass2->getSuperclasses();
2941 
2942                     // Zur Zeit wird nur von einer Superklasse ausgegangen
2943                     if( aSuperClassSeq.getLength() >= 1 )
2944                     {
2945                         xImplClass2 = aSuperClassSeq.getConstArray()[0];
2946                         OSL_ENSURE( xImplClass2.is(), "super class null" );
2947                     }
2948                     else
2949                     {
2950                         xImplClass2 = NULL;
2951                     }
2952                 }
2953             }
2954 
2955             // Anzahl der exportierten Methoden uebernehmen und Sequences anpassen
2956             // (kann abweichen, weil doppelte Methoden erst nach der Ermittlung
2957             //  von nExportedMethodCount herausgeworfen werden)
2958             sal_Int32& rMethCount = pAccess->mnMethCount;
2959             rMethCount = iAllExportedMethod;
2960             pAccess->maAllMethodSeq.realloc( rMethCount );
2961             pAccess->maMethodConceptSeq.realloc( rMethCount );
2962 
2963             // Groesse der Property-Sequences anpassen
2964             pAccess->maAllPropertySeq.realloc( rPropCount );
2965             pAccess->maPropertyConceptSeq.realloc( rPropCount );
2966             pAccess->maMapTypeSeq.realloc( rPropCount );
2967 
2968             // Ende der Schleife ueber alle vom ClassProvider angegebenen Klassen
2969         }
2970     }
2971     // Bei structs Fields als Properties registrieren
2972     else //if( eType == TypeClass_STRUCT )
2973     {
2974         // Ist es ein Interface oder eine struct?
2975         //Reference<XIdlClass> xClassRef = aToInspectObj.getReflection()->getIdlClass();
2976         Reference<XIdlClass> xClassRef = TypeToIdlClass( aToInspectObj.getValueType(), m_xSMgr );
2977         if( !xClassRef.is() )
2978         {
2979             OSL_ENSURE( sal_False, "Can't get XIdlClass from Reflection" );
2980             return pAccess;
2981         }
2982 
2983         // Felder holen
2984         Sequence< Reference<XIdlField> > fields = xClassRef->getFields();
2985         const Reference<XIdlField>* pFields = fields.getConstArray();
2986         sal_Int32 nLen = fields.getLength();
2987 
2988         for( i = 0 ; i < nLen ; i++ )
2989         {
2990             Reference<XIdlField> xField = pFields[i];
2991             Reference<XIdlClass> xPropType = xField->getType();
2992             ::rtl::OUString aPropName = xField->getName();
2993 
2994             // Ist die PropertySequence gross genug?
2995             pAccess->checkPropertyArraysSize
2996                 ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount );
2997 
2998             // In eigenes Property-Array eintragen
2999             Property& rProp = pAllPropArray[ rPropCount ];
3000             rProp.Name = aPropName;
3001             rProp.Handle = rPropCount;
3002             rProp.Type = Type( xPropType->getTypeClass(), xPropType->getName() );
3003             FieldAccessMode eAccessMode = xField->getAccessMode();
3004             rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY ||
3005                                 eAccessMode == FieldAccessMode_CONST)
3006                                 ? READONLY : 0;
3007 
3008             //FieldAccessMode eAccessMode = xField->getAccessMode();
3009             //rProp.Attributes = (eAccessMode == FieldAccessMode::READONLY || eAccessMode == CONST)
3010                 //? PropertyAttribute::READONLY : 0;
3011 
3012             // Namen in Hashtable eintragen
3013             rPropNameMap[ aPropName ] = rPropCount;
3014 
3015             // Tabelle fuer XExactName pflegen
3016             rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName;
3017 
3018             // Field merken
3019             pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq1,
3020                 pInterfaces1, rPropCount );
3021             pInterfaces1[ rPropCount ] = xField;
3022 
3023             // Art der Property merken
3024             pMapTypeArray[ rPropCount ] = MAP_FIELD;
3025             pPropertyConceptArray[ rPropCount ] = ATTRIBUTES;
3026             pAccess->mnAttributePropCount++;
3027 
3028             // Count pflegen
3029             rPropCount++;
3030         }
3031     }
3032 
3033     // Property-Sequence auf die richtige Laenge bringen
3034     pAccess->maAllPropertySeq.realloc( pAccess->mnPropCount );
3035 
3036     return pAccess;
3037 }
3038 
3039 //*************************************************************************
3040 Reference< XInterface > SAL_CALL ImplIntrospection_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr )
3041     throw( RuntimeException )
3042 {
3043     Reference< XInterface > xService = (OWeakObject*)(OComponentHelper*)new ImplIntrospection( rSMgr );
3044     return xService;
3045 }
3046 
3047 }
3048 
3049 extern "C"
3050 {
3051 //==================================================================================================
3052 void SAL_CALL component_getImplementationEnvironment(
3053     const sal_Char ** ppEnvTypeName, uno_Environment ** )
3054 {
3055     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
3056 }
3057 //==================================================================================================
3058 void * SAL_CALL component_getFactory(
3059     const sal_Char * pImplName, void * pServiceManager, void * )
3060 {
3061     void * pRet = 0;
3062 
3063     if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0)
3064     {
3065         Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory(
3066             reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
3067             ::rtl::OUString::createFromAscii( pImplName ),
3068             stoc_inspect::ImplIntrospection_CreateInstance,
3069             stoc_inspect::ImplIntrospection::getSupportedServiceNames_Static() ) );
3070 
3071         if (xFactory.is())
3072         {
3073             xFactory->acquire();
3074             pRet = xFactory.get();
3075         }
3076     }
3077 
3078     return pRet;
3079 }
3080 }
3081 
3082 
3083