Files
libreoffice/stoc/source/inspect/introspection.cxx
Noel Grandin 71b809959b remove unnecessary use of void in function declarations
ie.
    void f(void);
becomes
    void f();

I used the following command to make the changes:

  git grep -lP '\(\s*void\s*\)' -- *.cxx \
    | xargs perl -pi -w -e 's/(\w+)\s*\(\s*void\s*\)/$1\(\)/g;'

and ran it for both .cxx and .hxx files.

Change-Id: I314a1b56e9c14d10726e32841736b0ad5eef8ddd
2015-04-15 11:47:12 +02:00

2499 lines
101 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
#include <sal/config.h>
#include <cassert>
#include <cstddef>
#include <limits>
#include <map>
#include <set>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>
#include <osl/thread.h>
#include <cppuhelper/basemutex.hxx>
#include <cppuhelper/compbase2.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <cppuhelper/weak.hxx>
#include <cppuhelper/component.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <salhelper/simplereferenceobject.hxx>
#include <com/sun/star/uno/DeploymentException.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.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/XIdlClass.hpp>
#include <com/sun/star/reflection/XIdlField2.hpp>
#include <com/sun/star/reflection/theCoreReflection.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/ref.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <unordered_map>
using namespace css::uno;
using namespace css::lang;
using namespace css::reflection;
using namespace css::container;
using namespace css::registry;
using namespace css::beans;
using namespace css::beans::PropertyAttribute;
using namespace css::beans::PropertyConcept;
using namespace css::beans::MethodConcept;
using namespace cppu;
using namespace osl;
namespace
{
typedef WeakImplHelper3< XIntrospectionAccess, XMaterialHolder, XExactName > IntrospectionAccessHelper;
// Special value for Method-Concept, to be able to mark "normal" functions
#define MethodConcept_NORMAL_IMPL 0x80000000
// Method to assert, if a class is derived from another class
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();
for ( sal_Int32 i = 0; i < nSuperClassCount; ++i )
{
const Reference<XIdlClass>& rxClass = pClassesArray[i];
if ( xDerivedFromClass->equals( rxClass ) ||
isDerivedFrom( rxClass, xDerivedFromClass )
)
return true;
}
return false;
}
// *** Classification of Properties (no enum, to be able to use Sequence) ***
// Properties from a PropertySet-Interface
#define MAP_PROPERTY_SET 0
// Properties from Fields
#define MAP_FIELD 1
// Properties, that get described with get/set-Methods
#define MAP_GETSET 2
// Properties, with only a set-Method
#define MAP_SETONLY 3
// Increments, in which the size of Sequences get adjusted
#define ARRAY_SIZE_STEP 20
//*** IntrospectionAccessStatic_Impl ***
// Equals to the old IntrospectionAccessImpl, forms now a static
// part of the new Instance-related ImplIntrospectionAccess
// Hashtable for the search of names
typedef std::unordered_map
<
OUString,
sal_Int32,
OUStringHash
>
IntrospectionNameMap;
// Hashtable to assign exact names to the Lower-Case
// converted names, for the support of XExactName
typedef std::unordered_map
<
OUString,
OUString,
OUStringHash
>
LowerToExactNameMap;
class ImplIntrospectionAccess;
class IntrospectionAccessStatic_Impl: public salhelper::SimpleReferenceObject
{
friend class Implementation;
friend class ImplIntrospectionAccess;
// Holding CoreReflection
Reference< XIdlReflection > mxCoreReflection;
// InterfaceSequences, to save additional information in a property
// for example the Field at MAP_FIELD, the get/set-Methods at MAP_GETSET, et cetera
Sequence< Reference<XInterface> > aInterfaceSeq1;
Sequence< Reference<XInterface> > aInterfaceSeq2;
// Hashtables for names
IntrospectionNameMap maPropertyNameMap;
IntrospectionNameMap maMethodNameMap;
LowerToExactNameMap maLowerToExactNameMap;
// Sequence of all Properties, also for delivering from getProperties()
Sequence<Property> maAllPropertySeq;
// Mapping of properties to Access-Types
Sequence<sal_Int16> maMapTypeSeq;
// Classification of found methods
Sequence<sal_Int32> maPropertyConceptSeq;
// Number of Properties
sal_Int32 mnPropCount;
// Number of Properties, which are assigned to particular concepts
//sal_Int32 mnDangerousPropCount;
sal_Int32 mnPropertySetPropCount;
sal_Int32 mnAttributePropCount;
sal_Int32 mnMethodPropCount;
// Flag, if a FastPropertySet is supported
bool mbFastPropSet;
// Original-Handles of FastPropertySets
sal_Int32* mpOrgPropertyHandleArray;
// MethodSequence, that accepts all methods
Sequence< Reference<XIdlMethod> > maAllMethodSeq;
// Classification of found methods
Sequence<sal_Int32> maMethodConceptSeq;
// Number of methods
sal_Int32 mnMethCount;
// Sequence of Listener, that can be registered
Sequence< Type > maSupportedListenerSeq;
// Helper-methods for adjusting sizes of Sequences
void checkPropertyArraysSize
(
Property*& rpAllPropArray,
sal_Int16*& rpMapTypeArray,
sal_Int32*& rpPropertyConceptArray,
sal_Int32 iNextIndex
);
static void checkInterfaceArraySize( Sequence< Reference<XInterface> >& rSeq, Reference<XInterface>*& rpInterfaceArray,
sal_Int32 iNextIndex );
public:
IntrospectionAccessStatic_Impl( Reference< XIdlReflection > xCoreReflection_ );
virtual ~IntrospectionAccessStatic_Impl()
{
delete[] mpOrgPropertyHandleArray;
}
sal_Int32 getPropertyIndex( const OUString& aPropertyName ) const;
sal_Int32 getMethodIndex( const OUString& aMethodName ) const;
// Methods of XIntrospectionAccess (OLD, now only Impl)
void setPropertyValue(const Any& obj, const OUString& aPropertyName, const Any& aValue) const;
// void setPropertyValue(Any& obj, const OUString& aPropertyName, const Any& aValue) const;
Any getPropertyValue(const Any& obj, const 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() const { return maAllPropertySeq; }
Sequence< Reference<XIdlMethod> > getMethods() const { return maAllMethodSeq; }
Sequence< Type > getSupportedListeners() const { return maSupportedListenerSeq; }
Sequence<sal_Int32> getPropertyConcepts() const { return maPropertyConceptSeq; }
Sequence<sal_Int32> getMethodConcepts() const { return maMethodConceptSeq; }
};
// Ctor
IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlReflection > xCoreReflection_ )
: mxCoreReflection( xCoreReflection_ )
{
aInterfaceSeq1.realloc( ARRAY_SIZE_STEP );
aInterfaceSeq2.realloc( ARRAY_SIZE_STEP );
// Property-Data
maAllPropertySeq.realloc( ARRAY_SIZE_STEP );
maMapTypeSeq.realloc( ARRAY_SIZE_STEP );
maPropertyConceptSeq.realloc( ARRAY_SIZE_STEP );
mbFastPropSet = false;
mpOrgPropertyHandleArray = NULL;
mnPropCount = 0;
//mnDangerousPropCount = 0;
mnPropertySetPropCount = 0;
mnAttributePropCount = 0;
mnMethodPropCount = 0;
// Method-Data
mnMethCount = 0;
}
sal_Int32 IntrospectionAccessStatic_Impl::getPropertyIndex( const OUString& aPropertyName ) const
{
sal_Int32 iHashResult = -1;
IntrospectionAccessStatic_Impl* pThis = const_cast<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 OUString& aMethodName ) const
{
sal_Int32 iHashResult = -1;
IntrospectionAccessStatic_Impl* pThis = const_cast<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();
while( true )
{
// Strategy: Search back until the first '_' is found
sal_Int32 nFound = aMethodName.lastIndexOf( '_', nSearchFrom );
if( nFound == -1 )
break;
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 _ ?!
OUString aStr = aMethodName.copy( 0, nFound );
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 ];
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 OUString& aPropertyName, const Any& aValue ) const
//void IntrospectionAccessStatic_Impl::setPropertyValue( Any& obj, const 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
{
// Is the passed object something that fits?
TypeClass eObjType = obj.getValueType().getTypeClass();
Reference<XInterface> xInterface;
if( eObjType == TypeClass_INTERFACE )
{
xInterface = *static_cast<Reference<XInterface> const *>(obj.getValue());
}
else if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) )
{
throw IllegalArgumentException();
}
// Test flags
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:
{
// Get Property
const Property& rProp = maAllPropertySeq.getConstArray()[ nSequenceIndex ];
// Convert Interface-Parameter to the correct type
bool bUseCopy = false;
Any aRealValue;
TypeClass eValType = aValue.getValueType().getTypeClass();
if( eValType == TypeClass_INTERFACE )
{
Type aPropType = rProp.Type;
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 = *static_cast<Reference<XInterface> const *>(aValue.getValue());
if( valInterface.is() )
{
//Any queryInterface( const Type& rType );
aRealValue = valInterface->queryInterface( aPropType );
if( aRealValue.hasValue() )
bUseCopy = true;
}
}
}
// Do we have a FastPropertySet and a valid Handle?
// CAUTION: At this point we exploit, that the PropertySet
// gets queried at the beginning of the Introspection-Process.
sal_Int32 nOrgHandle;
if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 )
{
// Retrieve PropertySet-Interface
Reference<XFastPropertySet> xFastPropSet =
Reference<XFastPropertySet>::query( xInterface );
if( xFastPropSet.is() )
{
xFastPropSet->setFastPropertyValue( nOrgHandle, bUseCopy ? aRealValue : aValue );
}
else
{
// throw UnknownPropertyException
}
}
// else take the normal one
else
{
// Retrieve PropertySet-Interface
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 = static_cast<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:
{
// Retrieve set-Methods
Reference<XIdlMethod> xMethod = static_cast<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 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 = *static_cast<Reference<XInterface> const *>(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 = static_cast<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 = static_cast<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 Implementation;
// Untersuchtes Objekt
Any maInspectedObject;
// Als Interface
Reference<XInterface> mxIface;
// Statische Daten der Introspection
rtl::Reference< 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, rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ );
virtual ~ImplIntrospectionAccess();
// Methoden von XIntrospectionAccess
virtual sal_Int32 SAL_CALL getSuppliedMethodConcepts()
throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual sal_Int32 SAL_CALL getSuppliedPropertyConcepts()
throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Property SAL_CALL getProperty(const OUString& Name, sal_Int32 PropertyConcepts)
throw( NoSuchElementException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual sal_Bool SAL_CALL hasProperty(const OUString& Name, sal_Int32 PropertyConcepts)
throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Sequence< Property > SAL_CALL getProperties(sal_Int32 PropertyConcepts)
throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Reference<XIdlMethod> SAL_CALL getMethod(const OUString& Name, sal_Int32 MethodConcepts)
throw( NoSuchMethodException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual sal_Bool SAL_CALL hasMethod(const OUString& Name, sal_Int32 MethodConcepts)
throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Sequence< Reference<XIdlMethod> > SAL_CALL getMethods(sal_Int32 MethodConcepts)
throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Sequence< Type > SAL_CALL getSupportedListeners()
throw( RuntimeException, std::exception ) SAL_OVERRIDE;
using OWeakObject::queryAdapter;
virtual Reference<XInterface> SAL_CALL queryAdapter( const Type& rType )
throw( IllegalTypeException, RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XMaterialHolder
virtual Any SAL_CALL getMaterial() throw(RuntimeException, std::exception) SAL_OVERRIDE;
// Methoden von XExactName
virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
};
ImplIntrospectionAccess::ImplIntrospectionAccess
( const Any& obj, rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ )
: maInspectedObject( obj ), mpStaticImpl( pStaticImpl_ ), maAdapter()
{
// Objekt als Interface merken, wenn moeglich
TypeClass eType = maInspectedObject.getValueType().getTypeClass();
if( eType == TypeClass_INTERFACE )
mxIface = *static_cast<Reference<XInterface> const *>(maInspectedObject.getValue());
mnLastPropertyConcept = -1;
mnLastMethodConcept = -1;
}
ImplIntrospectionAccess::~ImplIntrospectionAccess()
{
}
//*** 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
rtl::Reference< 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,
rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ );
// Methoden von XInterface
virtual Any SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL acquire() throw() SAL_OVERRIDE { OWeakObject::acquire(); }
virtual void SAL_CALL release() throw() SAL_OVERRIDE { OWeakObject::release(); }
// Methoden von XPropertySet
virtual Reference<XPropertySetInfo> SAL_CALL getPropertySetInfo() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, const Any& aValue)
throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Any SAL_CALL getPropertyValue(const OUString& aPropertyName)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XFastPropertySet
virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const Any& aValue)
throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XPropertySetInfo
virtual Sequence< Property > SAL_CALL getProperties() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Property SAL_CALL getPropertyByName(const OUString& Name) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& Name) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XElementAccess
virtual Type SAL_CALL getElementType() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual sal_Bool SAL_CALL hasElements() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XNameAccess
virtual Any SAL_CALL getByName(const OUString& Name)
throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Sequence< OUString > SAL_CALL getElementNames() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual sal_Bool SAL_CALL hasByName(const OUString& Name) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XNameContainer
virtual void SAL_CALL insertByName(const OUString& Name, const Any& Element)
throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL replaceByName(const OUString& Name, const Any& Element)
throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL removeByName(const OUString& Name)
throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XIndexAccess
virtual sal_Int32 SAL_CALL getCount() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Any SAL_CALL getByIndex(sal_Int32 Index)
throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XIndexContainer
virtual void SAL_CALL insertByIndex(sal_Int32 Index, const Any& Element)
throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element)
throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL removeByIndex(sal_Int32 Index)
throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XEnumerationAccess
virtual Reference<XEnumeration> SAL_CALL createEnumeration() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
// Methoden von XIdlArray
virtual void SAL_CALL realloc(Any& array, sal_Int32 length)
throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual sal_Int32 SAL_CALL getLen(const Any& array) throw( IllegalArgumentException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual Any SAL_CALL get(const Any& array, sal_Int32 index)
throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException, std::exception ) SAL_OVERRIDE;
virtual void SAL_CALL set(Any& array, sal_Int32 index, const Any& value)
throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException, std::exception ) SAL_OVERRIDE;
};
ImplIntrospectionAdapter::ImplIntrospectionAdapter( ImplIntrospectionAccess* pAccess_,
const Any& obj,
rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ )
: mpAccess( pAccess_), mrInspectedObject( obj ), mpStaticImpl( pStaticImpl_ )
{
// Objekt als Interfaceholen
TypeClass eType = mrInspectedObject.getValueType().getTypeClass();
if( eType == TypeClass_INTERFACE )
{
mxIface = *static_cast<Reference< XInterface > const *>(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 );
}
}
// Methoden von XInterface
Any SAL_CALL ImplIntrospectionAdapter::queryInterface( const Type& rType )
throw( RuntimeException, std::exception )
{
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()
throw( RuntimeException, std::exception )
{
return (XPropertySetInfo *)this;
}
void ImplIntrospectionAdapter::setPropertyValue(const OUString& aPropertyName, const Any& aValue)
throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception )
{
mpStaticImpl->setPropertyValue( mrInspectedObject, aPropertyName, aValue );
}
Any ImplIntrospectionAdapter::getPropertyValue(const OUString& aPropertyName)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception )
{
return mpStaticImpl->getPropertyValue( mrInspectedObject, aPropertyName );
}
void ImplIntrospectionAdapter::addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception )
{
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 OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception )
{
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 OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception )
{
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 OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception )
{
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, std::exception )
{
}
Any ImplIntrospectionAdapter::getFastPropertyValue(sal_Int32)
throw( UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception )
{
return Any();
}
// Methoden von XPropertySetInfo
Sequence< Property > ImplIntrospectionAdapter::getProperties() throw( RuntimeException, std::exception )
{
return mpStaticImpl->getProperties();
}
Property ImplIntrospectionAdapter::getPropertyByName(const OUString& Name)
throw( RuntimeException, std::exception )
{
return mpAccess->getProperty( Name, PropertyConcept::ALL );
}
sal_Bool ImplIntrospectionAdapter::hasPropertyByName(const OUString& Name)
throw( RuntimeException, std::exception )
{
return mpAccess->hasProperty( Name, PropertyConcept::ALL );
}
// Methoden von XElementAccess
Type ImplIntrospectionAdapter::getElementType() throw( RuntimeException, std::exception )
{
return mxObjElementAccess->getElementType();
}
sal_Bool ImplIntrospectionAdapter::hasElements() throw( RuntimeException, std::exception )
{
return mxObjElementAccess->hasElements();
}
// Methoden von XNameAccess
Any ImplIntrospectionAdapter::getByName(const OUString& Name)
throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
{
return mxObjNameAccess->getByName( Name );
}
Sequence< OUString > ImplIntrospectionAdapter::getElementNames()
throw( RuntimeException, std::exception )
{
return mxObjNameAccess->getElementNames();
}
sal_Bool ImplIntrospectionAdapter::hasByName(const OUString& Name)
throw( RuntimeException, std::exception )
{
return mxObjNameAccess->hasByName( Name );
}
// Methoden von XNameContainer
void ImplIntrospectionAdapter::insertByName(const OUString& Name, const Any& Element)
throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException, std::exception )
{
mxObjNameContainer->insertByName( Name, Element );
}
void ImplIntrospectionAdapter::replaceByName(const OUString& Name, const Any& Element)
throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
{
mxObjNameContainer->replaceByName( Name, Element );
}
void ImplIntrospectionAdapter::removeByName(const OUString& Name)
throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
{
mxObjNameContainer->removeByName( Name );
}
// Methoden von XIndexAccess
// Schon in XNameAccess: virtual Reference<XIdlClass> getElementType() const
sal_Int32 ImplIntrospectionAdapter::getCount() throw( RuntimeException, std::exception )
{
return mxObjIndexAccess->getCount();
}
Any ImplIntrospectionAdapter::getByIndex(sal_Int32 Index)
throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
{
return mxObjIndexAccess->getByIndex( Index );
}
// Methoden von XIndexContainer
void ImplIntrospectionAdapter::insertByIndex(sal_Int32 Index, const Any& Element)
throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
{
mxObjIndexContainer->insertByIndex( Index, Element );
}
void ImplIntrospectionAdapter::replaceByIndex(sal_Int32 Index, const Any& Element)
throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
{
mxObjIndexContainer->replaceByIndex( Index, Element );
}
void ImplIntrospectionAdapter::removeByIndex(sal_Int32 Index)
throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
{
mxObjIndexContainer->removeByIndex( Index );
}
// Methoden von XEnumerationAccess
// Schon in XNameAccess: virtual Reference<XIdlClass> getElementType() const;
Reference<XEnumeration> ImplIntrospectionAdapter::createEnumeration() throw( RuntimeException, std::exception )
{
return mxObjEnumerationAccess->createEnumeration();
}
// Methoden von XIdlArray
void ImplIntrospectionAdapter::realloc(Any& array, sal_Int32 length)
throw( IllegalArgumentException, RuntimeException, std::exception )
{
mxObjIdlArray->realloc( array, length );
}
sal_Int32 ImplIntrospectionAdapter::getLen(const Any& array)
throw( IllegalArgumentException, RuntimeException, std::exception )
{
return mxObjIdlArray->getLen( array );
}
Any ImplIntrospectionAdapter::get(const Any& array, sal_Int32 index)
throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException, std::exception )
{
return mxObjIdlArray->get( array, index );
}
void ImplIntrospectionAdapter::set(Any& array, sal_Int32 index, const Any& value)
throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException, std::exception )
{
mxObjIdlArray->set( array, index, value );
}
//*** Implementation von ImplIntrospectionAccess ***
// Methoden von XIntrospectionAccess
sal_Int32 ImplIntrospectionAccess::getSuppliedMethodConcepts()
throw( RuntimeException, std::exception )
{
return MethodConcept::DANGEROUS |
PROPERTY |
LISTENER |
ENUMERATION |
NAMECONTAINER |
INDEXCONTAINER;
}
sal_Int32 ImplIntrospectionAccess::getSuppliedPropertyConcepts()
throw( RuntimeException, std::exception )
{
return PropertyConcept::DANGEROUS |
PROPERTYSET |
ATTRIBUTES |
METHODS;
}
Property ImplIntrospectionAccess::getProperty(const OUString& Name, sal_Int32 PropertyConcepts)
throw( NoSuchElementException, RuntimeException, std::exception )
{
Property aRet;
sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
bool bFound = 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 = true;
}
}
if( !bFound )
throw NoSuchElementException() ;
return aRet;
}
sal_Bool ImplIntrospectionAccess::hasProperty(const OUString& Name, sal_Int32 PropertyConcepts)
throw( RuntimeException, std::exception )
{
sal_Int32 i = mpStaticImpl->getPropertyIndex( Name );
bool bRet = false;
if( i != -1 )
{
sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts().getConstArray()[ i ];
if( (PropertyConcepts & nConcept) != 0 )
bRet = true;
}
return bRet;
}
Sequence< Property > ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts)
throw( RuntimeException, std::exception )
{
// 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 ];
}
// PropertyConcept merken, dies entspricht maLastPropertySeq
pThis->mnLastPropertyConcept = PropertyConcepts;
// Zusammengebastelte Sequence liefern
return maLastPropertySeq;
}
Reference<XIdlMethod> ImplIntrospectionAccess::getMethod(const OUString& Name, sal_Int32 MethodConcepts)
throw( NoSuchMethodException, RuntimeException, std::exception )
{
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 OUString& Name, sal_Int32 MethodConcepts)
throw( RuntimeException, std::exception )
{
sal_Int32 i = mpStaticImpl->getMethodIndex( Name );
bool bRet = false;
if( i != -1 )
{
sal_Int32 nConcept = mpStaticImpl->getMethodConcepts().getConstArray()[ i ];
if( (MethodConcepts & nConcept) != 0 )
bRet = true;
}
return bRet;
}
Sequence< Reference<XIdlMethod> > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts)
throw( RuntimeException, std::exception )
{
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 ];
}
// 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()
throw( RuntimeException, std::exception )
{
return mpStaticImpl->getSupportedListeners();
}
Reference<XInterface> SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type& rType )
throw( IllegalTypeException, RuntimeException, std::exception )
{
// 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() throw(RuntimeException, std::exception)
{
return maInspectedObject;
}
// Hilfs-Funktion zur LowerCase-Wandlung eines OUString
OUString toLower( const OUString& aUStr )
{
// Tabelle fuer XExactName pflegen
OUString aOWStr( aUStr.getStr() );
OUString aOWLowerStr = aOWStr.toAsciiLowerCase();
OUString aLowerUStr( aOWLowerStr.getStr() );
return aLowerUStr;
}
// Methoden von XExactName
OUString ImplIntrospectionAccess::getExactName( const OUString& rApproximateName ) throw( RuntimeException, std::exception )
{
OUString aRetStr;
LowerToExactNameMap::iterator aIt =
mpStaticImpl->maLowerToExactNameMap.find( toLower( rApproximateName ) );
if( !( aIt == mpStaticImpl->maLowerToExactNameMap.end() ) )
aRetStr = (*aIt).second;
return aRetStr;
}
struct ClassKey {
ClassKey(
css::uno::Reference<css::beans::XPropertySetInfo> const & theProperties,
css::uno::Reference<css::reflection::XIdlClass> const &
theImplementation,
css::uno::Sequence< css::uno::Reference<css::reflection::XIdlClass> >
const & theClasses):
properties(theProperties), implementation(theImplementation),
classes(theClasses)
{}
css::uno::Reference<css::beans::XPropertySetInfo> properties;
css::uno::Reference<css::reflection::XIdlClass> implementation;
css::uno::Sequence< css::uno::Reference<css::reflection::XIdlClass> >
classes;
};
struct ClassKeyLess {
bool operator ()(ClassKey const & key1, ClassKey const & key2) const {
if (key1.properties.get() < key2.properties.get()) {
return true;
}
if (key1.properties.get() > key2.properties.get()) {
return false;
}
if (key1.implementation.get() < key2.implementation.get()) {
return true;
}
if (key1.implementation.get() > key2.implementation.get()) {
return false;
}
if (key1.classes.getLength() < key2.classes.getLength()) {
return true;
}
if (key1.classes.getLength() > key2.classes.getLength()) {
return false;
}
for (sal_Int32 i = 0; i != key1.classes.getLength(); ++i) {
if (key1.classes[i].get() < key2.classes[i].get()) {
return true;
}
if (key1.classes[i].get() > key2.classes[i].get()) {
return false;
}
}
return false;
}
};
struct TypeKey {
TypeKey(
css::uno::Reference<css::beans::XPropertySetInfo> const & theProperties,
css::uno::Sequence<css::uno::Type> const & theTypes):
properties(theProperties)
{
//TODO: Could even sort the types lexicographically first, to increase
// the chance of matches between different implementations' getTypes(),
// but the old scheme of using getImplementationId() would have missed
// those matches, too:
OUStringBuffer b;
for (sal_Int32 i = 0; i != theTypes.getLength(); ++i) {
b.append(theTypes[i].getTypeName());
b.append('*'); // arbitrary delimiter not used by type grammar
}
types = b.makeStringAndClear();
}
css::uno::Reference<css::beans::XPropertySetInfo> properties;
OUString types;
};
struct TypeKeyLess {
bool operator ()(TypeKey const & key1, TypeKey const & key2) const {
if (key1.properties.get() < key2.properties.get()) {
return true;
}
if (key1.properties.get() > key2.properties.get()) {
return false;
}
return key1.types < key2.types;
}
};
template<typename Key, typename Less> class Cache {
public:
rtl::Reference<IntrospectionAccessStatic_Impl> find(Key const & key) const {
typename Map::const_iterator i(map_.find(key));
if (i == map_.end()) {
return rtl::Reference<IntrospectionAccessStatic_Impl>();
} else {
if (i->second.hits < std::numeric_limits<unsigned>::max()) {
++i->second.hits;
}
assert(i->second.access.is());
return i->second.access;
}
}
void insert(
Key const & key,
rtl::Reference<IntrospectionAccessStatic_Impl> const & access)
{
assert(access.is());
typename Map::size_type const MAX = 100;
assert(map_.size() <= MAX);
if (map_.size() == MAX) {
typename Map::iterator del(map_.begin());
for (typename Map::iterator i(map_.begin()); i != map_.end(); ++i) {
if (i->second.hits < del->second.hits) {
del = i;
}
}
map_.erase(del);
}
bool ins = map_.insert(typename Map::value_type(key, Data(access)))
.second;
assert(ins); (void)ins;
}
void clear() { map_.clear(); }
private:
struct Data {
explicit Data(
rtl::Reference<IntrospectionAccessStatic_Impl> const & theAccess):
access(theAccess), hits(1)
{}
rtl::Reference<IntrospectionAccessStatic_Impl> access;
mutable unsigned hits;
};
typedef std::map<Key, Data, Less> Map;
Map map_;
};
typedef
cppu::WeakComponentImplHelper2<
css::lang::XServiceInfo, css::beans::XIntrospection>
Implementation_Base;
class Implementation: private cppu::BaseMutex, public Implementation_Base {
public:
explicit Implementation(
css::uno::Reference<css::uno::XComponentContext> const & context):
Implementation_Base(m_aMutex),
reflection_(css::reflection::theCoreReflection::get(context))
{}
private:
virtual void SAL_CALL disposing() SAL_OVERRIDE {
reflection_.clear();
classCache_.clear();
typeCache_.clear();
}
virtual OUString SAL_CALL getImplementationName()
throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
{ return OUString("com.sun.star.comp.stoc.Introspection"); }
virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
{ return cppu::supportsService(this, ServiceName); }
virtual css::uno::Sequence<OUString> SAL_CALL
getSupportedServiceNames()
throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
{
Sequence<OUString> s(1);
s[0] = "com.sun.star.beans.Introspection";
return s;
}
virtual css::uno::Reference<css::beans::XIntrospectionAccess> SAL_CALL
inspect(css::uno::Any const & aObject)
throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
css::uno::Reference<css::reflection::XIdlReflection> reflection_;
Cache<ClassKey, ClassKeyLess> classCache_;
Cache<TypeKey, TypeKeyLess> typeCache_;
};
css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
css::uno::Any const & aObject)
throw (css::uno::RuntimeException, std::exception)
{
osl::MutexGuard g(m_aMutex);
if (rBHelper.bDisposed || rBHelper.bInDispose) {
throw css::lang::DisposedException(
getImplementationName(), static_cast<OWeakObject *>(this));
}
css::uno::Any aToInspectObj;
css::uno::Type t;
if (aObject >>= t) {
css::uno::Reference<css::reflection::XIdlClass> c(
reflection_->forName(t.getTypeName()));
if (!c.is()) {
SAL_WARN("stoc", "cannot reflect type " << t.getTypeName());
return css::uno::Reference<css::beans::XIntrospectionAccess>();
}
aToInspectObj <<= c;
} else {
aToInspectObj = aObject;
}
// Objekt untersuchen
TypeClass eType = aToInspectObj.getValueType().getTypeClass();
if( eType != TypeClass_INTERFACE && eType != TypeClass_STRUCT && eType != TypeClass_EXCEPTION )
return css::uno::Reference<css::beans::XIntrospectionAccess>();
Reference<XInterface> x;
if( eType == TypeClass_INTERFACE )
{
// Interface aus dem Any besorgen
x = *static_cast<Reference<XInterface> const *>(aToInspectObj.getValue());
if( !x.is() )
return css::uno::Reference<css::beans::XIntrospectionAccess>();
}
// Pointer auf ggf. noetige neue IntrospectionAccess-Instanz
rtl::Reference< IntrospectionAccessStatic_Impl > pAccess;
// Pruefen: Ist schon ein passendes Access-Objekt gecached?
Sequence< Reference<XIdlClass> > SupportedClassSeq;
Sequence< Type > SupportedTypesSeq;
Reference<XTypeProvider> xTypeProvider;
Reference<XIdlClass> xImplClass;
Reference<XPropertySetInfo> xPropSetInfo;
Reference<XPropertySet> xPropSet;
// Look for interfaces XTypeProvider and PropertySet
if( eType == TypeClass_INTERFACE )
{
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] = reflection_->forName(pTypes[i].getTypeName());
}
// TODO: Caching!
}
} else {
SAL_WARN(
"stoc",
"object of type \"" << aToInspectObj.getValueTypeName()
<< "\" lacks XTypeProvider");
xImplClass = reflection_->forName(aToInspectObj.getValueTypeName());
SupportedClassSeq.realloc(1);
SupportedClassSeq[0] = xImplClass;
}
xPropSet = Reference<XPropertySet>::query( x );
// Jetzt versuchen, das PropertySetInfo zu bekommen
if( xPropSet.is() )
xPropSetInfo = xPropSet->getPropertySetInfo();
} else {
xImplClass = reflection_->forName(aToInspectObj.getValueTypeName());
}
if (xTypeProvider.is()) {
TypeKey key(xPropSetInfo, xTypeProvider->getTypes());
pAccess = typeCache_.find(key);
if (pAccess.is()) {
return new ImplIntrospectionAccess(aToInspectObj, pAccess);
}
pAccess = new IntrospectionAccessStatic_Impl(reflection_);
typeCache_.insert(key, pAccess);
} else if (xImplClass.is()) {
ClassKey key(xPropSetInfo, xImplClass, SupportedClassSeq);
pAccess = classCache_.find(key);
if (pAccess.is()) {
return new ImplIntrospectionAccess(aToInspectObj, pAccess);
}
pAccess = new IntrospectionAccessStatic_Impl(reflection_);
classCache_.insert(key, pAccess);
}
// Kein Access gecached -> neu anlegen
Property* pAllPropArray;
Reference<XInterface>* pInterfaces1;
Reference<XInterface>* pInterfaces2;
sal_Int16* pMapTypeArray;
sal_Int32* pPropertyConceptArray;
sal_Int32 i;
if( !pAccess.is() )
pAccess = new IntrospectionAccessStatic_Impl( reflection_ );
// 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 );
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
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
{
SAL_WARN( "stoc", "Introspection: Property \"" <<
aPropName << "\" found more than once in PropertySet" );
}
// Count pflegen
rPropCount++;
}
}
// Indizes in die Export-Tabellen
sal_Int32 iAllExportedMethod = 0;
sal_Int32 iAllSupportedListener = 0;
std::set<OUString> seen;
// Flag, ob XInterface-Methoden erfasst werden sollen
// (das darf nur einmal erfolgen, initial zulassen)
bool bXInterfaceIsInvalid = 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.
bool bFoundXInterface = false;
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];
if (!seen.insert(rxIfaceClass->getName()).second) {
continue;
}
// 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 ];
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
OUString aPropName = rProp.Name;
// Haben wir den Namen schon?
IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName );
if( !( aIt == rPropNameMap.end() ) )
continue;
// Neuer Eintrag in die Hashtable
rPropNameMap[ aPropName ] = rPropCount;
// Tabelle fuer XExactName pflegen
rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName;
// Field merken
IntrospectionAccessStatic_Impl::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
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
};
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;
}
OUString aMethName;
OUString aPropName;
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 acquire oder release gerufen werden kann
rtl::OUString className(
rxMethod_i->getDeclaringClass()->getName());
if (className == "com.sun.star.uno.XInterface") {
bFoundXInterface = true;
if( bXInterfaceIsInvalid )
{
pMethodTypes[ i ] = INVALID_METHOD;
continue;
}
else
{
if( aMethName != "queryInterface" )
{
rMethodConcept_i |= MethodConcept::DANGEROUS;
continue;
}
}
} else if (className == "com.sun.star.uno.XAggregation")
{
if( aMethName == "setDelegator" )
{
rMethodConcept_i |= MethodConcept::DANGEROUS;
continue;
}
} else if (className
== "com.sun.star.container.XElementAccess")
{
rMethodConcept_i |= ( NAMECONTAINER |
INDEXCONTAINER |
ENUMERATION );
} else if ((className
== "com.sun.star.container.XNameContainer")
|| (className
== "com.sun.star.container.XNameAccess"))
{
rMethodConcept_i |= NAMECONTAINER;
} else if ((className
== "com.sun.star.container.XIndexContainer")
|| (className
== "com.sun.star.container.XIndexAccess"))
{
rMethodConcept_i |= INDEXCONTAINER;
} else if (className
== "com.sun.star.container.XEnumerationAccess")
{
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 == "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
IntrospectionAccessStatic_Impl::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
OUString aMethName2 = rxMethod_k->getName();
OUString aStartStr2 = aMethName2.copy( 0, 3 );
// ACHTUNG: Wegen SDL-Bug NICHT != bei OUString verwenden !!!
if( !( aStartStr2 == "set" ) )
continue;
// Ist es denn der gleiche Name?
OUString aPropName2 = aMethName2.copy( 3 );
// ACHTUNG: Wegen SDL-Bug NICHT != bei 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
IntrospectionAccessStatic_Impl::checkInterfaceArraySize( pAccess->aInterfaceSeq2,
pInterfaces2, rPropCount );
pInterfaces2[ rPropCount ] = rxMethod_k;
}
}
// Count pflegen
rPropCount++;
}
// Ist es eine addListener-Methode?
else if( aStartStr == "add" )
{
OUString aListenerStr( "Listener" );
// Namen der potentiellen Property
sal_Int32 nStrLen = aMethName.getLength();
sal_Int32 nCopyLen = nStrLen - aListenerStr.getLength();
OUString aEndStr = aMethName.copy( nCopyLen > 0 ? nCopyLen : 0 );
// Endet das Teil auf Listener?
// ACHTUNG: Wegen SDL-Bug NICHT != bei OUString verwenden !!!
if( !( aEndStr == aListenerStr ) )
continue;
// Welcher Listener?
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
OUString aMethName2 = rxMethod_k->getName();
sal_Int32 nNameLen = aMethName2.getLength();
sal_Int32 nCopyLen2 = (nNameLen < 6) ? nNameLen : 6;
OUString aStartStr2 = aMethName2.copy( 0, nCopyLen2 );
OUString aRemoveStr("remove" );
// ACHTUNG: Wegen SDL-Bug NICHT != bei OUString verwenden !!!
if( !( aStartStr2 == aRemoveStr ) )
continue;
// Ist es denn der gleiche Listener?
if( aMethName2.getLength() - aRemoveStr.getLength() <= aListenerStr.getLength() )
continue;
OUString aListenerName2 = aMethName2.copy
( 6, aMethName2.getLength() - aRemoveStr.getLength() - aListenerStr.getLength() );
// ACHTUNG: Wegen SDL-Bug NICHT != bei 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 == "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
IntrospectionAccessStatic_Impl::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
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
css::uno::Reference<css::reflection::XIdlClass>
xListenerClass(
reflection_->forName(
cppu::UnoType<void>::get()
.getTypeName()));
// 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();
css::uno::Reference<css::reflection::XIdlClass>
xEventListenerClass(
reflection_->forName(
cppu::UnoType<
css::lang::XEventListener>::get()
.getTypeName()));
// 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 = 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 );
}
// Bei structs Fields als Properties registrieren
else //if( eType == TypeClass_STRUCT )
{
// Ist es ein Interface oder eine struct?
//Reference<XIdlClass> xClassRef = aToInspectObj.getReflection()->getIdlClass();
css::uno::Reference<css::reflection::XIdlClass> xClassRef(
reflection_->forName(aToInspectObj.getValueTypeName()));
if( !xClassRef.is() )
{
SAL_WARN( "stoc", "Can't get XIdlClass from Reflection" );
return new ImplIntrospectionAccess(aToInspectObj, 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();
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
IntrospectionAccessStatic_Impl::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 new ImplIntrospectionAccess(aToInspectObj, pAccess);
}
struct Instance {
explicit Instance(
css::uno::Reference<css::uno::XComponentContext> const & context):
instance(new Implementation(context))
{}
rtl::Reference<cppu::OWeakObject> instance;
};
struct Singleton:
public rtl::StaticWithArg<
Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
{};
}
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
com_sun_star_comp_stoc_Introspection_get_implementation(
css::uno::XComponentContext * context,
css::uno::Sequence<css::uno::Any> const & arguments)
{
SAL_WARN_IF(
arguments.hasElements(), "stoc", "unexpected singleton arguments");
return cppu::acquire(Singleton::get(context).instance.get());
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */