/* -*- 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/main.h>
#include <cppuhelper/implbase.hxx>
#include <cppuhelper/servicefactory.hxx>
#include <osl/diagnose.h>
#include <ModuleA/XIntroTest.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XIntrospection.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/beans/XExactName.hpp>
#include <com/sun/star/container/XElementAccess.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/reflection/XIdlReflection.hpp>
#include <com/sun/star/registry/XImplementationRegistration.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace cppu;
using namespace ModuleA;
using namespace css::uno;
using namespace css::lang;
using namespace css::beans;
using namespace css::registry;
using namespace css::reflection;
using namespace css::container;
using namespace css::beans::PropertyAttribute;
#define DEFAULT_INDEX_ACCESS_COUNT 10
#define DEFAULT_NAME_ACCESS_COUNT 5
// Auxiliary function, in order to get from one type XIdlClass
Reference<XIdlClass> TypeToIdlClass(
const Type& rType,
const Reference< XMultiService
Factory > & xMgr )
{
static Reference< XIdlReflection > xRefl;
// register void as default class
Reference<XIdlClass> xRetClass;
typelib_TypeDescription * pTD = 0;
rType.getDescription( &pTD );
if ( pTD )
{
OUString sOWName( pTD->pTypeName );
if ( !xRefl.is() )
{
xRefl.set( xMgr->createInstance( "com.sun.star.reflection.CoreReflection" ), UNO_QUERY );
OSL_ENSURE( xRefl.is(), "### no corereflection!" );
}
xRetClass = xRefl->forName( sOWName );
}
return xRetClass;
}
// Helper function to convert Any to UString
// TODO: This code could be moved to a more central place.
// Currently it's used only for simple data types.
OUString AnyToString( const Any& aValue, sal_Bool bIncludeType, const Reference< XMultiServiceFactory > & xMgr )
{
Type aValType = aValue.getValueType();
TypeClass eType = aValType.getTypeClass();
char pBuffer[50];
OUString aRetStr;
switch ( eType )
{
case TypeClass_TYPE: aRetStr = "TYPE TYPE" ; break ;
case TypeClass_INTERFACE: aRetStr = "TYPE INTERFACE" ; break ;
case TypeClass_SERVICE: aRetStr = "TYPE SERVICE" ; break ;
case TypeClass_STRUCT: aRetStr = "TYPE STRUCT" ; break ;
case TypeClass_TYPEDEF: aRetStr = "TYPE TYPEDEF" ; break ;
case TypeClass_ENUM: aRetStr = "TYPE ENUM" ; break ;
case TypeClass_EXCEPTION: aRetStr = "TYPE EXCEPTION" ; break ;
case TypeClass_SEQUENCE: aRetStr = "TYPE SEQUENCE" ; break ;
case TypeClass_VOID: aRetStr = "TYPE void" ; break ;
case TypeClass_ANY: aRetStr = "TYPE any" ; break ;
case TypeClass_UNKNOWN: aRetStr = "TYPE unknown" ; break ;
case TypeClass_BOOLEAN:
{
sal_Bool b = *(sal_Bool*)aValue.getValue();
aRetStr = OUString::valueOf( b );
break ;
}
case TypeClass_CHAR:
{
sal_Unicode c = *(sal_Unicode*)aValue.getValue();
aRetStr = OUString::valueOf( c );
break ;
}
case TypeClass_STRING:
{
aValue >>= aRetStr;
break ;
}
case TypeClass_FLOAT:
{
float f(0.0);
aValue >>= f;
snprintf( pBuffer, sizeof ( pBuffer ), "%f" , f );
aRetStr = OUString( pBuffer, strlen( pBuffer ), RTL_TEXTENCODING_ASCII_US );
break ;
}
case TypeClass_DOUBLE:
{
double d(0.0);
aValue >>= d;
snprintf( pBuffer, sizeof ( pBuffer ), "%f" , d );
aRetStr = OUString( pBuffer, strlen( pBuffer ), RTL_TEXTENCODING_ASCII_US );
break ;
}
case TypeClass_BYTE:
{
sal_Int8 n(0);
aValue >>= n;
aRetStr = OUString::valueOf( (sal_Int32) n );
break ;
}
case TypeClass_SHORT:
{
sal_Int16 n(0);
aValue >>= n;
aRetStr = OUString::valueOf( (sal_Int32) n );
break ;
}
case TypeClass_LONG:
{
sal_Int32 n(0);
aValue >>= n;
aRetStr = OUString::valueOf( n );
break ;
}
default : ;
}
if ( bIncludeType )
{
Reference< XIdlClass > xIdlClass = TypeToIdlClass( aValType, xMgr );
aRetStr += " (Typ: " + xIdlClass->getName() + ")" ;
}
return aRetStr;
}
// XPropertySetInfo for test class
class ImplPropertySetInfo : public WeakImplHelper< XPropertySetInfo >
{
friend class ImplIntroTest;
Reference< XMultiServiceFactory > mxMgr;
public :
explicit ImplPropertySetInfo( const Reference< XMultiServiceFactory > & xMgr )
: mxMgr( xMgr ) {}
// Methods of XPropertySetInfo
virtual Sequence< Property > SAL_CALL getProperties( )
throw (RuntimeException);
virtual Property SAL_CALL getPropertyByName( const OUString& aName )
throw (UnknownPropertyException, RuntimeException);
virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name )
throw (RuntimeException);
};
Sequence< Property > ImplPropertySetInfo::getProperties()
throw ( RuntimeException )
{
static Sequence<Property> * pSeq = NULL;
if ( !pSeq )
{
// Create information for the properties "Width", "Height" and "Name"
pSeq = new Sequence<Property>( 3 );
Property * pAry = pSeq->getArray();
pAry[0].Name = "Factor" ;
pAry[0].Handle = -1;
pAry[0].Type = cppu::UnoType<double >::get();
pAry[0].Attributes = BOUND | TRANSIENT;
pAry[1].Name = "MyCount" ;
pAry[1].Handle = -1;
pAry[1].Type = cppu::UnoType<sal_Int32>::get();
pAry[1].Attributes = BOUND | TRANSIENT;
pAry[2].Name = "Info" ;
pAry[2].Handle = -1;
pAry[2].Type = cppu::UnoType<OUString>::get();
pAry[2].Attributes = TRANSIENT;
}
// Return information about all three properties
return *pSeq;
}
Property ImplPropertySetInfo::getPropertyByName(const OUString& Name)
throw ( UnknownPropertyException, RuntimeException )
{
Sequence<Property> aSeq = getProperties();
const Property * pAry = aSeq.getConstArray();
for ( sal_Int32 i = aSeq.getLength(); i--; )
{
if ( pAry[i].Name == Name )
return pAry[i];
}
// Property unknown, also return empty ones
return Property();
}
sal_Bool ImplPropertySetInfo::hasPropertyByName(const OUString& Name)
throw ( RuntimeException )
{
Sequence<Property> aSeq = getProperties();
const Property * pAry = aSeq.getConstArray();
for ( sal_Int32 i = aSeq.getLength(); i--; )
{
if ( pAry[i].Name == Name )
return sal_True;
}
// Property unknown, also return empty ones
return sal_False;
}
class ImplIntroTest : public WeakImplHelper< XIntroTest, XPropertySet, XNameAccess, XIndexAccess >
{
Reference< XMultiServiceFactory > mxMgr;
friend class ImplPropertySetInfo;
// Properties for the PropertySet
Any aAnyArray[10];
Reference< XPropertySetInfo > m_xMyInfo;
OUString m_ObjectName;
sal_Int16 m_nMarkusAge;
sal_Int16 m_nMarkusChildrenCount;
long m_lDroenk;
sal_Int16 m_nBla;
sal_Int16 m_nBlub;
sal_Int16 m_nGulp;
sal_Int16 m_nLaber;
TypeClass eTypeClass;
Sequence< OUString > aStringSeq;
Sequence< Sequence< Sequence< sal_Int16 > > > aMultSeq;
Reference< XIntroTest > m_xIntroTest;
// Data for NameAccess
Reference< XIntroTest >* pNameAccessTab;
// Data for IndexAccess
Reference< XIntroTest >* pIndexAccessTab;
sal_Int16 iIndexAccessCount;
// struct properties
Property m_aFirstStruct;
PropertyValue m_aSecondStruct;
// remember listener (one listener per property)
Reference< XPropertyChangeListener > aPropChangeListener;
OUString aPropChangeListenerStr;
Reference< XVetoableChangeListener > aVetoPropChangeListener;
OUString aVetoPropChangeListenerStr;
void Init();
public :
explicit ImplIntroTest( const Reference< XMultiServiceFactory > & xMgr )
: mxMgr( xMgr )
{
Init();
}
// despite virtual inline, to simplify coding (testing only)
// XPropertySet
virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo( )
throw (RuntimeException);
virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const Any& aValue )
throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException);
virtual Any SAL_CALL getPropertyValue( const OUString& PropertyName )
throw (UnknownPropertyException, WrappedTargetException, RuntimeException);
virtual void SAL_CALL addPropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ )
throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
{}
virtual void SAL_CALL removePropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*aListener*/ )
throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
{}
virtual void SAL_CALL addVetoableChangeListener( const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener >& /*aListener*/ )
throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
{}
virtual void SAL_CALL removeVetoableChangeListener( const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener >& /*aListener*/ )
throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
{}
// XIntroTest methods
// Attributes
virtual OUString SAL_CALL getObjectName() throw (RuntimeException)
{ return m_ObjectName; }
virtual void SAL_CALL setObjectName( const OUString& _objectname ) throw (RuntimeException)
{ m_ObjectName = _objectname; }
virtual OUString SAL_CALL getFirstName()
throw (RuntimeException);
virtual OUString SAL_CALL getLastName() throw (RuntimeException)
{ return OUString("Meyer" ); }
virtual sal_Int16 SAL_CALL getAge() throw (RuntimeException)
{ return m_nMarkusAge; }
virtual sal_Int16 SAL_CALL getChildrenCount() throw (RuntimeException)
{ return m_nMarkusChildrenCount; }
virtual void SAL_CALL setChildrenCount( sal_Int16 _childrencount ) throw (RuntimeException)
{ m_nMarkusChildrenCount = _childrencount; }
virtual Property SAL_CALL getFirstStruct() throw (RuntimeException)
{ return m_aFirstStruct; }
virtual void SAL_CALL setFirstStruct( const Property& _firststruct ) throw (RuntimeException)
{ m_aFirstStruct = _firststruct; }
virtual PropertyValue SAL_CALL getSecondStruct() throw (RuntimeException)
{ return m_aSecondStruct; }
virtual void SAL_CALL setSecondStruct( const PropertyValue& _secondstruct ) throw (RuntimeException)
{ m_aSecondStruct = _secondstruct; }
// Methods
virtual void SAL_CALL writeln( const OUString& Text )
throw (RuntimeException);
virtual sal_Int32 SAL_CALL getDroenk( ) throw (RuntimeException)
{ return m_lDroenk; }
virtual Reference< ::ModuleA::XIntroTest > SAL_CALL getIntroTest( ) throw (RuntimeException);
virtual sal_Int32 SAL_CALL getUps( sal_Int32 l ) throw (RuntimeException)
{ return 2*l; }
virtual void SAL_CALL setDroenk( sal_Int32 l ) throw (RuntimeException)
{ m_lDroenk = l; }
virtual sal_Int16 SAL_CALL getBla( ) throw (RuntimeException)
{ return m_nBla; }
virtual void SAL_CALL setBla( sal_Int32 n ) throw (RuntimeException)
{ m_nBla = (sal_Int16)n; }
virtual sal_Int16 SAL_CALL getBlub( ) throw (RuntimeException)
{ return m_nBlub; }
virtual void SAL_CALL setBlub( sal_Int16 n ) throw (RuntimeException)
{ m_nBlub = n; }
virtual sal_Int16 SAL_CALL getGulp( ) throw (RuntimeException)
{ return m_nGulp; }
virtual sal_Int16 SAL_CALL setGulp( sal_Int16 n ) throw (RuntimeException)
{ m_nGulp = n; return 1; }
virtual TypeClass SAL_CALL getTypeClass( sal_Int16 /*n*/ ) throw(RuntimeException)
{ return eTypeClass; }
virtual void SAL_CALL setTypeClass( TypeClass t, double /*d1*/, double /*d2*/ ) throw(RuntimeException)
{ eTypeClass = t; }
virtual Sequence< OUString > SAL_CALL getStrings( ) throw (RuntimeException)
{ return aStringSeq; }
virtual void SAL_CALL setStrings( const Sequence< OUString >& Strings ) throw (RuntimeException)
{ aStringSeq = Strings; }
virtual void SAL_CALL setStringsPerMethod( const Sequence< OUString >& Strings, sal_Int16 /*n*/ ) throw(RuntimeException)
{ aStringSeq = Strings; }
virtual Sequence< Sequence< Sequence< sal_Int16 > > > SAL_CALL getMultiSequence( ) throw (RuntimeException)
{ return aMultSeq; }
virtual void SAL_CALL setMultiSequence( const Sequence< Sequence< Sequence< sal_Int16 > > >& Seq ) throw (RuntimeException)
{ aMultSeq = Seq; }
virtual void SAL_CALL addPropertiesChangeListener( const Sequence< OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener )
throw (RuntimeException);
virtual void SAL_CALL removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& Listener )
throw (RuntimeException);
// Methods of XElementAccess
virtual Type SAL_CALL getElementType( )
throw (RuntimeException);
virtual sal_Bool SAL_CALL hasElements( )
throw (RuntimeException);
// XNameAccess methods
// Methods
virtual Any SAL_CALL getByName( const OUString& aName )
throw (NoSuchElementException, WrappedTargetException, RuntimeException);
virtual Sequence< OUString > SAL_CALL getElementNames( )
throw (RuntimeException);
virtual sal_Bool SAL_CALL hasByName( const OUString& aName )
throw (RuntimeException);
// XIndexAccess methods
// Methods
virtual sal_Int32 SAL_CALL getCount( )
throw (RuntimeException);
virtual Any SAL_CALL getByIndex( sal_Int32 Index )
throw (IndexOutOfBoundsException, WrappedTargetException, RuntimeException);
};
void ImplIntroTest::Init()
{
// set unique name
static sal_Int32 nObjCount = 0;
OUString aName( "IntroTest-Obj Nr. " );
aName += OUString::valueOf( nObjCount );
setObjectName( aName );
// initialize properties
aAnyArray[0] <<= 3.14;
aAnyArray[1] <<= (sal_Int32)42;
aAnyArray[2] <<= OUString( "Hallo" );
// fetch PropertySetInfo once for internal use
m_xMyInfo = getPropertySetInfo();
m_xMyInfo->acquire(); // otherwise it could crash at shutdown
m_nMarkusAge = 33;
m_nMarkusChildrenCount = 2;
m_lDroenk = 314;
m_nBla = 42;
m_nBlub = 111;
m_nGulp = 99;
m_nLaber = 1;
eTypeClass = TypeClass_INTERFACE;
// string sequence initialization
aStringSeq.realloc( 3 );
aStringSeq[ 0 ] = "String 0" ;
aStringSeq[ 1 ] = "String 1" ;
aStringSeq[ 2 ] = "String 2" ;
// structs initialization
m_aFirstStruct.Name = "FirstStruct-Name" ;
m_aFirstStruct.Handle = 77777;
//XIdlClassRef Type;
m_aFirstStruct.Attributes = -222;
//XInterfaceRef Source;
Any Value;
Value <<= M_E;
m_aSecondStruct.Value = Value;
//XIdlClassRef ListenerType;
m_aSecondStruct.State = PropertyState_DIRECT_VALUE;
// IndexAccess
iIndexAccessCount = DEFAULT_INDEX_ACCESS_COUNT;
pIndexAccessTab = NULL;
pNameAccessTab = NULL;
}
Reference< XPropertySetInfo > ImplIntroTest::getPropertySetInfo()
throw (RuntimeException)
{
static ImplPropertySetInfo aInfo( mxMgr );
// All objects have the same Properties, so
// the Info is the same for all
return &aInfo;
}
void ImplIntroTest::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
{
if ( aPropChangeListener.is() && aPropertyName == aPropChangeListenerStr )
{
PropertyChangeEvent aEvt;
aEvt.Source = (OWeakObject*)this ;
aEvt.PropertyName = aPropertyName;
aEvt.PropertyHandle = 0;
aPropChangeListener->propertyChange( aEvt );
}
if ( aVetoPropChangeListener.is() && aPropertyName == aVetoPropChangeListenerStr )
{
PropertyChangeEvent aEvt;
aEvt.Source = (OWeakObject*)this ;
aEvt.PropertyName = aVetoPropChangeListenerStr;
aEvt.PropertyHandle = 0;
aVetoPropChangeListener->vetoableChange( aEvt );
}
Sequence<Property> aPropSeq = m_xMyInfo->getProperties();
sal_Int32 nLen = aPropSeq.getLength();
for ( sal_Int32 i = 0 ; i < nLen ; i++ )
{
Property aProp = aPropSeq.getArray()[ i ];
if ( aProp.Name == aPropertyName )
aAnyArray[i] = aValue;
}
}
Any ImplIntroTest::getPropertyValue( const OUString& PropertyName )
throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
{
Sequence<Property> aPropSeq = m_xMyInfo->getProperties();
sal_Int32 nLen = aPropSeq.getLength();
for ( sal_Int32 i = 0 ; i < nLen ; i++ )
{
Property aProp = aPropSeq.getArray()[ i ];
if ( aProp.Name == PropertyName )
return aAnyArray[i];
}
return Any();
}
OUString ImplIntroTest::getFirstName()
throw (RuntimeException)
{
return OUString("Markus" );
}
void ImplIntroTest::writeln( const OUString& Text )
throw (RuntimeException)
{
OString aStr( Text.getStr(), Text.getLength(), RTL_TEXTENCODING_ASCII_US );
printf( "%s" , aStr.getStr() );
}
Reference< XIntroTest > ImplIntroTest::getIntroTest()
throw (RuntimeException)
{
if ( !m_xIntroTest.is() )
m_xIntroTest = new ImplIntroTest( mxMgr );
return m_xIntroTest;
}
// Methods of XElementAccess
Type ImplIntroTest::getElementType( )
throw (RuntimeException)
{
// TODO
Type aRetType;
return aRetType;
}
sal_Bool ImplIntroTest::hasElements( )
throw (RuntimeException)
{
return sal_True;
}
// XNameAccess methods
sal_Int32 getIndexForName( const OUString& ItemName )
{
OUString aLeftStr = ItemName.copy( 0, 4 );
if ( aLeftStr == "Item" )
{
// TODO
OUString aNumStr = ItemName.copy( 4 );
}
return -1;
}
Any ImplIntroTest::getByName( const OUString& aName )
throw (NoSuchElementException, WrappedTargetException, RuntimeException)
{
Any aRetAny;
if ( !pNameAccessTab )
pNameAccessTab = new Reference< XIntroTest >[ DEFAULT_NAME_ACCESS_COUNT ];
sal_Int32 iIndex = getIndexForName( aName );
if ( iIndex != -1 )
{
if ( !pNameAccessTab[iIndex].is() )
{
ImplIntroTest* p = new ImplIntroTest( mxMgr );
OUString aName2( "IntroTest by Name-Access, Index = " );
aName2 += OUString::valueOf( iIndex );
p->setObjectName( aName2 );
pNameAccessTab[iIndex] = p;
}
Reference< XIntroTest > xRet = pNameAccessTab[iIndex];
aRetAny = makeAny( xRet );
}
return aRetAny;
}
Sequence< OUString > ImplIntroTest::getElementNames( )
throw (RuntimeException)
{
Sequence<OUString> aStrSeq( DEFAULT_NAME_ACCESS_COUNT );
OUString* pStr = aStrSeq.getArray();
for ( sal_Int32 i = 0 ; i < DEFAULT_NAME_ACCESS_COUNT ; i++ )
{
OUString aName( "Item" );
aName += OUString::valueOf( i );
pStr[i] = aName;
}
return aStrSeq;
}
sal_Bool ImplIntroTest::hasByName( const OUString& aName )
throw (RuntimeException)
{
return ( getIndexForName( aName ) != -1 );
}
// XIndexAccess methods
sal_Int32 ImplIntroTest::getCount( )
throw (RuntimeException)
{
return iIndexAccessCount;
}
Any ImplIntroTest::getByIndex( sal_Int32 Index )
throw (IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
{
Any aRetAny;
if ( !pIndexAccessTab )
pIndexAccessTab = new Reference< XIntroTest >[ iIndexAccessCount ];
if ( Index < iIndexAccessCount )
{
if ( !pNameAccessTab[Index].is() )
{
ImplIntroTest* p = new ImplIntroTest( mxMgr );
OUString aName( "IntroTest by Index-Access, Index = " );
aName += OUString::valueOf( Index );
p->setObjectName( aName );
pIndexAccessTab[Index] = p;
}
Reference< XIntroTest > xRet = pIndexAccessTab[Index];
aRetAny = makeAny( xRet );
}
return aRetAny;
}
void ImplIntroTest::addPropertiesChangeListener( const Sequence< OUString >& /*PropertyNames*/,
const Reference< XPropertiesChangeListener >& /*Listener*/ )
throw (RuntimeException)
{
}
void ImplIntroTest::removePropertiesChangeListener
( const Reference< XPropertiesChangeListener >& /*Listener*/ )
throw (RuntimeException)
{
}
struct DefItem
{
char const * pName;
sal_Int32 nConcept;
};
// special value for method concept, to mark "normal" functions
#define MethodConcept_NORMAL_IMPL 0x80000000
// return test object
Any getIntrospectionTestObject( const Reference< XMultiServiceFactory > & xMgr )
{
Any aObjAny;
Reference< XIntroTest > xTestObj = new ImplIntroTest( xMgr );
aObjAny.setValue( &xTestObj, cppu::UnoType<XIntroTest>::get());
return aObjAny;
}
static sal_Bool test_introsp( Reference< XMultiServiceFactory > xMgr,
Reference< XIdlReflection > /*xRefl*/, Reference< XIntrospection > xIntrospection )
{
DefItem pPropertyDefs[] =
{
{ "Factor" , PropertyConcept::PROPERTYSET },
{ "MyCount" , PropertyConcept::PROPERTYSET },
{ "Info" , PropertyConcept::PROPERTYSET },
{ "ObjectName" , PropertyConcept::ATTRIBUTES },
{ "FirstName" , PropertyConcept::ATTRIBUTES },
{ "LastName" , PropertyConcept::ATTRIBUTES },
{ "Age" , PropertyConcept::ATTRIBUTES },
{ "ChildrenCount" , PropertyConcept::ATTRIBUTES },
{ "FirstStruct" , PropertyConcept::ATTRIBUTES },
{ "SecondStruct" , PropertyConcept::ATTRIBUTES },
{ "Droenk" , PropertyConcept::METHODS },
{ "IntroTest" , PropertyConcept::METHODS },
{ "Bla" , PropertyConcept::METHODS },
{ "Blub" , PropertyConcept::METHODS },
{ "Gulp" , PropertyConcept::METHODS },
{ "Strings" , PropertyConcept::METHODS },
{ "MultiSequence" , PropertyConcept::METHODS },
{ "PropertySetInfo" , PropertyConcept::METHODS },
{ "ElementType" , PropertyConcept::METHODS },
{ "ElementNames" , PropertyConcept::METHODS },
{ "Count" , PropertyConcept::METHODS },
{ "Types" , PropertyConcept::METHODS },
{ "ImplementationId" , PropertyConcept::METHODS },
{ NULL, 0 }
};
char const * pDemandedPropVals[] =
{
"3.140000" ,
"42" ,
"Hallo" ,
"IntroTest-Obj Nr. 0" ,
"Markus" ,
"Meyer" ,
"33" ,
"2" ,
"TYPE STRUCT" ,
"TYPE STRUCT" ,
"314" ,
"TYPE INTERFACE" ,
"42" ,
"111" ,
"99" ,
"TYPE SEQUENCE" ,
"TYPE SEQUENCE" ,
"TYPE INTERFACE" ,
"TYPE TYPE" ,
"TYPE SEQUENCE" ,
"10" ,
"TYPE SEQUENCE" ,
"TYPE SEQUENCE" ,
};
char const * pDemandedModifiedPropVals[] =
{
"4.140000" ,
"43" ,
"Hallo (Modified!)" ,
"IntroTest-Obj Nr. 0 (Modified!)" ,
"Markus" ,
"Meyer" ,
"33" ,
"3" ,
"Value has not been modified" ,
"Value has not been modified" ,
"315" ,
"Value has not been modified" ,
"42" ,
"112" ,
"99" ,
"Value has not been modified" ,
"Value has not been modified" ,
"Value has not been modified" ,
"Value has not been modified" ,
"Value has not been modified" ,
"10" ,
"Value has not been modified" ,
"Value has not been modified" ,
};
char const * pDemandedPropTypes[] =
{
"double" ,
"long" ,
"string" ,
"string" ,
"string" ,
"string" ,
"short" ,
"short" ,
"com.sun.star.beans.Property" ,
"com.sun.star.beans.PropertyValue" ,
"long" ,
"ModuleA.XIntroTest" ,
"short" ,
"short" ,
"short" ,
"[]string" ,
"[][][]short" ,
"com.sun.star.beans.XPropertySetInfo" ,
"type" ,
"[]string" ,
"long" ,
"[]type" ,
"[]byte" ,
};
DefItem pMethodDefs[] =
{
{ "queryInterface" , MethodConcept_NORMAL_IMPL },
{ "acquire" , MethodConcept::DANGEROUS },
{ "release" , MethodConcept::DANGEROUS },
{ "writeln" , MethodConcept_NORMAL_IMPL },
{ "getDroenk" , MethodConcept::PROPERTY },
{ "getIntroTest" , MethodConcept::PROPERTY },
{ "getUps" , MethodConcept_NORMAL_IMPL },
{ "setDroenk" , MethodConcept::PROPERTY },
{ "getBla" , MethodConcept::PROPERTY },
{ "setBla" , MethodConcept_NORMAL_IMPL },
{ "getBlub" , MethodConcept::PROPERTY },
{ "setBlub" , MethodConcept::PROPERTY },
{ "getGulp" , MethodConcept::PROPERTY },
{ "setGulp" , MethodConcept_NORMAL_IMPL },
{ "getTypeClass" , MethodConcept_NORMAL_IMPL },
{ "setTypeClass" , MethodConcept_NORMAL_IMPL },
{ "getStrings" , MethodConcept::PROPERTY },
{ "setStrings" , MethodConcept::PROPERTY },
{ "setStringsPerMethod" , MethodConcept_NORMAL_IMPL },
{ "getMultiSequence" , MethodConcept::PROPERTY },
{ "setMultiSequence" , MethodConcept::PROPERTY },
{ "addPropertiesChangeListener" , MethodConcept::LISTENER },
{ "removePropertiesChangeListener" , MethodConcept::LISTENER },
{ "getPropertySetInfo" , MethodConcept::PROPERTY },
{ "setPropertyValue" , MethodConcept_NORMAL_IMPL },
{ "getPropertyValue" , MethodConcept_NORMAL_IMPL },
{ "addPropertyChangeListener" , MethodConcept::LISTENER },
{ "removePropertyChangeListener" , MethodConcept::LISTENER },
{ "addVetoableChangeListener" , MethodConcept::LISTENER },
{ "removeVetoableChangeListener" , MethodConcept::LISTENER },
{ "getElementType" , MethodConcept::PROPERTY | MethodConcept::NAMECONTAINER| MethodConcept::INDEXCONTAINER | MethodConcept::ENUMERATION },
{ "hasElements" , MethodConcept::NAMECONTAINER | MethodConcept::INDEXCONTAINER | MethodConcept::ENUMERATION },
{ "getByName" , MethodConcept::NAMECONTAINER },
{ "getElementNames" , MethodConcept::PROPERTY | MethodConcept::NAMECONTAINER },
{ "hasByName" , MethodConcept::NAMECONTAINER },
{ "getCount" , MethodConcept::PROPERTY | MethodConcept::INDEXCONTAINER },
{ "getByIndex" , MethodConcept::INDEXCONTAINER },
{ "getTypes" , MethodConcept::PROPERTY },
{ "getImplementationId" , MethodConcept::PROPERTY },
{ "queryAdapter" , MethodConcept_NORMAL_IMPL },
{ NULL, 0 }
};
OString aErrorStr;
// create test object
Any aObjAny = getIntrospectionTestObject( xMgr );
// inspect introspection service
xIntrospection->inspect( aObjAny );
xIntrospection->inspect( aObjAny );
Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny );
OSL_ENSURE( xAccess.is(), "introspection failed, no XIntrospectionAccess returned" );
if ( !xAccess.is() )
return sal_False;
// check result of introspection
// determine XPropertySet-UIK
Type aType = cppu::UnoType<XPropertySet>::get();
Reference< XInterface > xPropSetIface = xAccess->queryAdapter( aType );
Reference< XPropertySet > xPropSet( xPropSetIface, UNO_QUERY );
OSL_ENSURE( xPropSet.is(), "Could not get XPropertySet by queryAdapter()" );
// XExactName
Reference< XExactName > xExactName( xAccess, UNO_QUERY );
OSL_ENSURE( xExactName.is(), "Introspection doesn't support ExactName" );
// loop over all concept combinations
for ( sal_Int32 nConcepts = 0 ; nConcepts < 16 ; nConcepts++ )
{
// how many properties should this be
sal_Int32 nDemandedPropCount = 0;
sal_Int32 iList = 0;
while ( pPropertyDefs[ iList ].pName )
{
if ( pPropertyDefs[ iList ].nConcept & nConcepts )
nDemandedPropCount++;
iList++;
}
if ( xPropSet.is() )
{
Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
Sequence<Property> aRetSeq = xAccess->getProperties( nConcepts );
sal_Int32 nLen = aRetSeq.getLength();
aErrorStr = "Expected to find "
+ OString::valueOf( nDemandedPropCount )
+ " properties but found "
+ OString::valueOf( nLen );
OSL_ENSURE( nLen == nDemandedPropCount, aErrorStr.getStr() );
const Property* pProps = aRetSeq.getConstArray();
Any aPropVal;
sal_Int32 i;
iList = 0;
for ( i = 0 ; i < nLen ; i++ )
{
const Property aProp = pProps[ i ];
// search for next suitable method in the list
while ( pPropertyDefs[ iList ].pName )
{
if ( pPropertyDefs[ iList ].nConcept & nConcepts )
break ;
iList++;
}
sal_Int32 iDemanded = iList;
iList++;
OUString aPropName = aProp.Name;
OString aNameStr( aPropName.getStr(), aPropName.getLength(), RTL_TEXTENCODING_ASCII_US );
OString aDemandedName = pPropertyDefs[ iDemanded ].pName;
aErrorStr = "Expected property \" "
+ aDemandedName
+ "\" , found \""
+ aNameStr
+ "\" ";
OSL_ENSURE( aNameStr == aDemandedName, aErrorStr.getStr() );
Type aPropType = aProp.Type;
OString aTypeNameStr( OUStringToOString(aPropType.getTypeName(), RTL_TEXTENCODING_ASCII_US) );
OString aDemandedTypeNameStr = pDemandedPropTypes[ iDemanded ];
aErrorStr = "Property \" "
+ aDemandedName
+ "\" , expected type >"
+ aDemandedTypeNameStr
+ "< found type >"
+ aTypeNameStr
+ "<" ;
OSL_ENSURE( aTypeNameStr == aDemandedTypeNameStr, aErrorStr.getStr() );
// read and report value of property
aPropVal = xPropSet->getPropertyValue( aPropName );
OString aValStr = OUStringToOString( AnyToString( aPropVal, sal_False, xMgr ), RTL_TEXTENCODING_ASCII_US );
OString aDemandedValStr = pDemandedPropVals[ iDemanded ];
aErrorStr = "Property \" "
+ aDemandedName
+ "\" , expected val >"
+ aDemandedValStr
+ "< found val >"
+ aValStr
+ "<" ;
OSL_ENSURE( aValStr == aDemandedValStr, aErrorStr.getStr() );
// check value and modify it according to its type
TypeClass eType = aPropVal.getValueTypeClass();
Any aNewVal;
sal_Bool bModify = sal_True;
switch ( eType )
{
case TypeClass_STRING:
{
OUString aStr;
aPropVal >>= aStr;
aStr += " (Modified!)" ;
aNewVal <<= aStr;
break ;
}
case TypeClass_DOUBLE:
{
double d(0.0);
aPropVal >>= d;
aNewVal <<= d + 1.0;
break ;
}
case TypeClass_SHORT:
{
sal_Int16 n(0);
aPropVal >>= n;
aNewVal <<= sal_Int16( n + 1 );
break ;
}
case TypeClass_LONG:
{
sal_Int32 n(0);
aPropVal >>= n;
aNewVal <<= sal_Int32( n + 1 );
break ;
}
default :
bModify = sal_False;
break ;
}
// modify only in the last iteration
if ( nConcepts == 15 )
{
// check XExactName, switch everything to upper case
// (introspection uses lower case)
OUString aUpperUStr = aPropName.toAsciiUpperCase();
OUString aExactName = xExactName->getExactName( aUpperUStr );
if ( aExactName != aPropName )
{
aErrorStr = "Property \" "
+ OUStringToOString( aPropName, RTL_TEXTENCODING_ASCII_US )
+ "\" , not found as \""
+ OUStringToOString(aUpperUStr, RTL_TEXTENCODING_ASCII_US )
+ "\" using XExactName";
OSL_ENSURE( sal_False, aErrorStr.getStr() );
}
}
else
{
bModify = sal_False;
}
// set new value, then read and return value
if ( bModify )
{
// catch UnknownPropertyException for ReadOnly properties
try
{
xPropSet->setPropertyValue( aPropName, aNewVal );
}
catch (const UnknownPropertyException &)
{
}
aPropVal = xPropSet->getPropertyValue( aPropName );
OUString aStr = AnyToString( aPropVal, sal_False, xMgr );
OString aModifiedValStr = OUStringToOString( aStr, RTL_TEXTENCODING_ASCII_US );
OString aDemandedModifiedValStr = pDemandedModifiedPropVals[ i ];
aErrorStr = "Property \" "
+ aDemandedName
+ "\" , expected modified val >"
+ aDemandedModifiedValStr
+ "< found val >"
+ aModifiedValStr
+ "<" ;
OSL_ENSURE( aModifiedValStr == aDemandedModifiedValStr, aErrorStr.getStr() );
}
// check whether all properties can be found individually
aErrorStr = "property \" "
+ aDemandedName
+ "\" not found with hasProperty()";
OUString aWDemandedName = OStringToOUString(aDemandedName, RTL_TEXTENCODING_ASCII_US );
sal_Bool bProperty = xAccess->hasProperty( aWDemandedName, nConcepts );
OSL_ENSURE( bProperty, aErrorStr.getStr() );
aErrorStr = "property \" "
+ aDemandedName
+ "\" not equal to same Property in sequence returned by getProperties()";
try
{
Property aGetProp = xAccess->getProperty( aWDemandedName, nConcepts );
}
catch (const RuntimeException &)
{
aErrorStr = "property \" "
+ aDemandedName
+ "\" , exception was thrown when trying getProperty()";
OSL_ENSURE( sal_False, aErrorStr.getStr() );
}
}
}
}
// loop over all concept combinations
for ( sal_Int32 nConcepts = 0 ; nConcepts < 128 ; nConcepts++ )
{
// The 2^6th bit stands for "the rest"
sal_Int32 nRealConcepts = nConcepts;
if ( nConcepts & 0x40 )
nRealConcepts |= (0xFFFFFFFF - 0x3F);
// Count the number of methods there should be
sal_Int32 nDemandedMethCount = 0;
sal_Int32 iList = 0;
while ( pMethodDefs[ iList ].pName )
{
if ( pMethodDefs[ iList ].nConcept & nRealConcepts )
nDemandedMethCount++;
iList++;
}
// Output the method array.
Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( nRealConcepts );
sal_Int32 nLen = aMethodSeq.getLength();
aErrorStr = "Expected to find "
+ OString::valueOf( nDemandedMethCount )
+ " methods but found "
+ OString::valueOf( nLen );
OSL_ENSURE( nLen == nDemandedMethCount, aErrorStr.getStr() );
const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
sal_Int32 i;
iList = 0;
for ( i = 0 ; i < nLen ; i++ )
{
const Reference< XIdlMethod >& rxMethod = pMethods[i];
OUString aMethName = rxMethod->getName();
OString aNameStr = OUStringToOString(aMethName, RTL_TEXTENCODING_ASCII_US );
// locate the next matching method in the list.
while ( pMethodDefs[ iList ].pName )
{
if ( pMethodDefs[ iList ].nConcept & nRealConcepts )
break ;
iList++;
}
OString aDemandedName = pMethodDefs[ iList ].pName;
iList++;
aErrorStr = "Expected method \" "
+ aDemandedName
+ "\" , found \""
+ aNameStr
+ "\" ";
OSL_ENSURE( aNameStr == aDemandedName, aErrorStr.getStr() );
// Check that the method is really there with hasMethod.
aErrorStr = "method \" "
+ aDemandedName
+ "\" not found with hasMethod()";
OUString aWDemandedName = OStringToOUString(aDemandedName, RTL_TEXTENCODING_ASCII_US );
sal_Bool bMethod = xAccess->hasMethod( aWDemandedName, nRealConcepts );
OSL_ENSURE( bMethod, aErrorStr.getStr() );
aErrorStr = "method \" "
+ aDemandedName
+ "\" not equal to same method in sequence returned by getMethods()";
try
{
Reference< XIdlMethod > xGetMethod = xAccess->getMethod( aWDemandedName, nRealConcepts );
OSL_ENSURE( xGetMethod == rxMethod , aErrorStr.getStr() );
}
catch (const RuntimeException &)
{
aErrorStr = "method \" "
+ aDemandedName
+ "\" , exception was thrown when trying getMethod()";
OSL_ENSURE( sal_False, aErrorStr.getStr() );
}
}
}
// print listener class
Sequence< Type > aClassSeq = xAccess->getSupportedListeners();
sal_Int32 nLen = aClassSeq.getLength();
const Type* pListeners = aClassSeq.getConstArray();
for ( sal_Int32 i = 0 ; i < nLen ; i++ )
{
const Type& aListenerType = pListeners[i];
OUString aListenerClassName = aListenerType.getTypeName();
}
return sal_True;
}
SAL_IMPLEMENT_MAIN()
{
Reference< XMultiServiceFactory > xMgr( createRegistryServiceFactory( OUString("stoctest.rdb" ) ) );
sal_Bool bSucc = sal_False;
try
{
Reference< XImplementationRegistration > xImplReg(
xMgr->createInstance("com.sun.star.registry.ImplementationRegistration" ), UNO_QUERY );
OSL_ENSURE( xImplReg.is(), "### no impl reg!" );
// Register services
OUString libName( "reflection.uno" SAL_DLLEXTENSION );
fprintf(stderr, "1\n" );
xImplReg->registerImplementation(OUString("com.sun.star.loader.SharedLibrary" ),
libName, Reference< XSimpleRegistry >() );
fprintf(stderr, "2\n" );
Reference< XIdlReflection > xRefl( xMgr->createInstance("com.sun.star.reflection.CoreReflection" ), UNO_QUERY );
OSL_ENSURE( xRefl.is(), "### no corereflection!" );
// Introspection
libName = OUString( "introspection.uno" SAL_DLLEXTENSION);
fprintf(stderr, "3\n" );
xImplReg->registerImplementation(OUString("com.sun.star.loader.SharedLibrary" ),
libName, Reference< XSimpleRegistry >() );
fprintf(stderr, "4\n" );
Reference< XIntrospection > xIntrosp( xMgr->createInstance("com.sun.star.beans.Introspection" ), UNO_QUERY );
OSL_ENSURE( xRefl.is(), "### no corereflection!" );
fprintf(stderr, "before test_introsp\n" );
bSucc = test_introsp( xMgr, xRefl, xIntrosp );
fprintf(stderr, "after test_introsp\n" );
}
catch (const Exception & rExc)
{
DBG_UNHANDLED_EXCEPTION("stoc" , "### exception occurred: " << rExc );
}
Reference< XComponent >( xMgr, UNO_QUERY )->dispose();
printf( "testintrosp %s !\n" , (bSucc ? "succeeded" : "failed" ) );
return (bSucc ? 0 : -1);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 C=86 H=95 G=90
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland