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