| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_stoc.hxx" |
| |
| #include <string.h> |
| |
| // Schalter fuer Introspection-Caching |
| #ifndef OS2 |
| #define USE_INTROSPECTION_CACHE |
| #endif |
| |
| #ifdef USE_INTROSPECTION_CACHE |
| #define INTROSPECTION_CACHE_MAX_SIZE 100 |
| #endif |
| #include <osl/diagnose.h> |
| #include <osl/mutex.hxx> |
| #include <osl/thread.h> |
| #include <cppuhelper/queryinterface.hxx> |
| #include <cppuhelper/weak.hxx> |
| #include <cppuhelper/component.hxx> |
| #include <cppuhelper/factory.hxx> |
| #include <cppuhelper/implbase3.hxx> |
| #include <cppuhelper/typeprovider.hxx> |
| |
| #include <com/sun/star/uno/DeploymentException.hpp> |
| #include <com/sun/star/lang/XSingleServiceFactory.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/lang/XServiceInfo.hpp> |
| #include <com/sun/star/lang/XEventListener.hpp> |
| #include <com/sun/star/reflection/XIdlReflection.hpp> |
| #include <com/sun/star/reflection/XIdlClassProvider.hpp> |
| #include <com/sun/star/reflection/XIdlClass.hpp> |
| #include <com/sun/star/reflection/XIdlField2.hpp> |
| #include <com/sun/star/beans/UnknownPropertyException.hpp> |
| #include <com/sun/star/beans/Property.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/beans/XFastPropertySet.hpp> |
| #include <com/sun/star/beans/XIntrospection.hpp> |
| #include <com/sun/star/beans/XIntrospectionAccess.hpp> |
| #include <com/sun/star/beans/XMaterialHolder.hpp> |
| #include <com/sun/star/beans/XExactName.hpp> |
| #include <com/sun/star/beans/PropertyAttribute.hpp> |
| #include <com/sun/star/beans/PropertyConcept.hpp> |
| #include <com/sun/star/beans/MethodConcept.hpp> |
| #include <com/sun/star/container/XNameContainer.hpp> |
| #include <com/sun/star/container/XIndexContainer.hpp> |
| #include <com/sun/star/container/XEnumerationAccess.hpp> |
| |
| #include <rtl/ustrbuf.hxx> |
| #include <rtl/ref.hxx> |
| #include <rtl/strbuf.hxx> |
| #include <hash_map> |
| |
| 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<XIdlClass> xToTestClass, Reference<XIdlClass> xDerivedFromClass ) |
| { |
| Sequence< Reference<XIdlClass> > aClassesSeq = xToTestClass->getSuperclasses(); |
| const Reference<XIdlClass>* pClassesArray = aClassesSeq.getConstArray(); |
| sal_Int32 nSuperClassCount = aClassesSeq.getLength(); |
| sal_Int32 i; |
| for( i = 0 ; i < nSuperClassCount ; i++ ) |
| { |
| const Reference<XIdlClass>& 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<XInterface> > aInterfaceSeq1; |
| Sequence< Reference<XInterface> > aInterfaceSeq2; |
| |
| // Hashtables fuer die Namen |
| IntrospectionNameMap maPropertyNameMap; |
| IntrospectionNameMap maMethodNameMap; |
| LowerToExactNameMap maLowerToExactNameMap; |
| |
| // Sequence aller Properties, auch zum Liefern aus getProperties() |
| Sequence<Property> maAllPropertySeq; |
| |
| // Mapping der Properties auf Zugriffs-Arten |
| Sequence<sal_Int16> maMapTypeSeq; |
| |
| // Klassifizierung der gefundenen Methoden |
| Sequence<sal_Int32> 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<XIdlMethod> > maAllMethodSeq; |
| |
| // Klassifizierung der gefundenen Methoden |
| Sequence<sal_Int32> 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<XInterface> >& rSeq, Reference<XInterface>*& 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<Property> getProperties(void) const { return maAllPropertySeq; } |
| Sequence< Reference<XIdlMethod> > getMethods(void) const { return maAllMethodSeq; } |
| Sequence< Type > getSupportedListeners(void) const { return maSupportedListenerSeq; } |
| Sequence<sal_Int32> getPropertyConcepts(void) const { return maPropertyConceptSeq; } |
| Sequence<sal_Int32> 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<XIdlMethod>* pMethods = maAllMethodSeq.getConstArray(); |
| const Reference<XIdlMethod> 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<XIdlMethod> 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> xInterface; |
| if( eObjType == TypeClass_INTERFACE ) |
| { |
| xInterface = *( Reference<XInterface>*)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<XIdlClass> xPropClass = rProp.Type; |
| if( xPropClass.is() && xPropClass->getTypeClass() == TypeClass_INTERFACE ) |
| { |
| Reference<XInterface> valInterface = *(Reference<XInterface>*)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<XFastPropertySet> xFastPropSet = |
| Reference<XFastPropertySet>::query( xInterface ); |
| if( xFastPropSet.is() ) |
| { |
| xFastPropSet->setFastPropertyValue( nOrgHandle, bUseCopy ? aRealValue : aValue ); |
| } |
| else |
| { |
| // throw UnknownPropertyException |
| } |
| } |
| // sonst eben das normale nehmen |
| else |
| { |
| // PropertySet-Interface holen |
| Reference<XPropertySet> xPropSet = |
| Reference<XPropertySet>::query( xInterface ); |
| if( xPropSet.is() ) |
| { |
| xPropSet->setPropertyValue( rProp.Name, bUseCopy ? aRealValue : aValue ); |
| } |
| else |
| { |
| // throw UnknownPropertyException |
| } |
| } |
| } |
| break; |
| |
| case MAP_FIELD: |
| { |
| Reference<XIdlField> xField = (XIdlField*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get()); |
| Reference<XIdlField2> 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<XIdlMethod> xMethod = (XIdlMethod*)(aInterfaceSeq2.getConstArray()[ nSequenceIndex ].get()); |
| if( xMethod.is() ) |
| { |
| Sequence<Any> 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> xInterface; |
| if( eObjType == TypeClass_INTERFACE ) |
| { |
| xInterface = *(Reference<XInterface>*)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<XFastPropertySet> xFastPropSet = |
| Reference<XFastPropertySet>::query( xInterface ); |
| if( xFastPropSet.is() ) |
| { |
| aRet = xFastPropSet->getFastPropertyValue( nOrgHandle); |
| } |
| else |
| { |
| // throw UnknownPropertyException |
| return aRet; |
| } |
| } |
| // sonst eben das normale nehmen |
| else |
| { |
| // PropertySet-Interface holen |
| Reference<XPropertySet> xPropSet = |
| Reference<XPropertySet>::query( xInterface ); |
| if( xPropSet.is() ) |
| { |
| aRet = xPropSet->getPropertyValue( rProp.Name ); |
| } |
| else |
| { |
| // throw UnknownPropertyException |
| return aRet; |
| } |
| } |
| } |
| break; |
| |
| case MAP_FIELD: |
| { |
| Reference<XIdlField> 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<XIdlMethod> xMethod = (XIdlMethod*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get()); |
| if( xMethod.is() ) |
| { |
| Sequence<Any> 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<XInterface> >& rSeq, |
| Reference<XInterface>*& 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<XInterface> mxIface; |
| |
| // Statische Daten der Introspection |
| IntrospectionAccessStatic_Impl* mpStaticImpl; |
| |
| // Adapter-Implementation |
| WeakReference< XInterface > maAdapter; |
| |
| // Letzte Sequence, die bei getProperties geliefert wurde (Optimierung) |
| Sequence<Property> maLastPropertySeq; |
| sal_Int32 mnLastPropertyConcept; |
| |
| // Letzte Sequence, die bei getMethods geliefert wurde (Optimierung) |
| Sequence<Reference<XIdlMethod> > 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<XIdlMethod> 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<XIdlMethod> > SAL_CALL getMethods(sal_Int32 MethodConcepts) |
| throw( RuntimeException ); |
| virtual Sequence< Type > SAL_CALL getSupportedListeners(void) |
| throw( RuntimeException ); |
| using OWeakObject::queryAdapter; |
| virtual Reference<XInterface> 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<XInterface>*)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<XInterface> mxIface; |
| |
| // Original-Interfaces des Objekts |
| Reference<XElementAccess> mxObjElementAccess; |
| Reference<XNameContainer> mxObjNameContainer; |
| Reference<XNameAccess> mxObjNameAccess; |
| Reference<XIndexAccess> mxObjIndexAccess; |
| Reference<XIndexContainer> mxObjIndexContainer; |
| Reference<XEnumerationAccess> mxObjEnumerationAccess; |
| Reference<XIdlArray> 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<XPropertySetInfo> 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<XPropertyChangeListener>& aListener) |
| throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); |
| virtual void SAL_CALL removePropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) |
| throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); |
| virtual void SAL_CALL addVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) |
| throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); |
| virtual void SAL_CALL removeVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XVetoableChangeListener>& 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<XEnumeration> 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<XElementAccess>::query( mxIface ); |
| mxObjNameAccess = Reference<XNameAccess>::query( mxIface ); |
| mxObjNameContainer = Reference<XNameContainer>::query( mxIface ); |
| mxObjIndexAccess = Reference<XIndexAccess>::query( mxIface ); |
| mxObjIndexContainer = Reference<XIndexContainer>::query( mxIface ); |
| mxObjEnumerationAccess = Reference<XEnumerationAccess>::query( mxIface ); |
| mxObjIdlArray = Reference<XIdlArray>::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<XPropertySetInfo> 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<XPropertyChangeListener>& aListener) |
| throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) |
| { |
| if( mxIface.is() ) |
| { |
| Reference<XPropertySet> xPropSet = |
| Reference<XPropertySet>::query( mxIface ); |
| //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY ); |
| if( xPropSet.is() ) |
| xPropSet->addPropertyChangeListener(aPropertyName, aListener); |
| } |
| } |
| |
| void ImplIntrospectionAdapter::removePropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) |
| throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) |
| { |
| if( mxIface.is() ) |
| { |
| Reference<XPropertySet> xPropSet = |
| Reference<XPropertySet>::query( mxIface ); |
| //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY ); |
| if( xPropSet.is() ) |
| xPropSet->removePropertyChangeListener(aPropertyName, aListener); |
| } |
| } |
| |
| void ImplIntrospectionAdapter::addVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) |
| throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) |
| { |
| if( mxIface.is() ) |
| { |
| Reference<XPropertySet> xPropSet = |
| Reference<XPropertySet>::query( mxIface ); |
| //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY ); |
| if( xPropSet.is() ) |
| xPropSet->addVetoableChangeListener(aPropertyName, aListener); |
| } |
| } |
| |
| void ImplIntrospectionAdapter::removeVetoableChangeListener(const ::rtl::OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) |
| throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) |
| { |
| if( mxIface.is() ) |
| { |
| Reference<XPropertySet> xPropSet = |
| Reference<XPropertySet>::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<XIdlClass> 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<XIdlClass> getElementType(void) const; |
| Reference<XEnumeration> 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<Property> 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<XIdlMethod> ImplIntrospectionAccess::getMethod(const ::rtl::OUString& Name, sal_Int32 MethodConcepts) |
| throw( NoSuchMethodException, RuntimeException ) |
| { |
| Reference<XIdlMethod> xRet; |
| sal_Int32 i = mpStaticImpl->getMethodIndex( Name ); |
| if( i != -1 ) |
| { |
| |
| sal_Int32 nConcept = mpStaticImpl->getMethodConcepts().getConstArray()[ i ]; |
| if( (MethodConcepts & nConcept) != 0 ) |
| { |
| const Reference<XIdlMethod>* 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<XIdlMethod> > 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<XIdlMethod> > aMethodSeq = mpStaticImpl->getMethods(); |
| const Reference<XIdlMethod>* 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<XIdlMethod>* 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<XInterface> 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<XInterface> 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<XIdlClass> > aIdlClasses; |
| Reference<XPropertySetInfo> xPropInfo; |
| Reference<XIdlClass> xImplClass; |
| sal_Int32 nHitCount; |
| |
| void IncHitCount() const { ((hashIntrospectionKey_Impl*)this)->nHitCount++; } |
| hashIntrospectionKey_Impl() : nHitCount( 0 ) {} |
| hashIntrospectionKey_Impl( const Sequence< Reference<XIdlClass> > & rIdlClasses, |
| const Reference<XPropertySetInfo> & rxPropInfo, |
| const Reference<XIdlClass> & rxImplClass ); |
| }; |
| |
| hashIntrospectionKey_Impl::hashIntrospectionKey_Impl |
| ( |
| const Sequence< Reference<XIdlClass> > & rIdlClasses, |
| const Reference<XPropertySetInfo> & rxPropInfo, |
| const Reference<XIdlClass> & 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<XIdlClass>* pRefs1 = rObj1.aIdlClasses.getConstArray(); |
| const Reference<XIdlClass>* pRefs2 = rObj2.aIdlClasses.getConstArray(); |
| return memcmp( pRefs1, pRefs2, nCount1 * sizeof( Reference<XIdlClass> ) ) == 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<XPropertySetInfo> xPropInfo; |
| Sequence< sal_Int8 > maImpIdSeq; |
| sal_Int32 nHitCount; |
| |
| void IncHitCount() const { ((hashTypeProviderKey_Impl*)this)->nHitCount++; } |
| hashTypeProviderKey_Impl() : nHitCount( 0 ) {} |
| hashTypeProviderKey_Impl( const Reference<XPropertySetInfo> & rxPropInfo, const Sequence< sal_Int8 > & aImpIdSeq_ ); |
| }; |
| |
| hashTypeProviderKey_Impl::hashTypeProviderKey_Impl |
| ( |
| const Reference<XPropertySetInfo> & 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<XMultiServiceFactory> m_xSMgr; |
| |
| // CoreReflection halten |
| Reference< XIdlReflection > mxCoreReflection; |
| |
| // Klassen, deren Methoden eine spezielle Rolle spielen |
| Reference<XIdlClass> mxElementAccessClass; |
| Reference<XIdlClass> mxNameContainerClass; |
| Reference<XIdlClass> mxNameAccessClass; |
| Reference<XIdlClass> mxIndexContainerClass; |
| Reference<XIdlClass> mxIndexAccessClass; |
| Reference<XIdlClass> mxEnumerationAccessClass; |
| Reference<XIdlClass> mxInterfaceClass; |
| Reference<XIdlClass> mxAggregationClass; |
| sal_Bool mbDisposed; |
| |
| #ifdef USE_INTROSPECTION_CACHE |
| sal_uInt16 mnCacheEntryCount; |
| sal_uInt16 mnTPCacheEntryCount; |
| IntrospectionAccessCacheMap* mpCache; |
| TypeProviderAccessCacheMap* mpTypeProviderCache; |
| #endif |
| |
| public: |
| ImplIntrospection( const Reference<XMultiServiceFactory> & 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_Int8> 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<XIntrospectionAccess> 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<XMultiServiceFactory> & 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<XIntrospectionAccess> ImplIntrospection::inspect(const Any& aToInspectObj) |
| throw( RuntimeException ) |
| { |
| Reference<XIntrospectionAccess> 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<XIdlClass> TypeToIdlClass( const Type& rType, const Reference< XMultiServiceFactory > & xMgr ) |
| { |
| static Reference< XIdlReflection > xRefl; |
| |
| // void als Default-Klasse eintragen |
| Reference<XIdlClass> 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<XInterface> x; |
| if( eType == TypeClass_INTERFACE ) |
| { |
| // Interface aus dem Any besorgen |
| x = *(Reference<XInterface>*)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<XIdlClass> > SupportedClassSeq; |
| Sequence< Type > SupportedTypesSeq; |
| Reference<XIdlClassProvider> xClassProvider; |
| Reference<XTypeProvider> xTypeProvider; |
| Reference<XIdlClass> xImplClass; |
| Reference<XPropertySetInfo> xPropSetInfo; |
| Reference<XPropertySet> xPropSet; |
| |
| // Bei Interfaces XTypeProvider / XIdlClassProvider- und PropertySet-Interface anfordern |
| if( eType == TypeClass_INTERFACE ) |
| { |
| // XIdlClassProvider |
| xTypeProvider = Reference<XTypeProvider>::query( x ); |
| if( xTypeProvider.is() ) |
| { |
| SupportedTypesSeq = xTypeProvider->getTypes(); |
| sal_Int32 nTypeCount = SupportedTypesSeq.getLength(); |
| if( nTypeCount ) |
| { |
| SupportedClassSeq.realloc( nTypeCount ); |
| Reference<XIdlClass>* 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<XIdlClassProvider>::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<XPropertySet>::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<XInterface>* pInterfaces1; |
| Reference<XInterface>* 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<XFastPropertySet> xDummy = Reference<XFastPropertySet>::query( x ); |
| sal_Bool bFast = pAccess->mbFastPropSet = xDummy.is(); |
| |
| Sequence<Property> 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<XIdlClass> xImplClass2 = SupportedClassSeq.getConstArray()[nIdx]; |
| while( xImplClass2.is() ) |
| { |
| // Interfaces der Implementation holen |
| Sequence< Reference<XIdlClass> > aClassSeq = xImplClass2->getInterfaces(); |
| sal_Int32 nIfaceCount = aClassSeq.getLength(); |
| |
| aClassSeq.realloc( nIfaceCount + 1 ); |
| aClassSeq.getArray()[ nIfaceCount ] = xImplClass2; |
| nIfaceCount++; |
| |
| const Reference<XIdlClass>* pParamArray = aClassSeq.getConstArray(); |
| |
| for( sal_Int32 j = 0 ; j < nIfaceCount ; j++ ) |
| { |
| const Reference<XIdlClass>& 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<XIdlField> > fields = rxIfaceClass->getFields(); |
| const Reference<XIdlField>* pFields = fields.getConstArray(); |
| sal_Int32 nLen = fields.getLength(); |
| |
| for( i = 0 ; i < nLen ; i++ ) |
| { |
| Reference<XIdlField> xField = pFields[i]; |
| Reference<XIdlClass> 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<XIdlMethod> > methods = rxIfaceClass->getMethods(); |
| const Reference<XIdlMethod>* 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<XIdlMethod>& 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<XIdlClass> > 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<XIdlClass> 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<XIdlMethod>& 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<XIdlClass> xSetRetType = rxMethod_k->getReturnType(); |
| if( xSetRetType->getTypeClass() != TypeClass_VOID ) |
| { |
| continue; |
| } |
| |
| // set-Methode darf nur einen Parameter haben |
| Sequence< Reference<XIdlClass> > 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<XIdlClass>* pParamArray2 = setParams.getConstArray(); |
| Reference<XIdlClass> 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<XIdlMethod>& 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<XIdlMethod>& 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<XIdlClass> xSetRetType = rxMethod_i->getReturnType(); |
| if( xSetRetType->getTypeClass() != TypeClass_VOID ) |
| { |
| continue; |
| } |
| |
| // set-Methode darf nur einen Parameter haben |
| Sequence< Reference<XIdlClass> > 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<XIdlClass> 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<XIdlMethod>* 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<XIdlMethod>& 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<XIdlMethod> 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<XIdlMethod>& rxMethod = pSourceMethods[i]; |
| |
| // void als Default-Klasse eintragen |
| Reference<XIdlClass> xListenerClass = TypeToIdlClass( getCppuVoidType(), m_xSMgr ); |
| // ALT: Reference<XIdlClass> xListenerClass = Void_getReflection()->getIdlClass(); |
| |
| // 1. Moeglichkeit: Parameter nach einer Listener-Klasse durchsuchen |
| // Nachteil: Superklassen muessen rekursiv durchsucht werden |
| Sequence< Reference<XIdlClass> > aParams = rxMethod->getParameterTypes(); |
| const Reference<XIdlClass>* pParamArray2 = aParams.getConstArray(); |
| |
| Reference<XIdlClass> xEventListenerClass = TypeToIdlClass( getCppuType( (Reference<XEventListener>*) NULL ), m_xSMgr ); |
| // ALT: Reference<XIdlClass> xEventListenerClass = XEventListener_getReflection()->getIdlClass(); |
| sal_Int32 nParamCount = aParams.getLength(); |
| sal_Int32 k; |
| for( k = 0 ; k < nParamCount ; k++ ) |
| { |
| const Reference<XIdlClass>& 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<XIdlClass> 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<XIdlClass> > 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<XIdlClass> xClassRef = aToInspectObj.getReflection()->getIdlClass(); |
| Reference<XIdlClass> 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<XIdlField> > fields = xClassRef->getFields(); |
| const Reference<XIdlField>* pFields = fields.getConstArray(); |
| sal_Int32 nLen = fields.getLength(); |
| |
| for( i = 0 ; i < nLen ; i++ ) |
| { |
| Reference<XIdlField> xField = pFields[i]; |
| Reference<XIdlClass> 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; |
| } |
| } |
| |
| |