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