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