/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_stoc.hxx" #include // Schalter fuer Introspection-Caching #ifndef OS2 #define USE_INTROSPECTION_CACHE #endif #ifdef USE_INTROSPECTION_CACHE #define INTROSPECTION_CACHE_MAX_SIZE 100 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::reflection; using namespace com::sun::star::container; using namespace com::sun::star::registry; using namespace com::sun::star::beans; using namespace com::sun::star::beans::PropertyAttribute; using namespace com::sun::star::beans::PropertyConcept; using namespace com::sun::star::beans::MethodConcept; using namespace cppu; using namespace osl; #define IMPLEMENTATION_NAME "com.sun.star.comp.stoc.Introspection" #define SERVICE_NAME "com.sun.star.beans.Introspection" namespace stoc_inspect { typedef WeakImplHelper3< XIntrospectionAccess, XMaterialHolder, XExactName > IntrospectionAccessHelper; //================================================================================================== // Spezial-Wert fuer Method-Concept, um "normale" Funktionen kennzeichnen zu koennen #define MethodConcept_NORMAL_IMPL 0x80000000 // Methode zur Feststellung, ob eine Klasse von einer anderen abgeleitet ist sal_Bool isDerivedFrom( Reference xToTestClass, Reference xDerivedFromClass ) { Sequence< Reference > aClassesSeq = xToTestClass->getSuperclasses(); const Reference* pClassesArray = aClassesSeq.getConstArray(); sal_Int32 nSuperClassCount = aClassesSeq.getLength(); sal_Int32 i; for( i = 0 ; i < nSuperClassCount ; i++ ) { const Reference& rxClass = pClassesArray[i]; if( xDerivedFromClass->equals( rxClass ) ) { // Treffer return sal_True; } else { // Rekursiv weitersuchen return isDerivedFrom( rxClass, xDerivedFromClass ); } } return sal_False; } //======================================================================== // *** Klassifizierung der Properties (kein enum, um Sequence verwenden zu koennen) *** // Properties aus einem PropertySet-Interface #define MAP_PROPERTY_SET 0 // Properties aus Fields #define MAP_FIELD 1 // Properties, die durch get/set-Methoden beschrieben werden #define MAP_GETSET 2 // Properties, die nur eine set-Methode haben #define MAP_SETONLY 3 // Schrittweite, in der die Groesse der Sequences angepasst wird #define ARRAY_SIZE_STEP 20 //************************************** //*** IntrospectionAccessStatic_Impl *** //************************************** // Entspricht dem alten IntrospectionAccessImpl, bildet jetzt den statischen // Anteil des neuen Instanz-bezogenen ImplIntrospectionAccess // ACHTUNG !!! Von Hand refcounten !!! // Hashtable fuer die Suche nach Namen struct hashName_Impl { size_t operator()(const ::rtl::OUString Str) const { return (size_t)Str.hashCode(); } }; struct eqName_Impl { sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const { return ( Str1 == Str2 ); } }; typedef std::hash_map < ::rtl::OUString, sal_Int32, hashName_Impl, eqName_Impl > IntrospectionNameMap; // Hashtable zur Zuordnung der exakten Namen zu den zu Lower-Case // konvertierten Namen, dient zur Unterst�tzung von XExactName typedef std::hash_map < ::rtl::OUString, ::rtl::OUString, hashName_Impl, eqName_Impl > LowerToExactNameMap; class ImplIntrospectionAccess; class IntrospectionAccessStatic_Impl { friend class ImplIntrospection; friend class ImplIntrospectionAccess; // CoreReflection halten Reference< XIdlReflection > mxCoreReflection; // InterfaceSequences, um Zusatz-Infos zu einer Property speichern zu koennen. // z.B. das Field bei MAP_FIELD, die get/set-Methoden bei MAP_GETSET usw. Sequence< Reference > aInterfaceSeq1; Sequence< Reference > aInterfaceSeq2; // Hashtables fuer die Namen IntrospectionNameMap maPropertyNameMap; IntrospectionNameMap maMethodNameMap; LowerToExactNameMap maLowerToExactNameMap; // Sequence aller Properties, auch zum Liefern aus getProperties() Sequence maAllPropertySeq; // Mapping der Properties auf Zugriffs-Arten Sequence maMapTypeSeq; // Klassifizierung der gefundenen Methoden Sequence maPropertyConceptSeq; // Anzahl der Properties sal_Int32 mnPropCount; // Anzahl der Properties, die den jeweiligen Konzepten zugeordnet sind //sal_Int32 mnDangerousPropCount; sal_Int32 mnPropertySetPropCount; sal_Int32 mnAttributePropCount; sal_Int32 mnMethodPropCount; // Flag, ob ein FastPropertySet unterstuetzt wird sal_Bool mbFastPropSet; // Original-Handles eines FastPropertySets sal_Int32* mpOrgPropertyHandleArray; // MethodSequence, die alle Methoden aufnimmt Sequence< Reference > maAllMethodSeq; // Klassifizierung der gefundenen Methoden Sequence maMethodConceptSeq; // Anzahl der Methoden sal_Int32 mnMethCount; // Sequence der Listener, die angemeldet werden koennen Sequence< Type > maSupportedListenerSeq; // BaseInit (soll spaeter in der Applikation erfolgen!) void BaseInit( void ); // Hilfs-Methoden zur Groessen-Anpassung der Sequences void checkPropertyArraysSize ( Property*& rpAllPropArray, sal_Int16*& rpMapTypeArray, sal_Int32*& rpPropertyConceptArray, sal_Int32 iNextIndex ); void checkInterfaceArraySize( Sequence< Reference >& rSeq, Reference*& rpInterfaceArray, sal_Int32 iNextIndex ); // RefCount sal_Int32 nRefCount; public: IntrospectionAccessStatic_Impl( Reference< XIdlReflection > xCoreReflection_ ); ~IntrospectionAccessStatic_Impl() { delete[] mpOrgPropertyHandleArray; } sal_Int32 getPropertyIndex( const ::rtl::OUString& aPropertyName ) const; sal_Int32 getMethodIndex( const ::rtl::OUString& aMethodName ) const; void acquire() { nRefCount++; } void release() { nRefCount--; if( nRefCount <= 0 ) delete this; } // Methoden von XIntrospectionAccess (ALT, jetzt nur Impl) void setPropertyValue(const Any& obj, const ::rtl::OUString& aPropertyName, const Any& aValue) const; // void setPropertyValue(Any& obj, const ::rtl::OUString& aPropertyName, const Any& aValue) const; Any getPropertyValue(const Any& obj, const ::rtl::OUString& aPropertyName) const; void setPropertyValueByIndex(const Any& obj, sal_Int32 nIndex, const Any& aValue) const; // void setPropertyValueByIndex(Any& obj, sal_Int32 nIndex, const Any& aValue) const; Any getPropertyValueByIndex(const Any& obj, sal_Int32 nIndex) const; Sequence getProperties(void) const { return maAllPropertySeq; } Sequence< Reference > getMethods(void) const { return maAllMethodSeq; } Sequence< Type > getSupportedListeners(void) const { return maSupportedListenerSeq; } Sequence getPropertyConcepts(void) const { return maPropertyConceptSeq; } Sequence getMethodConcepts(void) const { return maMethodConceptSeq; } }; // Ctor IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlReflection > xCoreReflection_ ) : mxCoreReflection( xCoreReflection_ ) { aInterfaceSeq1.realloc( ARRAY_SIZE_STEP ); aInterfaceSeq2.realloc( ARRAY_SIZE_STEP ); // Property-Daten maAllPropertySeq.realloc( ARRAY_SIZE_STEP ); maMapTypeSeq.realloc( ARRAY_SIZE_STEP ); maPropertyConceptSeq.realloc( ARRAY_SIZE_STEP ); mbFastPropSet = sal_False; mpOrgPropertyHandleArray = NULL; mnPropCount = 0; //mnDangerousPropCount = 0; mnPropertySetPropCount = 0; mnAttributePropCount = 0; mnMethodPropCount = 0; // Method-Daten mnMethCount = 0; // Eigenens RefCounting nRefCount = 0; } // Von Hand refcounten !!! sal_Int32 IntrospectionAccessStatic_Impl::getPropertyIndex( const ::rtl::OUString& aPropertyName ) const { sal_Int32 iHashResult = -1; IntrospectionAccessStatic_Impl* pThis = (IntrospectionAccessStatic_Impl*)this; IntrospectionNameMap::iterator aIt = pThis->maPropertyNameMap.find( aPropertyName ); if( !( aIt == pThis->maPropertyNameMap.end() ) ) iHashResult = (*aIt).second; return iHashResult; } sal_Int32 IntrospectionAccessStatic_Impl::getMethodIndex( const ::rtl::OUString& aMethodName ) const { sal_Int32 iHashResult = -1; IntrospectionAccessStatic_Impl* pThis = (IntrospectionAccessStatic_Impl*)this; IntrospectionNameMap::iterator aIt = pThis->maMethodNameMap.find( aMethodName ); if( !( aIt == pThis->maMethodNameMap.end() ) ) { iHashResult = (*aIt).second; } // #95159 Check if full qualified name matches else { sal_Int32 nSearchFrom = aMethodName.getLength(); nSearchFrom = aMethodName.getLength(); while( true ) { // Strategy: Search back until the first '_' is found sal_Int32 nFound = aMethodName.lastIndexOf( '_', nSearchFrom ); if( nFound == -1 ) break; ::rtl::OUString aPureMethodName = aMethodName.copy( nFound + 1 ); aIt = pThis->maMethodNameMap.find( aPureMethodName ); if( !( aIt == pThis->maMethodNameMap.end() ) ) { // Check if it can be a type? // Problem: Does not work if package names contain _ ?! ::rtl::OUString aStr = aMethodName.copy( 0, nFound ); ::rtl::OUString aTypeName = aStr.replace( '_', '.' ); Reference< XIdlClass > xClass = mxCoreReflection->forName( aTypeName ); if( xClass.is() ) { // If this is a valid class it could be the right method // Could be the right method, type has to be checked iHashResult = (*aIt).second; const Reference* pMethods = maAllMethodSeq.getConstArray(); const Reference xMethod = pMethods[ iHashResult ]; Reference< XIdlClass > xMethClass = xMethod->getDeclaringClass(); if( xClass->equals( xMethClass ) ) { break; } else { iHashResult = -1; // Could also be another method with the same name // Iterate over all methods sal_Int32 nLen = maAllMethodSeq.getLength(); for( int i = 0 ; i < nLen ; ++i ) { const Reference xMethod2 = pMethods[ i ]; ::rtl::OUString aTestClassName = xMethod2->getDeclaringClass()->getName(); ::rtl::OUString aTestMethodName = xMethod2->getName(); if( xMethod2->getName() == aPureMethodName ) { Reference< XIdlClass > xMethClass2 = xMethod2->getDeclaringClass(); if( xClass->equals( xMethClass2 ) ) { iHashResult = i; break; } } } if( iHashResult != -1 ) break; } } } nSearchFrom = nFound - 1; if( nSearchFrom < 0 ) break; } } return iHashResult; } void IntrospectionAccessStatic_Impl::setPropertyValue( const Any& obj, const ::rtl::OUString& aPropertyName, const Any& aValue ) const //void IntrospectionAccessStatic_Impl::setPropertyValue( Any& obj, const ::rtl::OUString& aPropertyName, const Any& aValue ) const { sal_Int32 i = getPropertyIndex( aPropertyName ); if( i != -1 ) setPropertyValueByIndex( obj, (sal_Int32)i, aValue ); else throw UnknownPropertyException(); } void IntrospectionAccessStatic_Impl::setPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const //void IntrospectionAccessStatic_Impl::setPropertyValueByIndex( Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const { // Handelt es sich bei dem uebergebenen Objekt ueberhaupt um was passendes? TypeClass eObjType = obj.getValueType().getTypeClass(); Reference xInterface; if( eObjType == TypeClass_INTERFACE ) { xInterface = *( Reference*)obj.getValue(); } else if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) ) { throw IllegalArgumentException(); } // Flags pruefen const Property* pProps = maAllPropertySeq.getConstArray(); if( (pProps[ nSequenceIndex ].Attributes & READONLY) != 0 ) { throw UnknownPropertyException(); } const sal_Int16* pMapTypeArray = maMapTypeSeq.getConstArray(); switch( pMapTypeArray[ nSequenceIndex ] ) { case MAP_PROPERTY_SET: { // Property besorgen const Property& rProp = maAllPropertySeq.getConstArray()[ nSequenceIndex ]; // Interface-Parameter auf den richtigen Typ bringen sal_Bool bUseCopy = sal_False; Any aRealValue; TypeClass eValType = aValue.getValueType().getTypeClass(); if( eValType == TypeClass_INTERFACE ) { Type aPropType = rProp.Type; ::rtl::OUString aTypeName( aPropType.getTypeName() ); Reference< XIdlClass > xPropClass = mxCoreReflection->forName( aTypeName ); //Reference xPropClass = rProp.Type; if( xPropClass.is() && xPropClass->getTypeClass() == TypeClass_INTERFACE ) { Reference valInterface = *(Reference*)aValue.getValue(); if( valInterface.is() ) { //Any queryInterface( const Type& rType ); aRealValue = valInterface->queryInterface( aPropType ); if( aRealValue.hasValue() ) bUseCopy = sal_True; } } } // Haben wir ein FastPropertySet und ein gueltiges Handle? // ACHTUNG: An dieser Stelle wird ausgenutzt, dass das PropertySet // zu Beginn des Introspection-Vorgangs abgefragt wird. sal_Int32 nOrgHandle; if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 ) { // PropertySet-Interface holen Reference xFastPropSet = Reference::query( xInterface ); if( xFastPropSet.is() ) { xFastPropSet->setFastPropertyValue( nOrgHandle, bUseCopy ? aRealValue : aValue ); } else { // throw UnknownPropertyException } } // sonst eben das normale nehmen else { // PropertySet-Interface holen Reference xPropSet = Reference::query( xInterface ); if( xPropSet.is() ) { xPropSet->setPropertyValue( rProp.Name, bUseCopy ? aRealValue : aValue ); } else { // throw UnknownPropertyException } } } break; case MAP_FIELD: { Reference xField = (XIdlField*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get()); Reference xField2(xField, UNO_QUERY); if( xField2.is() ) { xField2->set( (Any&)obj, aValue ); // IllegalArgumentException // NullPointerException } else if( xField.is() ) { xField->set( obj, aValue ); // IllegalArgumentException // NullPointerException } else { // throw IllegalArgumentException(); } } break; case MAP_GETSET: case MAP_SETONLY: { // set-Methode holen Reference xMethod = (XIdlMethod*)(aInterfaceSeq2.getConstArray()[ nSequenceIndex ].get()); if( xMethod.is() ) { Sequence args( 1 ); args.getArray()[0] = aValue; xMethod->invoke( obj, args ); } else { // throw IllegalArgumentException(); } } break; } } Any IntrospectionAccessStatic_Impl::getPropertyValue( const Any& obj, const ::rtl::OUString& aPropertyName ) const { sal_Int32 i = getPropertyIndex( aPropertyName ); if( i != -1 ) return getPropertyValueByIndex( obj, i ); throw UnknownPropertyException(); } Any IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex) const { Any aRet; // Handelt es sich bei dem uebergebenen Objekt ueberhaupt um was passendes? TypeClass eObjType = obj.getValueType().getTypeClass(); Reference xInterface; if( eObjType == TypeClass_INTERFACE ) { xInterface = *(Reference*)obj.getValue(); } else if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) ) { // throw IllegalArgumentException(); return aRet; } const sal_Int16* pMapTypeArray = maMapTypeSeq.getConstArray(); switch( pMapTypeArray[ nSequenceIndex ] ) { case MAP_PROPERTY_SET: { // Property besorgen const Property& rProp = maAllPropertySeq.getConstArray()[ nSequenceIndex ]; // Haben wir ein FastPropertySet und ein gueltiges Handle? // ACHTUNG: An dieser Stelle wird ausgenutzt, dass das PropertySet // zu Beginn des Introspection-Vorgangs abgefragt wird. sal_Int32 nOrgHandle; if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 ) { // PropertySet-Interface holen Reference xFastPropSet = Reference::query( xInterface ); if( xFastPropSet.is() ) { aRet = xFastPropSet->getFastPropertyValue( nOrgHandle); } else { // throw UnknownPropertyException return aRet; } } // sonst eben das normale nehmen else { // PropertySet-Interface holen Reference xPropSet = Reference::query( xInterface ); if( xPropSet.is() ) { aRet = xPropSet->getPropertyValue( rProp.Name ); } else { // throw UnknownPropertyException return aRet; } } } break; case MAP_FIELD: { Reference xField = (XIdlField*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get()); if( xField.is() ) { aRet = xField->get( obj ); // IllegalArgumentException // NullPointerException } else { // throw IllegalArgumentException(); return aRet; } } break; case MAP_GETSET: { // get-Methode holen Reference xMethod = (XIdlMethod*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get()); if( xMethod.is() ) { Sequence args; aRet = xMethod->invoke( obj, args ); } else { // throw IllegalArgumentException(); return aRet; } } break; case MAP_SETONLY: // get-Methode gibt es nicht // throw WriteOnlyPropertyException(); return aRet; } return aRet; } // Hilfs-Methoden zur Groessen-Anpassung der Sequences void IntrospectionAccessStatic_Impl::checkPropertyArraysSize ( Property*& rpAllPropArray, sal_Int16*& rpMapTypeArray, sal_Int32*& rpPropertyConceptArray, sal_Int32 iNextIndex ) { sal_Int32 nLen = maAllPropertySeq.getLength(); if( iNextIndex >= nLen ) { maAllPropertySeq.realloc( nLen + ARRAY_SIZE_STEP ); rpAllPropArray = maAllPropertySeq.getArray(); maMapTypeSeq.realloc( nLen + ARRAY_SIZE_STEP ); rpMapTypeArray = maMapTypeSeq.getArray(); maPropertyConceptSeq.realloc( nLen + ARRAY_SIZE_STEP ); rpPropertyConceptArray = maPropertyConceptSeq.getArray(); } } void IntrospectionAccessStatic_Impl::checkInterfaceArraySize( Sequence< Reference >& rSeq, Reference*& rpInterfaceArray, sal_Int32 iNextIndex ) { sal_Int32 nLen = rSeq.getLength(); if( iNextIndex >= nLen ) { // Neue Groesse mit ARRAY_SIZE_STEP abgleichen sal_Int32 nMissingSize = iNextIndex - nLen + 1; sal_Int32 nSteps = nMissingSize / ARRAY_SIZE_STEP + 1; sal_Int32 nNewSize = nLen + nSteps * ARRAY_SIZE_STEP; rSeq.realloc( nNewSize ); rpInterfaceArray = rSeq.getArray(); } } //******************************* //*** ImplIntrospectionAccess *** //******************************* // Neue Impl-Klasse im Rahmen der Introspection-Umstellung auf Instanz-gebundene // Introspection mit Property-Zugriff ueber XPropertySet. Die alte Klasse // ImplIntrospectionAccess lebt als IntrospectionAccessStatic_Impl class ImplIntrospectionAccess : public IntrospectionAccessHelper { friend class ImplIntrospection; // Untersuchtes Objekt Any maInspectedObject; // Als Interface Reference mxIface; // Statische Daten der Introspection IntrospectionAccessStatic_Impl* mpStaticImpl; // Adapter-Implementation WeakReference< XInterface > maAdapter; // Letzte Sequence, die bei getProperties geliefert wurde (Optimierung) Sequence maLastPropertySeq; sal_Int32 mnLastPropertyConcept; // Letzte Sequence, die bei getMethods geliefert wurde (Optimierung) Sequence > maLastMethodSeq; sal_Int32 mnLastMethodConcept; public: ImplIntrospectionAccess( const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ ); ~ImplIntrospectionAccess(); // Methoden von XIntrospectionAccess virtual sal_Int32 SAL_CALL getSuppliedMethodConcepts(void) throw( RuntimeException ); virtual sal_Int32 SAL_CALL getSuppliedPropertyConcepts(void) throw( RuntimeException ); virtual Property SAL_CALL getProperty(const ::rtl::OUString& Name, sal_Int32 PropertyConcepts) throw( NoSuchElementException, RuntimeException ); virtual sal_Bool SAL_CALL hasProperty(const ::rtl::OUString& Name, sal_Int32 PropertyConcepts) throw( RuntimeException ); virtual Sequence< Property > SAL_CALL getProperties(sal_Int32 PropertyConcepts) throw( RuntimeException ); virtual Reference SAL_CALL getMethod(const ::rtl::OUString& Name, sal_Int32 MethodConcepts) throw( NoSuchMethodException, RuntimeException ); virtual sal_Bool SAL_CALL hasMethod(const ::rtl::OUString& Name, sal_Int32 MethodConcepts) throw( RuntimeException ); virtual Sequence< Reference > SAL_CALL getMethods(sal_Int32 MethodConcepts) throw( RuntimeException ); virtual Sequence< Type > SAL_CALL getSupportedListeners(void) throw( RuntimeException ); using OWeakObject::queryAdapter; virtual Reference SAL_CALL queryAdapter( const Type& rType ) throw( IllegalTypeException, RuntimeException ); // Methoden von XMaterialHolder virtual Any SAL_CALL getMaterial(void) throw(RuntimeException); // Methoden von XExactName virtual ::rtl::OUString SAL_CALL getExactName( const ::rtl::OUString& rApproximateName ) throw( RuntimeException ); }; ImplIntrospectionAccess::ImplIntrospectionAccess ( const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ ) : maInspectedObject( obj ), mpStaticImpl( pStaticImpl_ ), maAdapter() { mpStaticImpl->acquire(); // Objekt als Interface merken, wenn moeglich TypeClass eType = maInspectedObject.getValueType().getTypeClass(); if( eType == TypeClass_INTERFACE ) mxIface = *(Reference*)maInspectedObject.getValue(); mnLastPropertyConcept = -1; mnLastMethodConcept = -1; } ImplIntrospectionAccess::~ImplIntrospectionAccess() { mpStaticImpl->release(); } //******************************* //*** ImplIntrospectionAdapter *** //******************************* // Neue Impl-Klasse im Rahmen der Introspection-Umstellung auf Instanz-gebundene // Introspection mit Property-Zugriff ueber XPropertySet. Die alte Klasse // ImplIntrospectionAccess lebt als IntrospectionAccessStatic_Impl class ImplIntrospectionAdapter : public XPropertySet, public XFastPropertySet, public XPropertySetInfo, public XNameContainer, public XIndexContainer, public XEnumerationAccess, public XIdlArray, public OWeakObject { // Parent-Objekt ::rtl::Reference< ImplIntrospectionAccess > mpAccess; // Untersuchtes Objekt const Any& mrInspectedObject; // Statische Daten der Introspection IntrospectionAccessStatic_Impl* mpStaticImpl; // Objekt als Interface Reference mxIface; // Original-Interfaces des Objekts Reference mxObjElementAccess; Reference mxObjNameContainer; Reference mxObjNameAccess; Reference mxObjIndexAccess; Reference mxObjIndexContainer; Reference mxObjEnumerationAccess; Reference mxObjIdlArray; public: ImplIntrospectionAdapter( ImplIntrospectionAccess* pAccess_, const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ ); ~ImplIntrospectionAdapter(); // Methoden von XInterface virtual Any SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException ); virtual void SAL_CALL acquire() throw() { OWeakObject::acquire(); } virtual void SAL_CALL release() throw() { OWeakObject::release(); } // Methoden von XPropertySet virtual Reference SAL_CALL getPropertySetInfo() throw( RuntimeException ); virtual void SAL_CALL setPropertyValue(const ::rtl::OUString& aPropertyName, const Any& aValue) throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ); virtual Any SAL_CALL getPropertyValue(const ::rtl::OUString& aPropertyName) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); virtual void SAL_CALL addPropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); virtual void SAL_CALL removePropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); virtual void SAL_CALL addVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); virtual void SAL_CALL removeVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); // Methoden von XFastPropertySet virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const Any& aValue) throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ); virtual Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); // Methoden von XPropertySetInfo virtual Sequence< Property > SAL_CALL getProperties(void) throw( RuntimeException ); virtual Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException ); virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException ); // Methoden von XElementAccess virtual Type SAL_CALL getElementType(void) throw( RuntimeException ); virtual sal_Bool SAL_CALL hasElements(void) throw( RuntimeException ); // Methoden von XNameAccess virtual Any SAL_CALL getByName(const ::rtl::OUString& Name) throw( NoSuchElementException, WrappedTargetException, RuntimeException ); virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames(void) throw( RuntimeException ); virtual sal_Bool SAL_CALL hasByName(const ::rtl::OUString& Name) throw( RuntimeException ); // Methoden von XNameContainer virtual void SAL_CALL insertByName(const ::rtl::OUString& Name, const Any& Element) throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException ); virtual void SAL_CALL replaceByName(const ::rtl::OUString& Name, const Any& Element) throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException ); virtual void SAL_CALL removeByName(const ::rtl::OUString& Name) throw( NoSuchElementException, WrappedTargetException, RuntimeException ); // Methoden von XIndexAccess virtual sal_Int32 SAL_CALL getCount(void) throw( RuntimeException ); virtual Any SAL_CALL getByIndex(sal_Int32 Index) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ); // Methoden von XIndexContainer virtual void SAL_CALL insertByIndex(sal_Int32 Index, const Any& Element) throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ); virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element) throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ); virtual void SAL_CALL removeByIndex(sal_Int32 Index) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ); // Methoden von XEnumerationAccess virtual Reference SAL_CALL createEnumeration(void) throw( RuntimeException ); // Methoden von XIdlArray virtual void SAL_CALL realloc(Any& array, sal_Int32 length) throw( IllegalArgumentException, RuntimeException ); virtual sal_Int32 SAL_CALL getLen(const Any& array) throw( IllegalArgumentException, RuntimeException ); virtual Any SAL_CALL get(const Any& array, sal_Int32 index) throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException ); virtual void SAL_CALL set(Any& array, sal_Int32 index, const Any& value) throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException ); }; ImplIntrospectionAdapter::ImplIntrospectionAdapter( ImplIntrospectionAccess* pAccess_, const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ ) : mpAccess( pAccess_), mrInspectedObject( obj ), mpStaticImpl( pStaticImpl_ ) { mpStaticImpl->acquire(); // Objekt als Interfaceholen TypeClass eType = mrInspectedObject.getValueType().getTypeClass(); if( eType == TypeClass_INTERFACE ) { mxIface = *( Reference< XInterface >*)mrInspectedObject.getValue(); mxObjElementAccess = Reference::query( mxIface ); mxObjNameAccess = Reference::query( mxIface ); mxObjNameContainer = Reference::query( mxIface ); mxObjIndexAccess = Reference::query( mxIface ); mxObjIndexContainer = Reference::query( mxIface ); mxObjEnumerationAccess = Reference::query( mxIface ); mxObjIdlArray = Reference::query( mxIface ); } } ImplIntrospectionAdapter::~ImplIntrospectionAdapter() { mpStaticImpl->release(); } // Methoden von XInterface Any SAL_CALL ImplIntrospectionAdapter::queryInterface( const Type& rType ) throw( RuntimeException ) { Any aRet( ::cppu::queryInterface( rType, static_cast< XPropertySet * >( this ), static_cast< XFastPropertySet * >( this ), static_cast< XPropertySetInfo * >( this ) ) ); if( !aRet.hasValue() ) aRet = OWeakObject::queryInterface( rType ); if( !aRet.hasValue() ) { // Wrapper fuer die Objekt-Interfaces if( ( mxObjElementAccess.is() && (aRet = ::cppu::queryInterface ( rType, static_cast< XElementAccess* >( static_cast< XNameAccess* >( this ) ) ) ).hasValue() ) || ( mxObjNameAccess.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() ) || ( mxObjNameContainer.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() ) || ( mxObjIndexAccess.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() ) || ( mxObjIndexContainer.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() ) || ( mxObjEnumerationAccess .is() && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() ) || ( mxObjIdlArray.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() ) ) { } } return aRet; } //*************************************************** //*** Implementation von ImplIntrospectionAdapter *** //*************************************************** // Methoden von XPropertySet Reference ImplIntrospectionAdapter::getPropertySetInfo(void) throw( RuntimeException ) { return (XPropertySetInfo *)this; } void ImplIntrospectionAdapter::setPropertyValue(const ::rtl::OUString& aPropertyName, const Any& aValue) throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ) { mpStaticImpl->setPropertyValue( mrInspectedObject, aPropertyName, aValue ); } Any ImplIntrospectionAdapter::getPropertyValue(const ::rtl::OUString& aPropertyName) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) { return mpStaticImpl->getPropertyValue( mrInspectedObject, aPropertyName ); } void ImplIntrospectionAdapter::addPropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) { if( mxIface.is() ) { Reference xPropSet = Reference::query( mxIface ); //Reference xPropSet( mxIface, USR_QUERY ); if( xPropSet.is() ) xPropSet->addPropertyChangeListener(aPropertyName, aListener); } } void ImplIntrospectionAdapter::removePropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) { if( mxIface.is() ) { Reference xPropSet = Reference::query( mxIface ); //Reference xPropSet( mxIface, USR_QUERY ); if( xPropSet.is() ) xPropSet->removePropertyChangeListener(aPropertyName, aListener); } } void ImplIntrospectionAdapter::addVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) { if( mxIface.is() ) { Reference xPropSet = Reference::query( mxIface ); //Reference xPropSet( mxIface, USR_QUERY ); if( xPropSet.is() ) xPropSet->addVetoableChangeListener(aPropertyName, aListener); } } void ImplIntrospectionAdapter::removeVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) { if( mxIface.is() ) { Reference xPropSet = Reference::query( mxIface ); if( xPropSet.is() ) xPropSet->removeVetoableChangeListener(aPropertyName, aListener); } } // Methoden von XFastPropertySet void ImplIntrospectionAdapter::setFastPropertyValue(sal_Int32, const Any&) throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ) { } Any ImplIntrospectionAdapter::getFastPropertyValue(sal_Int32) throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) { return Any(); } // Methoden von XPropertySetInfo Sequence< Property > ImplIntrospectionAdapter::getProperties(void) throw( RuntimeException ) { return mpStaticImpl->getProperties(); } Property ImplIntrospectionAdapter::getPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException ) { return mpAccess->getProperty( Name, PropertyConcept::ALL ); } sal_Bool ImplIntrospectionAdapter::hasPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException ) { return mpAccess->hasProperty( Name, PropertyConcept::ALL ); } // Methoden von XElementAccess Type ImplIntrospectionAdapter::getElementType(void) throw( RuntimeException ) { return mxObjElementAccess->getElementType(); } sal_Bool ImplIntrospectionAdapter::hasElements(void) throw( RuntimeException ) { return mxObjElementAccess->hasElements(); } // Methoden von XNameAccess Any ImplIntrospectionAdapter::getByName(const ::rtl::OUString& Name) throw( NoSuchElementException, WrappedTargetException, RuntimeException ) { return mxObjNameAccess->getByName( Name ); } Sequence< ::rtl::OUString > ImplIntrospectionAdapter::getElementNames(void) throw( RuntimeException ) { return mxObjNameAccess->getElementNames(); } sal_Bool ImplIntrospectionAdapter::hasByName(const ::rtl::OUString& Name) throw( RuntimeException ) { return mxObjNameAccess->hasByName( Name ); } // Methoden von XNameContainer void ImplIntrospectionAdapter::insertByName(const ::rtl::OUString& Name, const Any& Element) throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException ) { mxObjNameContainer->insertByName( Name, Element ); } void ImplIntrospectionAdapter::replaceByName(const ::rtl::OUString& Name, const Any& Element) throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException ) { mxObjNameContainer->replaceByName( Name, Element ); } void ImplIntrospectionAdapter::removeByName(const ::rtl::OUString& Name) throw( NoSuchElementException, WrappedTargetException, RuntimeException ) { mxObjNameContainer->removeByName( Name ); } // Methoden von XIndexAccess // Schon in XNameAccess: virtual Reference getElementType(void) const sal_Int32 ImplIntrospectionAdapter::getCount(void) throw( RuntimeException ) { return mxObjIndexAccess->getCount(); } Any ImplIntrospectionAdapter::getByIndex(sal_Int32 Index) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) { return mxObjIndexAccess->getByIndex( Index ); } // Methoden von XIndexContainer void ImplIntrospectionAdapter::insertByIndex(sal_Int32 Index, const Any& Element) throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) { mxObjIndexContainer->insertByIndex( Index, Element ); } void ImplIntrospectionAdapter::replaceByIndex(sal_Int32 Index, const Any& Element) throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) { mxObjIndexContainer->replaceByIndex( Index, Element ); } void ImplIntrospectionAdapter::removeByIndex(sal_Int32 Index) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) { mxObjIndexContainer->removeByIndex( Index ); } // Methoden von XEnumerationAccess // Schon in XNameAccess: virtual Reference getElementType(void) const; Reference ImplIntrospectionAdapter::createEnumeration(void) throw( RuntimeException ) { return mxObjEnumerationAccess->createEnumeration(); } // Methoden von XIdlArray void ImplIntrospectionAdapter::realloc(Any& array, sal_Int32 length) throw( IllegalArgumentException, RuntimeException ) { mxObjIdlArray->realloc( array, length ); } sal_Int32 ImplIntrospectionAdapter::getLen(const Any& array) throw( IllegalArgumentException, RuntimeException ) { return mxObjIdlArray->getLen( array ); } Any ImplIntrospectionAdapter::get(const Any& array, sal_Int32 index) throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException ) { return mxObjIdlArray->get( array, index ); } void ImplIntrospectionAdapter::set(Any& array, sal_Int32 index, const Any& value) throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException ) { mxObjIdlArray->set( array, index, value ); } //************************************************** //*** Implementation von ImplIntrospectionAccess *** //************************************************** // Methoden von XIntrospectionAccess sal_Int32 ImplIntrospectionAccess::getSuppliedMethodConcepts(void) throw( RuntimeException ) { return MethodConcept::DANGEROUS | PROPERTY | LISTENER | ENUMERATION | NAMECONTAINER | INDEXCONTAINER; } sal_Int32 ImplIntrospectionAccess::getSuppliedPropertyConcepts(void) throw( RuntimeException ) { return PropertyConcept::DANGEROUS | PROPERTYSET | ATTRIBUTES | METHODS; } Property ImplIntrospectionAccess::getProperty(const ::rtl::OUString& Name, sal_Int32 PropertyConcepts) throw( NoSuchElementException, RuntimeException ) { Property aRet; sal_Int32 i = mpStaticImpl->getPropertyIndex( Name ); sal_Bool bFound = sal_False; if( i != -1 ) { sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts().getConstArray()[ i ]; if( (PropertyConcepts & nConcept) != 0 ) { const Property* pProps = mpStaticImpl->getProperties().getConstArray(); aRet = pProps[ i ]; bFound = sal_True; } } if( !bFound ) throw NoSuchElementException() ; return aRet; } sal_Bool ImplIntrospectionAccess::hasProperty(const ::rtl::OUString& Name, sal_Int32 PropertyConcepts) throw( RuntimeException ) { sal_Int32 i = mpStaticImpl->getPropertyIndex( Name ); sal_Bool bRet = sal_False; if( i != -1 ) { sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts().getConstArray()[ i ]; if( (PropertyConcepts & nConcept) != 0 ) bRet = sal_True; } return bRet; } Sequence< Property > ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts) throw( RuntimeException ) { // Wenn alle unterstuetzten Konzepte gefordert werden, Sequence einfach durchreichen sal_Int32 nAllSupportedMask = PROPERTYSET | ATTRIBUTES | METHODS; if( ( PropertyConcepts & nAllSupportedMask ) == nAllSupportedMask ) { return mpStaticImpl->getProperties(); } // Gleiche Sequence wie beim vorigen mal? if( mnLastPropertyConcept == PropertyConcepts ) { return maLastPropertySeq; } // Anzahl der zu liefernden Properties sal_Int32 nCount = 0; // Es gibt zur Zeit keine DANGEROUS-Properties // if( PropertyConcepts & DANGEROUS ) // nCount += mpStaticImpl->mnDangerousPropCount; if( PropertyConcepts & PROPERTYSET ) nCount += mpStaticImpl->mnPropertySetPropCount; if( PropertyConcepts & ATTRIBUTES ) nCount += mpStaticImpl->mnAttributePropCount; if( PropertyConcepts & METHODS ) nCount += mpStaticImpl->mnMethodPropCount; // Sequence entsprechend der geforderten Anzahl reallocieren ImplIntrospectionAccess* pThis = (ImplIntrospectionAccess*)this; // const umgehen pThis->maLastPropertySeq.realloc( nCount ); Property* pDestProps = pThis->maLastPropertySeq.getArray(); // Alle Properties durchgehen und entsprechend der Concepte uebernehmen Sequence aPropSeq = mpStaticImpl->getProperties(); const Property* pSourceProps = aPropSeq.getConstArray(); const sal_Int32* pConcepts = mpStaticImpl->getPropertyConcepts().getConstArray(); sal_Int32 nLen = aPropSeq.getLength(); sal_Int32 iDest = 0; for( sal_Int32 i = 0 ; i < nLen ; i++ ) { sal_Int32 nConcept = pConcepts[ i ]; if( nConcept & PropertyConcepts ) pDestProps[ iDest++ ] = pSourceProps[ i ]; /* // Property mit Concepts ausgeben ::rtl::OUString aPropName = pSourceProps[ i ].Name; String aNameStr = OOUStringToString(aPropName, CHARSET_SYSTEM); String ConceptStr; if( nConcept & PROPERTYSET ) ConceptStr += "PROPERTYSET"; if( nConcept & ATTRIBUTES ) ConceptStr += "ATTRIBUTES"; if( nConcept & METHODS ) ConceptStr += "METHODS"; printf( "Property %ld: %s, Concept = %s\n", i, aNameStr.GetStr(), ConceptStr.GetStr() ); */ } // PropertyConcept merken, dies entspricht maLastPropertySeq pThis->mnLastPropertyConcept = PropertyConcepts; // Zusammengebastelte Sequence liefern return maLastPropertySeq; } Reference ImplIntrospectionAccess::getMethod(const ::rtl::OUString& Name, sal_Int32 MethodConcepts) throw( NoSuchMethodException, RuntimeException ) { Reference xRet; sal_Int32 i = mpStaticImpl->getMethodIndex( Name ); if( i != -1 ) { sal_Int32 nConcept = mpStaticImpl->getMethodConcepts().getConstArray()[ i ]; if( (MethodConcepts & nConcept) != 0 ) { const Reference* pMethods = mpStaticImpl->getMethods().getConstArray(); xRet = pMethods[i]; } } if( !xRet.is() ) throw NoSuchMethodException(); return xRet; } sal_Bool ImplIntrospectionAccess::hasMethod(const ::rtl::OUString& Name, sal_Int32 MethodConcepts) throw( RuntimeException ) { sal_Int32 i = mpStaticImpl->getMethodIndex( Name ); sal_Bool bRet = sal_False; if( i != -1 ) { sal_Int32 nConcept = mpStaticImpl->getMethodConcepts().getConstArray()[ i ]; if( (MethodConcepts & nConcept) != 0 ) bRet = sal_True; } return bRet; } Sequence< Reference > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts) throw( RuntimeException ) { ImplIntrospectionAccess* pThis = (ImplIntrospectionAccess*)this; // const umgehen // Wenn alle unterstuetzten Konzepte gefordert werden, Sequence einfach durchreichen sal_Int32 nAllSupportedMask = MethodConcept::DANGEROUS | PROPERTY | LISTENER | ENUMERATION | NAMECONTAINER | INDEXCONTAINER | MethodConcept_NORMAL_IMPL; if( ( MethodConcepts & nAllSupportedMask ) == nAllSupportedMask ) { return mpStaticImpl->getMethods(); } // Gleiche Sequence wie beim vorigen mal? if( mnLastMethodConcept == MethodConcepts ) { return maLastMethodSeq; } // Methoden-Sequences besorgen Sequence< Reference > aMethodSeq = mpStaticImpl->getMethods(); const Reference* pSourceMethods = aMethodSeq.getConstArray(); const sal_Int32* pConcepts = mpStaticImpl->getMethodConcepts().getConstArray(); sal_Int32 nLen = aMethodSeq.getLength(); // Sequence entsprechend der geforderten Anzahl reallocieren // Anders als bei den Properties kann die Anzahl nicht durch // Zaehler in inspect() vorher ermittelt werden, da Methoden // mehreren Konzepten angehoeren koennen pThis->maLastMethodSeq.realloc( nLen ); Reference* pDestMethods = pThis->maLastMethodSeq.getArray(); // Alle Methods durchgehen und entsprechend der Concepte uebernehmen sal_Int32 iDest = 0; for( sal_Int32 i = 0 ; i < nLen ; i++ ) { sal_Int32 nConcept = pConcepts[ i ]; if( nConcept & MethodConcepts ) pDestMethods[ iDest++ ] = pSourceMethods[ i ]; #if OSL_DEBUG_LEVEL > 0 static bool debug = false; if ( debug ) { // Methode mit Concepts ausgeben const Reference< XIdlMethod >& rxMethod = pSourceMethods[ i ]; ::rtl::OString aNameStr = ::rtl::OUStringToOString( rxMethod->getName(), osl_getThreadTextEncoding() ); ::rtl::OString ConceptStr; if( nConcept & MethodConcept::DANGEROUS ) ConceptStr += "DANGEROUS |"; if( nConcept & MethodConcept::PROPERTY ) ConceptStr += "PROPERTY |"; if( nConcept & MethodConcept::LISTENER ) ConceptStr += "LISTENER |"; if( nConcept & MethodConcept::ENUMERATION ) ConceptStr += "ENUMERATION |"; if( nConcept & MethodConcept::NAMECONTAINER ) ConceptStr += "NAMECONTAINER |"; if( nConcept & MethodConcept::INDEXCONTAINER ) ConceptStr += "INDEXCONTAINER |"; OSL_TRACE( "Method %ld: %s, Concepts = %s", i, aNameStr.getStr(), ConceptStr.getStr() ); } #endif } // Auf die richtige Laenge bringen pThis->maLastMethodSeq.realloc( iDest ); // MethodConcept merken, dies entspricht maLastMethodSeq pThis->mnLastMethodConcept = MethodConcepts; // Zusammengebastelte Sequence liefern return maLastMethodSeq; } Sequence< Type > ImplIntrospectionAccess::getSupportedListeners(void) throw( RuntimeException ) { return mpStaticImpl->getSupportedListeners(); } Reference SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type& rType ) throw( IllegalTypeException, RuntimeException ) { // Gibt es schon einen Adapter? Reference< XInterface > xAdapter( maAdapter ); if( !xAdapter.is() ) { xAdapter = *( new ImplIntrospectionAdapter( this, maInspectedObject, mpStaticImpl ) ); maAdapter = xAdapter; } Reference xRet; xAdapter->queryInterface( rType ) >>= xRet; return xRet; } // Methoden von XMaterialHolder Any ImplIntrospectionAccess::getMaterial(void) throw(RuntimeException) { return maInspectedObject; } // Hilfs-Funktion zur LowerCase-Wandlung eines ::rtl::OUString ::rtl::OUString toLower( ::rtl::OUString aUStr ) { // Tabelle fuer XExactName pflegen ::rtl::OUString aOWStr( aUStr.getStr() ); ::rtl::OUString aOWLowerStr = aOWStr.toAsciiLowerCase(); ::rtl::OUString aLowerUStr( aOWLowerStr.getStr() ); return aLowerUStr; } // Methoden von XExactName ::rtl::OUString ImplIntrospectionAccess::getExactName( const ::rtl::OUString& rApproximateName ) throw( RuntimeException ) { ::rtl::OUString aRetStr; LowerToExactNameMap::iterator aIt = mpStaticImpl->maLowerToExactNameMap.find( toLower( rApproximateName ) ); if( !( aIt == mpStaticImpl->maLowerToExactNameMap.end() ) ) aRetStr = (*aIt).second; return aRetStr; } //----------------------------------------------------------------------------- #ifdef USE_INTROSPECTION_CACHE struct hashIntrospectionKey_Impl { Sequence< Reference > aIdlClasses; Reference xPropInfo; Reference xImplClass; sal_Int32 nHitCount; void IncHitCount() const { ((hashIntrospectionKey_Impl*)this)->nHitCount++; } hashIntrospectionKey_Impl() : nHitCount( 0 ) {} hashIntrospectionKey_Impl( const Sequence< Reference > & rIdlClasses, const Reference & rxPropInfo, const Reference & rxImplClass ); }; hashIntrospectionKey_Impl::hashIntrospectionKey_Impl ( const Sequence< Reference > & rIdlClasses, const Reference & rxPropInfo, const Reference & rxImplClass ) : aIdlClasses( rIdlClasses ) , xPropInfo( rxPropInfo ) , xImplClass( rxImplClass ) , nHitCount( 0 ) {} struct hashIntrospectionAccessCache_Impl { size_t operator()(const hashIntrospectionKey_Impl & rObj ) const { return (size_t)rObj.xImplClass.get() ^ (size_t)rObj.xPropInfo.get(); } bool operator()( const hashIntrospectionKey_Impl & rObj1, const hashIntrospectionKey_Impl & rObj2 ) const { if( rObj1.xPropInfo != rObj2.xPropInfo || rObj1.xImplClass != rObj2.xImplClass ) return sal_False; sal_Int32 nCount1 = rObj1.aIdlClasses.getLength(); sal_Int32 nCount2 = rObj2.aIdlClasses.getLength(); if( nCount1 != nCount2 ) return sal_False; const Reference* pRefs1 = rObj1.aIdlClasses.getConstArray(); const Reference* pRefs2 = rObj2.aIdlClasses.getConstArray(); return memcmp( pRefs1, pRefs2, nCount1 * sizeof( Reference ) ) == 0; } }; typedef std::hash_map < hashIntrospectionKey_Impl, IntrospectionAccessStatic_Impl*, hashIntrospectionAccessCache_Impl, hashIntrospectionAccessCache_Impl > IntrospectionAccessCacheMap_Impl; class IntrospectionAccessCacheMap : public IntrospectionAccessCacheMap_Impl { public: ~IntrospectionAccessCacheMap() { IntrospectionAccessCacheMap::iterator iter = begin(); IntrospectionAccessCacheMap::iterator stop = this->end(); while( iter != stop ) { (*iter).second->release(); (*iter).second = NULL; iter++; } } }; // For XTypeProvider struct hashTypeProviderKey_Impl { Reference xPropInfo; Sequence< sal_Int8 > maImpIdSeq; sal_Int32 nHitCount; void IncHitCount() const { ((hashTypeProviderKey_Impl*)this)->nHitCount++; } hashTypeProviderKey_Impl() : nHitCount( 0 ) {} hashTypeProviderKey_Impl( const Reference & rxPropInfo, const Sequence< sal_Int8 > & aImpIdSeq_ ); }; hashTypeProviderKey_Impl::hashTypeProviderKey_Impl ( const Reference & rxPropInfo, const Sequence< sal_Int8 > & aImpIdSeq_ ) : xPropInfo( rxPropInfo ) , maImpIdSeq( aImpIdSeq_ ) , nHitCount( 0 ) {} struct TypeProviderAccessCache_Impl { size_t operator()(const hashTypeProviderKey_Impl & rObj ) const; bool operator()( const hashTypeProviderKey_Impl & rObj1, const hashTypeProviderKey_Impl & rObj2 ) const { if( rObj1.xPropInfo != rObj2.xPropInfo ) return sal_False; bool bEqual = false; sal_Int32 nLen1 = rObj1.maImpIdSeq.getLength(); sal_Int32 nLen2 = rObj2.maImpIdSeq.getLength(); if( nLen1 == nLen2 && nLen1 > 0 ) { const sal_Int8* pId1 = rObj1.maImpIdSeq.getConstArray(); const sal_Int8* pId2 = rObj2.maImpIdSeq.getConstArray(); bEqual = (memcmp( pId1, pId2, nLen1 * sizeof( sal_Int8 ) ) == 0 ); } return bEqual; } }; size_t TypeProviderAccessCache_Impl::operator()(const hashTypeProviderKey_Impl & rObj ) const { const sal_Int32* pBytesAsInt32Array = (const sal_Int32*)rObj.maImpIdSeq.getConstArray(); sal_Int32 nLen = rObj.maImpIdSeq.getLength(); sal_Int32 nCount32 = nLen / 4; sal_Int32 nMod32 = nLen % 4; // XOR with full 32 bit values sal_Int32 nId32 = 0; sal_Int32 i; for( i = 0 ; i < nCount32 ; i++ ) nId32 ^= *(pBytesAsInt32Array++); // XOR with remaining byte values if( nMod32 ) { const sal_Int8* pBytes = (const sal_Int8*)pBytesAsInt32Array; sal_Int8* pInt8_Id32 = (sal_Int8*)&nId32; for( i = 0 ; i < nMod32 ; i++ ) *(pInt8_Id32++) ^= *(pBytes++); } return (size_t)nId32; } typedef std::hash_map < hashTypeProviderKey_Impl, IntrospectionAccessStatic_Impl*, TypeProviderAccessCache_Impl, TypeProviderAccessCache_Impl > TypeProviderAccessCacheMap_Impl; class TypeProviderAccessCacheMap : public TypeProviderAccessCacheMap_Impl { public: ~TypeProviderAccessCacheMap() { TypeProviderAccessCacheMap::iterator iter = begin(); TypeProviderAccessCacheMap::iterator stop = this->end(); while( iter != stop ) { (*iter).second->release(); (*iter).second = NULL; iter++; } } }; #endif //************************* //*** ImplIntrospection *** //************************* struct OIntrospectionMutex { Mutex m_mutex; }; class ImplIntrospection : public XIntrospection , public XServiceInfo , public OIntrospectionMutex , public OComponentHelper { friend class ImplMergeIntrospection; friend class ImplMVCIntrospection; // Implementation der Introspection. // ACHTUNG: RefCounting von Hand !!! IntrospectionAccessStatic_Impl* implInspect(const Any& aToInspectObj); // Save XMultiServiceFactory from createComponent Reference m_xSMgr; // CoreReflection halten Reference< XIdlReflection > mxCoreReflection; // Klassen, deren Methoden eine spezielle Rolle spielen Reference mxElementAccessClass; Reference mxNameContainerClass; Reference mxNameAccessClass; Reference mxIndexContainerClass; Reference mxIndexAccessClass; Reference mxEnumerationAccessClass; Reference mxInterfaceClass; Reference mxAggregationClass; sal_Bool mbDisposed; #ifdef USE_INTROSPECTION_CACHE sal_uInt16 mnCacheEntryCount; sal_uInt16 mnTPCacheEntryCount; IntrospectionAccessCacheMap* mpCache; TypeProviderAccessCacheMap* mpTypeProviderCache; #endif public: ImplIntrospection( const Reference & rXSMgr ); // Methoden von XInterface virtual Any SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException ); virtual void SAL_CALL acquire() throw() { OComponentHelper::acquire(); } virtual void SAL_CALL release() throw() { OComponentHelper::release(); } // XTypeProvider Sequence< Type > SAL_CALL getTypes( ) throw( RuntimeException ); Sequence SAL_CALL getImplementationId( ) throw( RuntimeException ); // XServiceInfo ::rtl::OUString SAL_CALL getImplementationName() throw(); sal_Bool SAL_CALL supportsService(const ::rtl::OUString& ServiceName) throw(); Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(void) throw(); static ::rtl::OUString SAL_CALL getImplementationName_Static( ); static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static(void) throw(); // Methoden von XIntrospection virtual Reference SAL_CALL inspect(const Any& aToInspectObj) throw( RuntimeException ); protected: // some XComponent part from OComponentHelper virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); }; enum MethodType { STANDARD_METHOD, // normale Methode, kein Bezug zu Properties oder Listenern GETSET_METHOD, // gehoert zu einer get/set-Property ADD_LISTENER_METHOD, // add-Methode einer Listener-Schnittstelle REMOVE_LISTENER_METHOD, // remove-Methode einer Listener-Schnittstelle INVALID_METHOD // Methode, deren Klasse nicht beruecksichtigt wird, z.B. XPropertySet }; // Ctor ImplIntrospection::ImplIntrospection( const Reference & rXSMgr ) : OComponentHelper( m_mutex ) , m_xSMgr( rXSMgr ) { #ifdef USE_INTROSPECTION_CACHE mnCacheEntryCount = 0; mnTPCacheEntryCount = 0; mpCache = NULL; mpTypeProviderCache = NULL; #endif // Spezielle Klassen holen // Reference< XInterface > xServiceIface = m_xSMgr->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.CoreReflection")) ); // if( xServiceIface.is() ) // mxCoreReflection = Reference< XIdlReflection >::query( xServiceIface ); Reference< XPropertySet > xProps( rXSMgr, UNO_QUERY ); OSL_ASSERT( xProps.is() ); if (xProps.is()) { Reference< XComponentContext > xContext; xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext; OSL_ASSERT( xContext.is() ); if (xContext.is()) { xContext->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection") ) ) >>= mxCoreReflection; OSL_ENSURE( mxCoreReflection.is(), "### CoreReflection singleton not accessible!?" ); } } if (! mxCoreReflection.is()) { throw DeploymentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessible") ), Reference< XInterface >() ); } mxElementAccessClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XElementAccess")) ); mxNameContainerClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XNameContainer")) ); mxNameAccessClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XNameAccess")) ); mxIndexContainerClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XIndexContainer")) ); mxIndexAccessClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XIndexAccess")) ); mxEnumerationAccessClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XEnumerationAccess")) ); mxInterfaceClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XInterface")) ); mxAggregationClass = mxCoreReflection->forName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XAggregation")) ); mbDisposed = sal_False; } // XComponent void ImplIntrospection::dispose() throw(::com::sun::star::uno::RuntimeException) { OComponentHelper::dispose(); #ifdef USE_INTROSPECTION_CACHE // Cache loeschen delete mpCache; mpCache = NULL; delete mpTypeProviderCache; mpTypeProviderCache = NULL; #endif mxElementAccessClass = NULL; mxNameContainerClass = NULL; mxNameAccessClass = NULL; mxIndexContainerClass = NULL; mxIndexAccessClass = NULL; mxEnumerationAccessClass = NULL; mxInterfaceClass = NULL; mxAggregationClass = NULL; mbDisposed = sal_True; } //----------------------------------------------------------------------------- // XInterface Any ImplIntrospection::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException) { Any aRet( ::cppu::queryInterface( rType, static_cast< XIntrospection * >( this ), static_cast< XServiceInfo * >( this ) ) ); return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType )); } // XTypeProvider Sequence< Type > ImplIntrospection::getTypes() throw( RuntimeException ) { static OTypeCollection * s_pTypes = 0; if (! s_pTypes) { MutexGuard aGuard( Mutex::getGlobalMutex() ); if (! s_pTypes) { static OTypeCollection s_aTypes( ::getCppuType( (const Reference< XIntrospection > *)0 ), ::getCppuType( (const Reference< XServiceInfo > *)0 ), OComponentHelper::getTypes() ); s_pTypes = &s_aTypes; } } return s_pTypes->getTypes(); } Sequence< sal_Int8 > ImplIntrospection::getImplementationId() throw( RuntimeException ) { static OImplementationId * s_pId = 0; if (! s_pId) { MutexGuard aGuard( Mutex::getGlobalMutex() ); if (! s_pId) { static OImplementationId s_aId; s_pId = &s_aId; } } return s_pId->getImplementationId(); } // XServiceInfo ::rtl::OUString ImplIntrospection::getImplementationName() throw() { return getImplementationName_Static(); } // XServiceInfo sal_Bool ImplIntrospection::supportsService(const ::rtl::OUString& ServiceName) throw() { Sequence< ::rtl::OUString > aSNL = getSupportedServiceNames(); const ::rtl::OUString * pArray = aSNL.getConstArray(); for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) if( pArray[i] == ServiceName ) return sal_True; return sal_False; } // XServiceInfo Sequence< ::rtl::OUString > ImplIntrospection::getSupportedServiceNames(void) throw() { return getSupportedServiceNames_Static(); } //************************************************************************* // Helper XServiceInfo ::rtl::OUString ImplIntrospection::getImplementationName_Static( ) { return ::rtl::OUString::createFromAscii( IMPLEMENTATION_NAME ); } // ORegistryServiceManager_Static Sequence< ::rtl::OUString > ImplIntrospection::getSupportedServiceNames_Static(void) throw() { Sequence< ::rtl::OUString > aSNS( 1 ); aSNS.getArray()[0] = ::rtl::OUString::createFromAscii( SERVICE_NAME ); return aSNS; } //************************************************************************* // Methoden von XIntrospection Reference ImplIntrospection::inspect(const Any& aToInspectObj) throw( RuntimeException ) { Reference xAccess; if ( aToInspectObj.getValueType().getTypeClass() == TypeClass_TYPE ) { Type aType; aToInspectObj >>= aType; Reference< XIdlClass > xIdlClass = mxCoreReflection->forName(((Type*)(aToInspectObj.getValue()))->getTypeName()); if ( xIdlClass.is() ) { Any aRealInspectObj; aRealInspectObj <<= xIdlClass; IntrospectionAccessStatic_Impl* pStaticImpl = implInspect( aRealInspectObj ); if( pStaticImpl ) xAccess = new ImplIntrospectionAccess( aRealInspectObj, pStaticImpl ); } } else { IntrospectionAccessStatic_Impl* pStaticImpl = implInspect( aToInspectObj ); if( pStaticImpl ) xAccess = new ImplIntrospectionAccess( aToInspectObj, pStaticImpl ); } return xAccess; } //----------------------------------------------------------------------------- // Hashtable fuer Pruefung auf mehrfache Beruecksichtigung von Interfaces struct hashInterface_Impl { size_t operator()(const void* p) const { return (size_t)p; } }; struct eqInterface_Impl { bool operator()(const void* p1, const void* p2) const { return ( p1 == p2 ); } }; typedef std::hash_map < void*, void*, hashInterface_Impl, eqInterface_Impl > CheckedInterfacesMap; // TODO: Spaeter auslagern Reference TypeToIdlClass( const Type& rType, const Reference< XMultiServiceFactory > & xMgr ) { static Reference< XIdlReflection > xRefl; // void als Default-Klasse eintragen Reference xRetClass; typelib_TypeDescription * pTD = 0; rType.getDescription( &pTD ); if( pTD ) { ::rtl::OUString sOWName( pTD->pTypeName ); if( !xRefl.is() ) { xRefl = Reference< XIdlReflection >( xMgr->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.CoreReflection")) ), UNO_QUERY ); OSL_ENSURE( xRefl.is(), "### no corereflection!" ); } xRetClass = xRefl->forName( sOWName ); } return xRetClass; } // Implementation der Introspection. IntrospectionAccessStatic_Impl* ImplIntrospection::implInspect(const Any& aToInspectObj) { MutexGuard aGuard( m_mutex ); // Wenn die Introspection schon disposed ist, wird nur ein leeres Ergebnis geliefert if( mbDisposed ) return NULL; // Objekt untersuchen TypeClass eType = aToInspectObj.getValueType().getTypeClass(); if( eType != TypeClass_INTERFACE && eType != TypeClass_STRUCT && eType != TypeClass_EXCEPTION ) return NULL; Reference x; if( eType == TypeClass_INTERFACE ) { // Interface aus dem Any besorgen x = *(Reference*)aToInspectObj.getValue(); if( !x.is() ) return NULL; } #ifdef USE_INTROSPECTION_CACHE // Haben wir schon eine Cache-Instanz if( !mpCache ) mpCache = new IntrospectionAccessCacheMap; if( !mpTypeProviderCache ) mpTypeProviderCache = new TypeProviderAccessCacheMap; IntrospectionAccessCacheMap& aCache = *mpCache; TypeProviderAccessCacheMap& aTPCache = *mpTypeProviderCache; // Pointer auf ggf. noetige neue IntrospectionAccess-Instanz IntrospectionAccessStatic_Impl* pAccess = NULL; #else // Pointer auf ggf. noetige neue IntrospectionAccess-Instanz IntrospectionAccessStatic_Impl* pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection ); #endif // Pruefen: Ist schon ein passendes Access-Objekt gecached? Sequence< Reference > SupportedClassSeq; Sequence< Type > SupportedTypesSeq; Reference xClassProvider; Reference xTypeProvider; Reference xImplClass; Reference xPropSetInfo; Reference xPropSet; // Bei Interfaces XTypeProvider / XIdlClassProvider- und PropertySet-Interface anfordern if( eType == TypeClass_INTERFACE ) { // XIdlClassProvider xTypeProvider = Reference::query( x ); if( xTypeProvider.is() ) { SupportedTypesSeq = xTypeProvider->getTypes(); sal_Int32 nTypeCount = SupportedTypesSeq.getLength(); if( nTypeCount ) { SupportedClassSeq.realloc( nTypeCount ); Reference* pClasses = SupportedClassSeq.getArray(); const Type* pTypes = SupportedTypesSeq.getConstArray(); for( sal_Int32 i = 0 ; i < nTypeCount ; i++ ) { pClasses[ i ] = TypeToIdlClass( pTypes[ i ], m_xSMgr ); } // TODO: Caching! } } else { // XIdlClassProvider xClassProvider = Reference::query( x ); if( xClassProvider.is() ) { SupportedClassSeq = xClassProvider->getIdlClasses(); if( SupportedClassSeq.getLength() ) xImplClass = SupportedClassSeq.getConstArray()[0]; } } // #70197, fuer InvocationAdapter: Interface-Typ im Any auch ohne // ClassProvider unterstuetzen if( !xClassProvider.is() && !xTypeProvider.is() ) { xImplClass = TypeToIdlClass( aToInspectObj.getValueType(), m_xSMgr ); SupportedClassSeq.realloc( 1 ); SupportedClassSeq.getArray()[ 0 ] = xImplClass; } xPropSet = Reference::query( x ); // Jetzt versuchen, das PropertySetInfo zu bekommen if( xPropSet.is() ) xPropSetInfo = xPropSet->getPropertySetInfo(); } else { xImplClass = TypeToIdlClass( aToInspectObj.getValueType(), m_xSMgr ); } #ifdef USE_INTROSPECTION_CACHE if( xTypeProvider.is() ) { Sequence< sal_Int8 > aImpIdSeq = xTypeProvider->getImplementationId(); sal_Int32 nIdLen = aImpIdSeq.getLength(); if( nIdLen ) { // cache only, if the descriptor class is set hashTypeProviderKey_Impl aKeySeq( xPropSetInfo, aImpIdSeq ); TypeProviderAccessCacheMap::iterator aIt = aTPCache.find( aKeySeq ); if( aIt == aTPCache.end() ) { // not found // Neue Instanz anlegen und unter dem gegebenen Key einfuegen pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection ); // RefCount von Hand erhoehen, muss beim Entfernen // aus der Hashtable wieder released werden pAccess->acquire(); // Groesse begrenzen, alten Eintrag wieder rausschmeissen if( mnTPCacheEntryCount > INTROSPECTION_CACHE_MAX_SIZE ) { // Access mit dem kleinsten HitCount suchen TypeProviderAccessCacheMap::iterator iter = aTPCache.begin(); TypeProviderAccessCacheMap::iterator end = aTPCache.end(); TypeProviderAccessCacheMap::iterator toDelete = iter; while( iter != end ) { if( (*iter).first.nHitCount < (*toDelete).first.nHitCount ) toDelete = iter; ++iter; } // Gefundenen Eintrag entfernen if( (*toDelete).second ) (*toDelete).second->release(); (*toDelete).second = NULL; aTPCache.erase( toDelete ); } else mnTPCacheEntryCount++; // Neuer Eintrage rein in die Table aKeySeq.nHitCount = 1; aTPCache[ aKeySeq ] = pAccess; } else { // Hit-Count erhoehen (*aIt).first.IncHitCount(); return (*aIt).second; } } } else if( xImplClass.is() ) { // cache only, if the descriptor class is set hashIntrospectionKey_Impl aKeySeq( SupportedClassSeq, xPropSetInfo, xImplClass ); IntrospectionAccessCacheMap::iterator aIt = aCache.find( aKeySeq ); if( aIt == aCache.end() ) { // not found // Neue Instanz anlegen und unter dem gegebenen Key einfuegen pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection ); // RefCount von Hand erhoehen, muss beim Entfernen // aus der Hashtable wieder released werden pAccess->acquire(); // Groesse begrenzen, alten Eintrag wieder rausschmeissen if( mnCacheEntryCount > INTROSPECTION_CACHE_MAX_SIZE ) { // Access mit dem kleinsten HitCount suchen IntrospectionAccessCacheMap::iterator iter = aCache.begin(); IntrospectionAccessCacheMap::iterator end = aCache.end(); IntrospectionAccessCacheMap::iterator toDelete = iter; while( iter != end ) { if( (*iter).first.nHitCount < (*toDelete).first.nHitCount ) toDelete = iter; ++iter; } // Gefundenen Eintrag entfernen if( (*toDelete).second ) (*toDelete).second->release(); (*toDelete).second = NULL; aCache.erase( toDelete ); } else mnCacheEntryCount++; // Neuer Eintrage rein in die Table aKeySeq.nHitCount = 1; aCache[ aKeySeq ] = pAccess; } else { // Hit-Count erhoehen (*aIt).first.IncHitCount(); return (*aIt).second; } } #endif // Kein Access gecached -> neu anlegen Property* pAllPropArray; Reference* pInterfaces1; Reference* pInterfaces2; sal_Int16* pMapTypeArray; sal_Int32* pPropertyConceptArray; sal_Int32 i; if( !pAccess ) pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection ); // Referenzen auf wichtige Daten von pAccess sal_Int32& rPropCount = pAccess->mnPropCount; IntrospectionNameMap& rPropNameMap = pAccess->maPropertyNameMap; IntrospectionNameMap& rMethodNameMap = pAccess->maMethodNameMap; LowerToExactNameMap& rLowerToExactNameMap = pAccess->maLowerToExactNameMap; // Schon mal Pointer auf das eigene Property-Feld holen pAllPropArray = pAccess->maAllPropertySeq.getArray(); pInterfaces1 = pAccess->aInterfaceSeq1.getArray(); pInterfaces2 = pAccess->aInterfaceSeq2.getArray(); pMapTypeArray = pAccess->maMapTypeSeq.getArray(); pPropertyConceptArray = pAccess->maPropertyConceptSeq.getArray(); //************************* //*** Analyse vornehmen *** //************************* if( eType == TypeClass_INTERFACE ) { // Zunaechst nach speziellen Interfaces suchen, die fuer // die Introspection von besonderer Bedeutung sind. // XPropertySet vorhanden? if( xPropSet.is() && xPropSetInfo.is() ) { // Gibt es auch ein FastPropertySet? Reference xDummy = Reference::query( x ); sal_Bool bFast = pAccess->mbFastPropSet = xDummy.is(); Sequence aPropSeq = xPropSetInfo->getProperties(); const Property* pProps = aPropSeq.getConstArray(); sal_Int32 nLen = aPropSeq.getLength(); // Bei FastPropertySet muessen wir uns die Original-Handles merken if( bFast ) pAccess->mpOrgPropertyHandleArray = new sal_Int32[ nLen ]; for( i = 0 ; i < nLen ; i++ ) { // Property in eigene Liste uebernehmen pAccess->checkPropertyArraysSize ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); Property& rProp = pAllPropArray[ rPropCount ]; rProp = pProps[ i ]; if( bFast ) pAccess->mpOrgPropertyHandleArray[ i ] = rProp.Handle; // PropCount als Handle fuer das eigene FastPropertySet eintragen rProp.Handle = rPropCount; // Art der Property merken pMapTypeArray[ rPropCount ] = MAP_PROPERTY_SET; pPropertyConceptArray[ rPropCount ] = PROPERTYSET; pAccess->mnPropertySetPropCount++; // Namen in Hashtable eintragen, wenn nicht schon bekannt ::rtl::OUString aPropName = rProp.Name; // Haben wir den Namen schon? IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName ); if( aIt == rPropNameMap.end() ) { // Neuer Eintrag in die Hashtable rPropNameMap[ aPropName ] = rPropCount; // Tabelle fuer XExactName pflegen rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; } else { OSL_ENSURE( sal_False, ::rtl::OString( "Introspection: Property \"" ) + ::rtl::OUStringToOString( aPropName, RTL_TEXTENCODING_ASCII_US ) + ::rtl::OString( "\" found more than once in PropertySet" ) ); } // Count pflegen rPropCount++; } } // Jetzt alle weiteren implementierten Interfaces durchgehen // Diese muessen durch das XIdlClassProvider-Interface geliefert werden. // #70197, fuer InvocationAdapter: Interface-Typ im Any auch ohne // ClassProvider unterstuetzen //if( xClassProvider.is() ) { // Indizes in die Export-Tabellen sal_Int32 iAllExportedMethod = 0; sal_Int32 iAllSupportedListener = 0; // Hashtable fuer Pruefung auf mehrfache Beruecksichtigung von Interfaces CheckedInterfacesMap aCheckedInterfacesMap; // Flag, ob XInterface-Methoden erfasst werden sollen // (das darf nur einmal erfolgen, initial zulassen) sal_Bool bXInterfaceIsInvalid = sal_False; // Flag, ob die XInterface-Methoden schon erfasst wurden. Wenn sal_True, // wird bXInterfaceIsInvalid am Ende der Iface-Schleife aktiviert und // XInterface-Methoden werden danach abgeklemmt. sal_Bool bFoundXInterface = sal_False; // Schleife ueber alle vom ClassProvider angegebenen Klassen sal_Int32 nClassCount = SupportedClassSeq.getLength(); for( sal_Int32 nIdx = 0 ; nIdx < nClassCount; nIdx++ ) { Reference xImplClass2 = SupportedClassSeq.getConstArray()[nIdx]; while( xImplClass2.is() ) { // Interfaces der Implementation holen Sequence< Reference > aClassSeq = xImplClass2->getInterfaces(); sal_Int32 nIfaceCount = aClassSeq.getLength(); aClassSeq.realloc( nIfaceCount + 1 ); aClassSeq.getArray()[ nIfaceCount ] = xImplClass2; nIfaceCount++; const Reference* pParamArray = aClassSeq.getConstArray(); for( sal_Int32 j = 0 ; j < nIfaceCount ; j++ ) { const Reference& rxIfaceClass = pParamArray[j]; // Pruefen, ob das Interface schon beruecksichtigt wurde. XInterface* pIface = SAL_STATIC_CAST( XInterface*, rxIfaceClass.get() ); if( aCheckedInterfacesMap.count( pIface ) > 0 ) { // Kennen wir schon continue; } else { // Sonst eintragen aCheckedInterfacesMap[ pIface ] = pIface; } //******************************************************************** // 2. Fields als Properties registrieren // Felder holen Sequence< Reference > fields = rxIfaceClass->getFields(); const Reference* pFields = fields.getConstArray(); sal_Int32 nLen = fields.getLength(); for( i = 0 ; i < nLen ; i++ ) { Reference xField = pFields[i]; Reference xPropType = xField->getType(); // Ist die PropertySequence gross genug? pAccess->checkPropertyArraysSize ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); // In eigenes Property-Array eintragen Property& rProp = pAllPropArray[ rPropCount ]; ::rtl::OUString aFieldName = xField->getName(); rProp.Name = aFieldName; rProp.Handle = rPropCount; Type aFieldType( xPropType->getTypeClass(), xPropType->getName() ); rProp.Type = aFieldType; FieldAccessMode eAccessMode = xField->getAccessMode(); rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY || eAccessMode == FieldAccessMode_CONST) ? READONLY : 0; // Namen in Hashtable eintragen ::rtl::OUString aPropName = rProp.Name; // Haben wir den Namen schon? IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName ); if( !( aIt == rPropNameMap.end() ) ) { /* TODO OSL_TRACE( String( "Introspection: Property \"" ) + OOUStringToString( aPropName, CHARSET_SYSTEM ) + String( "\" found more than once" ) ); */ continue; } // Neuer Eintrag in die Hashtable rPropNameMap[ aPropName ] = rPropCount; // Tabelle fuer XExactName pflegen rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; // Field merken pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq1, pInterfaces1, rPropCount ); pInterfaces1[ rPropCount ] = xField; // Art der Property merken pMapTypeArray[ rPropCount ] = MAP_FIELD; pPropertyConceptArray[ rPropCount ] = ATTRIBUTES; pAccess->mnAttributePropCount++; // Count pflegen rPropCount++; } //******************************************************************** // 3. Methoden // Zaehler fuer die gefundenen Listener sal_Int32 nListenerCount = 0; // Alle Methoden holen und merken Sequence< Reference > methods = rxIfaceClass->getMethods(); const Reference* pSourceMethods = methods.getConstArray(); sal_Int32 nSourceMethodCount = methods.getLength(); // 3. a) get/set- und Listener-Methoden suchen // Feld fuer Infos ueber die Methoden anlegen, damit spaeter leicht die Methoden // gefunden werden koennen, die nicht im Zusammenhang mit Properties oder Listenern // stehen. NEU: auch MethodConceptArray initialisieren MethodType* pMethodTypes = new MethodType[ nSourceMethodCount ]; sal_Int32* pLocalMethodConcepts = new sal_Int32[ nSourceMethodCount ]; for( i = 0 ; i < nSourceMethodCount ; i++ ) { pMethodTypes[ i ] = STANDARD_METHOD; pLocalMethodConcepts[ i ] = 0; } ::rtl::OUString aMethName; ::rtl::OUString aPropName; ::rtl::OUString aStartStr; for( i = 0 ; i < nSourceMethodCount ; i++ ) { // Methode ansprechen const Reference& rxMethod_i = pSourceMethods[i]; sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ]; // Namen besorgen aMethName = rxMethod_i->getName(); // Methoden katalogisieren // Alle (?) Methoden von XInterface filtern, damit z.B. nicht // vom Scripting aus aquire oder release gerufen werden kann if( rxMethod_i->getDeclaringClass()->equals( mxInterfaceClass ) ) { // XInterface-Methoden sind hiermit einmal beruecksichtigt bFoundXInterface = sal_True; if( bXInterfaceIsInvalid ) { pMethodTypes[ i ] = INVALID_METHOD; continue; } else { if( aMethName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("queryInterface")) ) { rMethodConcept_i |= MethodConcept::DANGEROUS; continue; } } } else if( rxMethod_i->getDeclaringClass()->equals( mxAggregationClass ) ) { if( aMethName == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("setDelegator")) ) { rMethodConcept_i |= MethodConcept::DANGEROUS; continue; } } else if( rxMethod_i->getDeclaringClass()->equals( mxElementAccessClass ) ) { rMethodConcept_i |= ( NAMECONTAINER | INDEXCONTAINER | ENUMERATION ); } else if( rxMethod_i->getDeclaringClass()->equals( mxNameContainerClass ) || rxMethod_i->getDeclaringClass()->equals( mxNameAccessClass ) ) { rMethodConcept_i |= NAMECONTAINER; } else if( rxMethod_i->getDeclaringClass()->equals( mxIndexContainerClass ) || rxMethod_i->getDeclaringClass()->equals( mxIndexAccessClass ) ) { rMethodConcept_i |= INDEXCONTAINER; } else if( rxMethod_i->getDeclaringClass()->equals( mxEnumerationAccessClass ) ) { rMethodConcept_i |= ENUMERATION; } // Wenn der Name zu kurz ist, wird's sowieso nichts if( aMethName.getLength() <= 3 ) continue; // Ist es eine get-Methode? aStartStr = aMethName.copy( 0, 3 ); if( aStartStr == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("get")) ) { // Namen der potentiellen Property aPropName = aMethName.copy( 3 ); // get-Methode darf keinen Parameter haben Sequence< Reference > getParams = rxMethod_i->getParameterTypes(); if( getParams.getLength() > 0 ) { continue; } // Haben wir den Namen schon? IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName ); if( !( aIt == rPropNameMap.end() ) ) { /* TODO OSL_TRACE( String( "Introspection: Property \"" ) + OOUStringToString( aPropName, CHARSET_SYSTEM ) + String( "\" found more than once" ) ); */ continue; } // Eine readonly-Property ist es jetzt mindestens schon rMethodConcept_i |= PROPERTY; pMethodTypes[i] = GETSET_METHOD; Reference xGetRetType = rxMethod_i->getReturnType(); // Ist die PropertySequence gross genug? pAccess->checkPropertyArraysSize ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); // In eigenes Property-Array eintragen Property& rProp = pAllPropArray[ rPropCount ]; rProp.Name = aPropName; rProp.Handle = rPropCount; rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() ); rProp.Attributes = READONLY; // Neuer Eintrag in die Hashtable rPropNameMap[ aPropName ] = rPropCount; // Tabelle fuer XExactName pflegen rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; // get-Methode merken pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq1, pInterfaces1, rPropCount ); pInterfaces1[ rPropCount ] = rxMethod_i; // Art der Property merken pMapTypeArray[ rPropCount ] = MAP_GETSET; pPropertyConceptArray[ rPropCount ] = METHODS; pAccess->mnMethodPropCount++; // Passende set-Methode suchen sal_Int32 k; for( k = 0 ; k < nSourceMethodCount ; k++ ) { // Methode ansprechen const Reference& rxMethod_k = pSourceMethods[k]; // Nur Methoden nehmen, die nicht schon zugeordnet sind if( k == i || pMethodTypes[k] != STANDARD_METHOD ) continue; // Name holen und auswerten ::rtl::OUString aMethName2 = rxMethod_k->getName(); ::rtl::OUString aStartStr2 = aMethName2.copy( 0, 3 ); // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!! if( !( aStartStr2 == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("set")) ) ) continue; // Ist es denn der gleiche Name? ::rtl::OUString aPropName2 = aMethName2.copy( 3 ); // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!! if( !( aPropName == aPropName2 ) ) continue; // set-Methode muss void returnen Reference xSetRetType = rxMethod_k->getReturnType(); if( xSetRetType->getTypeClass() != TypeClass_VOID ) { continue; } // set-Methode darf nur einen Parameter haben Sequence< Reference > setParams = rxMethod_k->getParameterTypes(); sal_Int32 nParamCount = setParams.getLength(); if( nParamCount != 1 ) { continue; } // Jetzt muss nur noch der return-Typ dem Parameter-Typ entsprechen const Reference* pParamArray2 = setParams.getConstArray(); Reference xParamType = pParamArray2[ 0 ]; if( xParamType->equals( xGetRetType ) ) { pLocalMethodConcepts[ k ] = PROPERTY; pMethodTypes[k] = GETSET_METHOD; // ReadOnly-Flag wieder loschen rProp.Attributes &= ~READONLY; // set-Methode merken pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq2, pInterfaces2, rPropCount ); pInterfaces2[ rPropCount ] = rxMethod_k; } } // Count pflegen rPropCount++; } // Ist es eine addListener-Methode? else if( aStartStr == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("add")) ) { ::rtl::OUString aListenerStr( RTL_CONSTASCII_USTRINGPARAM("Listener" ) ); // Namen der potentiellen Property sal_Int32 nStrLen = aMethName.getLength(); sal_Int32 nCopyLen = nStrLen - aListenerStr.getLength(); ::rtl::OUString aEndStr = aMethName.copy( nCopyLen > 0 ? nCopyLen : 0 ); // Endet das Teil auf Listener? // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!! if( !( aEndStr == aListenerStr ) ) continue; // Welcher Listener? ::rtl::OUString aListenerName = aMethName.copy( 3, nStrLen - aListenerStr.getLength() - 3 ); // TODO: Hier koennten noch genauere Pruefungen vorgenommen werden // - Rueckgabe-Typ // - Anzahl und Art der Parameter // Passende remove-Methode suchen, sonst gilt's nicht sal_Int32 k; for( k = 0 ; k < nSourceMethodCount ; k++ ) { // Methode ansprechen const Reference& rxMethod_k = pSourceMethods[k]; // Nur Methoden nehmen, die nicht schon zugeordnet sind if( k == i || pMethodTypes[k] != STANDARD_METHOD ) continue; // Name holen und auswerten ::rtl::OUString aMethName2 = rxMethod_k->getName(); sal_Int32 nNameLen = aMethName2.getLength(); sal_Int32 nCopyLen2 = (nNameLen < 6) ? nNameLen : 6; ::rtl::OUString aStartStr2 = aMethName2.copy( 0, nCopyLen2 ); ::rtl::OUString aRemoveStr( RTL_CONSTASCII_USTRINGPARAM("remove" ) ); // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!! if( !( aStartStr2 == aRemoveStr ) ) continue; // Ist es denn der gleiche Listener? if( aMethName2.getLength() - aRemoveStr.getLength() <= aListenerStr.getLength() ) continue; ::rtl::OUString aListenerName2 = aMethName2.copy ( 6, aMethName2.getLength() - aRemoveStr.getLength() - aListenerStr.getLength() ); // ACHTUNG: Wegen SDL-Bug NICHT != bei ::rtl::OUString verwenden !!! if( !( aListenerName == aListenerName2 ) ) continue; // TODO: Hier koennten noch genauere Pruefungen vorgenommen werden // - Rueckgabe-Typ // - Anzahl und Art der Parameter // Methoden sind als Listener-Schnittstelle erkannt rMethodConcept_i |= LISTENER; pLocalMethodConcepts[ k ] |= LISTENER; pMethodTypes[i] = ADD_LISTENER_METHOD; pMethodTypes[k] = REMOVE_LISTENER_METHOD; nListenerCount++; } } } // Jetzt koennen noch SET-Methoden ohne zugehoerige GET-Methode existieren, // diese muessen zu Write-Only-Properties gemachte werden. for( i = 0 ; i < nSourceMethodCount ; i++ ) { // Methode ansprechen const Reference& rxMethod_i = pSourceMethods[i]; // Nur Methoden nehmen, die nicht schon zugeordnet sind if( pMethodTypes[i] != STANDARD_METHOD ) continue; // Namen besorgen aMethName = rxMethod_i->getName(); // Wenn der Name zu kurz ist, wird's sowieso nichts if( aMethName.getLength() <= 3 ) continue; // Ist es eine set-Methode ohne zugehoerige get-Methode? aStartStr = aMethName.copy( 0, 3 ); if( aStartStr == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("set")) ) { // Namen der potentiellen Property aPropName = aMethName.copy( 3 ); // set-Methode muss void returnen Reference xSetRetType = rxMethod_i->getReturnType(); if( xSetRetType->getTypeClass() != TypeClass_VOID ) { continue; } // set-Methode darf nur einen Parameter haben Sequence< Reference > setParams = rxMethod_i->getParameterTypes(); sal_Int32 nParamCount = setParams.getLength(); if( nParamCount != 1 ) { continue; } // Haben wir den Namen schon? IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName ); if( !( aIt == rPropNameMap.end() ) ) { /* TODO: OSL_TRACE( String( "Introspection: Property \"" ) + OOUStringToString( aPropName, CHARSET_SYSTEM ) + String( "\" found more than once" ) ); */ continue; } // Alles klar, es ist eine Write-Only-Property pLocalMethodConcepts[ i ] = PROPERTY; pMethodTypes[i] = GETSET_METHOD; Reference xGetRetType = setParams.getConstArray()[0]; // Ist die PropertySequence gross genug? pAccess->checkPropertyArraysSize ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); // In eigenes Property-Array eintragen Property& rProp = pAllPropArray[ rPropCount ]; rProp.Name = aPropName; rProp.Handle = rPropCount; rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() ); rProp.Attributes = 0; // PROPERTY_WRITEONLY ??? // Neuer Eintrag in die Hashtable rPropNameMap[ aPropName ] = rPropCount; // Tabelle fuer XExactName pflegen rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; // set-Methode merken pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq2, pInterfaces2, rPropCount ); pInterfaces2[ rPropCount ] = rxMethod_i; // Art der Property merken pMapTypeArray[ rPropCount ] = MAP_SETONLY; pPropertyConceptArray[ rPropCount ] = METHODS; pAccess->mnMethodPropCount++; // Count pflegen rPropCount++; } } //******************************************************************** // 4. Methoden in die Gesamt-Sequence uebernehmen // Wieviele Methoden muessen in die Method-Sequence? sal_Int32 nExportedMethodCount = 0; sal_Int32 nSupportedListenerCount = 0; for( i = 0 ; i < nSourceMethodCount ; i++ ) { if( pMethodTypes[ i ] != INVALID_METHOD ) { nExportedMethodCount++; } if( pMethodTypes[ i ] == ADD_LISTENER_METHOD ) { nSupportedListenerCount++; } } // Sequences im Access-Objekt entsprechend aufbohren pAccess->maAllMethodSeq.realloc( nExportedMethodCount + iAllExportedMethod ); pAccess->maMethodConceptSeq.realloc( nExportedMethodCount + iAllExportedMethod ); pAccess->maSupportedListenerSeq.realloc( nSupportedListenerCount + iAllSupportedListener ); // Methoden reinschreiben Reference* pDestMethods = pAccess->maAllMethodSeq.getArray(); sal_Int32* pMethodConceptArray = pAccess->maMethodConceptSeq.getArray(); Type* pListenerClassRefs = pAccess->maSupportedListenerSeq.getArray(); for( i = 0 ; i < nSourceMethodCount ; i++ ) { if( pMethodTypes[ i ] != INVALID_METHOD ) { // Methode ansprechen const Reference& rxMethod = pSourceMethods[i]; // Namen in Hashtable eintragen, wenn nicht schon bekannt ::rtl::OUString aMethName2 = rxMethod->getName(); IntrospectionNameMap::iterator aIt = rMethodNameMap.find( aMethName2 ); if( aIt == rMethodNameMap.end() ) { // Eintragen rMethodNameMap[ aMethName2 ] = iAllExportedMethod; // Tabelle fuer XExactName pflegen rLowerToExactNameMap[ toLower( aMethName2 ) ] = aMethName2; } else { sal_Int32 iHashResult = (*aIt).second; Reference xExistingMethod = pDestMethods[ iHashResult ]; Reference< XIdlClass > xExistingMethClass = xExistingMethod->getDeclaringClass(); Reference< XIdlClass > xNewMethClass = rxMethod->getDeclaringClass(); if( xExistingMethClass->equals( xNewMethClass ) ) continue; } pDestMethods[ iAllExportedMethod ] = rxMethod; // Wenn kein Concept gesetzt wurde, ist die Methode "normal" sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ]; if( !rMethodConcept_i ) rMethodConcept_i = MethodConcept_NORMAL_IMPL; pMethodConceptArray[ iAllExportedMethod ] = rMethodConcept_i; iAllExportedMethod++; } if( pMethodTypes[ i ] == ADD_LISTENER_METHOD ) { // Klasse des Listeners ermitteln const Reference& rxMethod = pSourceMethods[i]; // void als Default-Klasse eintragen Reference xListenerClass = TypeToIdlClass( getCppuVoidType(), m_xSMgr ); // ALT: Reference xListenerClass = Void_getReflection()->getIdlClass(); // 1. Moeglichkeit: Parameter nach einer Listener-Klasse durchsuchen // Nachteil: Superklassen muessen rekursiv durchsucht werden Sequence< Reference > aParams = rxMethod->getParameterTypes(); const Reference* pParamArray2 = aParams.getConstArray(); Reference xEventListenerClass = TypeToIdlClass( getCppuType( (Reference*) NULL ), m_xSMgr ); // ALT: Reference xEventListenerClass = XEventListener_getReflection()->getIdlClass(); sal_Int32 nParamCount = aParams.getLength(); sal_Int32 k; for( k = 0 ; k < nParamCount ; k++ ) { const Reference& rxClass = pParamArray2[k]; // Sind wir von einem Listener abgeleitet? if( rxClass->equals( xEventListenerClass ) || isDerivedFrom( rxClass, xEventListenerClass ) ) { xListenerClass = rxClass; break; } } // 2. Moeglichkeit: Namen der Methode auswerden // Nachteil: geht nicht bei Test-Listenern, die es nicht gibt //aMethName = rxMethod->getName(); //aListenerName = aMethName.Copy( 3, aMethName.Len()-8-3 ); //Reference xListenerClass = reflection->forName( aListenerName ); Type aListenerType( TypeClass_INTERFACE, xListenerClass->getName() ); pListenerClassRefs[ iAllSupportedListener ] = aListenerType; iAllSupportedListener++; } } // Wenn in diesem Durchlauf XInterface-Methoden // dabei waren, diese zukuenftig ignorieren if( bFoundXInterface ) bXInterfaceIsInvalid = sal_True; delete[] pMethodTypes; delete[] pLocalMethodConcepts; } // Super-Klasse(n) vorhanden? Dann dort fortsetzen Sequence< Reference > aSuperClassSeq = xImplClass2->getSuperclasses(); // Zur Zeit wird nur von einer Superklasse ausgegangen if( aSuperClassSeq.getLength() >= 1 ) { xImplClass2 = aSuperClassSeq.getConstArray()[0]; OSL_ENSURE( xImplClass2.is(), "super class null" ); } else { xImplClass2 = NULL; } } } // Anzahl der exportierten Methoden uebernehmen und Sequences anpassen // (kann abweichen, weil doppelte Methoden erst nach der Ermittlung // von nExportedMethodCount herausgeworfen werden) sal_Int32& rMethCount = pAccess->mnMethCount; rMethCount = iAllExportedMethod; pAccess->maAllMethodSeq.realloc( rMethCount ); pAccess->maMethodConceptSeq.realloc( rMethCount ); // Groesse der Property-Sequences anpassen pAccess->maAllPropertySeq.realloc( rPropCount ); pAccess->maPropertyConceptSeq.realloc( rPropCount ); pAccess->maMapTypeSeq.realloc( rPropCount ); // Ende der Schleife ueber alle vom ClassProvider angegebenen Klassen } } // Bei structs Fields als Properties registrieren else //if( eType == TypeClass_STRUCT ) { // Ist es ein Interface oder eine struct? //Reference xClassRef = aToInspectObj.getReflection()->getIdlClass(); Reference xClassRef = TypeToIdlClass( aToInspectObj.getValueType(), m_xSMgr ); if( !xClassRef.is() ) { OSL_ENSURE( sal_False, "Can't get XIdlClass from Reflection" ); return pAccess; } // Felder holen Sequence< Reference > fields = xClassRef->getFields(); const Reference* pFields = fields.getConstArray(); sal_Int32 nLen = fields.getLength(); for( i = 0 ; i < nLen ; i++ ) { Reference xField = pFields[i]; Reference xPropType = xField->getType(); ::rtl::OUString aPropName = xField->getName(); // Ist die PropertySequence gross genug? pAccess->checkPropertyArraysSize ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); // In eigenes Property-Array eintragen Property& rProp = pAllPropArray[ rPropCount ]; rProp.Name = aPropName; rProp.Handle = rPropCount; rProp.Type = Type( xPropType->getTypeClass(), xPropType->getName() ); FieldAccessMode eAccessMode = xField->getAccessMode(); rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY || eAccessMode == FieldAccessMode_CONST) ? READONLY : 0; //FieldAccessMode eAccessMode = xField->getAccessMode(); //rProp.Attributes = (eAccessMode == FieldAccessMode::READONLY || eAccessMode == CONST) //? PropertyAttribute::READONLY : 0; // Namen in Hashtable eintragen rPropNameMap[ aPropName ] = rPropCount; // Tabelle fuer XExactName pflegen rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; // Field merken pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq1, pInterfaces1, rPropCount ); pInterfaces1[ rPropCount ] = xField; // Art der Property merken pMapTypeArray[ rPropCount ] = MAP_FIELD; pPropertyConceptArray[ rPropCount ] = ATTRIBUTES; pAccess->mnAttributePropCount++; // Count pflegen rPropCount++; } } // Property-Sequence auf die richtige Laenge bringen pAccess->maAllPropertySeq.realloc( pAccess->mnPropCount ); return pAccess; } //************************************************************************* Reference< XInterface > SAL_CALL ImplIntrospection_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw( RuntimeException ) { Reference< XInterface > xService = (OWeakObject*)(OComponentHelper*)new ImplIntrospection( rSMgr ); return xService; } } extern "C" { //================================================================================================== void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ) { *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; } //================================================================================================== void * SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * ) { void * pRet = 0; if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0) { Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory( reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), ::rtl::OUString::createFromAscii( pImplName ), stoc_inspect::ImplIntrospection_CreateInstance, stoc_inspect::ImplIntrospection::getSupportedServiceNames_Static() ) ); if (xFactory.is()) { xFactory->acquire(); pRet = xFactory.get(); } } return pRet; } }