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