Constructing Helpers
Up to then I have only used C-like style. This C-like style was only to focus on what seems the most important for a beginner : how to handle interfaces, services... But in this chapter we want to show a different way : constructing classes which help the programmer : it's why we name them “helper”. We can encounter such examples in Java code examples which comes with SDK. We begin with the fisrt one which comes in spirit : a connection helper.
Desktop Helper
The GAP's Helper
GAP from India helps me when trying to construct a Run Time Dialog Box. He provided this helper. We first give the SimpleOOConnection.hpp file :
[cpp]
//Listing 1 Gap helper
// C++
// SimpleOOConection.hpp
- ifndef SIMPLEOOCONNECTION_HPP_
- define SIMPLEOOCONNECTION_HPP_
- endif
- include<iostream>
- include <cppuhelper/bootstrap.hxx>
- include <com/sun/star/bridge/XUnoUrlResolver.hpp>
- include <com/sun/star/lang/XMultiServiceFactory.hpp>
using namespace std;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::bridge;
using namespace rtl;
using namespace cppu;
class SimpleOOConnection {
public :
SimpleOOConnection();
Reference< XMultiServiceFactory > connect_ooffice(const char *url);
private :
int iNoOfConnection_;
};
And now the implementation file :
[cpp]
//Listing 2
// C++
- include "SimpleOOConnection.hpp"
// int SimpleOOConnection::iNoOfConnection_=0;
SimpleOOConnection::SimpleOOConnection()
{
iNoOfConnection_++;
}
Reference< XMultiServiceFactory > SimpleOOConnection::connect_ooffice(const char *url)
{
// create the initial component context
cout<<endl;
cout<<url<<"HI"<<endl;
//Initiating Local Component Context
Reference< XComponentContext > rComponentContext =
defaultBootstrap_InitialComponentContext();
/**
- This local Context contents small Service Manager tha konws how to create services that are neccessary to talk to other
- component context.One such service is com.sun.star.bridge.UnoUrlResolver So it ask local Service Manager to create this
- service.
- /
// retrieve the Local Service Manager from the Local context i.e We get Just servicemanager here
Reference< XMultiComponentFactory > rServiceManager =
rComponentContext->getServiceManager();
// here we instantiate a sample service with the service com.sun.star.bridge.UnoUrlResolver . Created by local service manager.
Reference< XInterface > rInstance =
rServiceManager->createInstanceWithContext(
OUString::createFromAscii("com.sun.star.bridge.UnoUrlResolver" ),rComponentContext );
// Query for the XUnoUrlResolver interface fro sample service
Reference< XUnoUrlResolver > rResolver( rInstance, UNO_QUERY );
//Now it uses UnoUrlResolver to get component context together with service manager from server side
try
{
// resolve the uno-url
rInstance = rResolver->resolve( OUString::createFromAscii(url ) );
// query for the simpler XMultiServiceFactory interface, sufficient for scripting
Reference< XMultiServiceFactory > rOfficeServiceManager (rInstance, UNO_QUERY);
return(rOfficeServiceManager);
}
catch( Exception &e )
{
OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
printf( "Error: %s\n", o.pData->buffer );
return('\0');
}
}
Simple Desktop Helper
We first give the header file :
[cpp]
//Listing 3 Header file of the desktop helper
// C++
//********* DesktopHelper class : header DesktopHelper.hpp
- include <com/sun/star/uno/XInterface.hpp>
- include <com/sun/star/frame/XComponentLoader.hpp>
- include <com/sun/star/lang/XMultiServiceFactory.hpp>
- include <com/sun/star/frame/XDesktop.hpp>
using namespace com::sun::star::uno;
using namespace com::sun::star::frame;
using namespace com::sun::star::lang;
class DesktopHelper {
public :
DesktopHelper();
Reference< XInterface > Desktop;
Reference< XComponentLoader > xComponentLoader;
Reference< XMultiServiceFactory > xSVMG;
Reference< XDesktop > xDesktop;
private :
Reference< XMultiServiceFactory > ooConnect();
};
and the implementation :
Listing 4 Desktop helper implementation
// C++
//****** DesktopHelper class : implementation DesktopHelper.cxx
- include <stdio.h>
- include <com/sun/star/bridge/XUnoUrlResolver.hpp>
- include <cppuhelper/bootstrap.hxx>
using namespace com::sun::star::bridge;
using rtl::OUString;
using rtl::OString;
using namespace cppu;
DesktopHelper::DesktopHelper(){
xSVMG = ooConnect();
if( xSVMG.is() ){
printf( "Connected sucessfully to the office\n" );
}
//get the desktop service using createInstance returns an XInterface type
Reference< XInterface > Desktop = xSVMG->createInstance(
OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
//query for the XComponentLoader interface
xComponentLoader = Reference< XComponentLoader > (Desktop, UNO_QUERY);
if( xComponentLoader.is() ){
printf( "XComponentloader successfully instanciated\n" );
}
xDesktop = Reference< XDesktop > (Desktop,UNO_QUERY);
}
Reference< XMultiServiceFactory > DesktopHelper::ooConnect(){
// create the initial component context
Reference< XComponentContext > rComponentContext =
defaultBootstrap_InitialComponentContext();
// retrieve the servicemanager from the context
Reference< XMultiComponentFactory > rServiceManager =
rComponentContext->getServiceManager();
// instantiate a sample service with the servicemanager.
Reference< XInterface > rInstance = rServiceManager->createInstanceWithContext(
OUString::createFromAscii("com.sun.star.bridge.UnoUrlResolver" ),rComponentContext );
// Query for the XUnoUrlResolver interface
Reference< XUnoUrlResolver > rResolver( rInstance, UNO_QUERY );
if( ! rResolver.is() ){
printf( "Error: Couldn't instantiate com.sun.star.bridge.UnoUrlResolver service\n" );
return NULL;
}
try {
// resolve the uno-url
rInstance = rResolver->resolve( OUString::createFromAscii(
"uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" ) );
if( ! rInstance.is() ){
printf( "StarOffice.ServiceManager is not exported from remote counterpart\n" );
return NULL;
}
// query for the simpler XMultiServiceFactory interface, sufficient for scripting
Reference< XMultiServiceFactory > rOfficeServiceManager (rInstance, UNO_QUERY);
if( ! rOfficeServiceManager.is() ){
printf( "XMultiServiceFactory interface is not exported for StarOffice.ServiceManager\n" );
return NULL;
}
return rOfficeServiceManager;
}
catch( Exception &e ){
OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
printf( "Error: %s\n", o.pData->buffer );
return NULL;
}
return NULL;
}
Desktop Helper with message box
What we want here is to have an helper which can avoid us using printf and use a message box instead. But remember the message box interface is deprecated.
The new class definition is :
[cpp]
//Listing 5 A second desktop helper (header file)
// C++
//********* DesktopHelper class : header DesktopHelper.hpp
- include <com/sun/star/uno/XInterface.hpp>
- include <com/sun/star/frame/XComponentLoader.hpp>
- include <com/sun/star/lang/XMultiServiceFactory.hpp>
- include <com/sun/star/frame/XDesktop.hpp>
- include <com/sun/star/awt/XToolkit.hpp>
using namespace com::sun::star::uno;
using namespace com::sun::star::frame;
using namespace com::sun::star::lang;
using namespace com::sun::star::awt;
class DesktopHelper {
public :
DesktopHelper();
void ShowMessageBox( const OUString& aTitle, const OUString& aMsgText );
Reference< XInterface > Desktop;
Reference< XComponentLoader > xComponentLoader;
Reference< XMultiServiceFactory > xSVMG;
Reference< XDesktop > xDesktop;
sal_Int16 endMsgbox;
private :
Reference< XMultiServiceFactory > ooConnect();
sal_Bool useMsgbox;
Reference< XToolkit > xToolkit;
Reference< XFrame > xFrame;
};
and the new constructor :
[cpp]
//Listing 6 A second desktop helper (implementation file)
// C++
DesktopHelper::DesktopHelper(){
useMsgbox = false;
endMsgbox = 0;
xSVMG = ooConnect();
if( xSVMG.is() ){
printf( "Connected sucessfully to the office\n" );
}
//get the desktop service using createInstance returns an XInterface type
Reference< XInterface > Desktop = xSVMG->createInstance(
OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
//query for the XComponentLoader interface
xComponentLoader = Reference< XComponentLoader > (Desktop, UNO_QUERY);
if( xComponentLoader.is() ){
printf( "XComponentloader successfully instanciated\n" );
}
xDesktop = Reference< XDesktop > (Desktop,UNO_QUERY);
xToolkit = Reference< XToolkit >( xSVMG->createInstance(
OUString( RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.awt.Toolkit" ))), UNO_QUERY );
xFrame = xDesktop->getCurrentFrame();
if (xFrame.is() && xToolkit.is()) useMsgbox = true;
}
The method to print out a message is :
[cpp]
//Listing 7 ShowMessageBox function (XMessageBox interface is deprecated)
// C++
void DesktopHelper::ShowMessageBox( const OUString& aTitle, const OUString& aMsgText )
{
if ( useMsgbox )
{
// describe window properties.
WindowDescriptor aDescriptor;
aDescriptor.Type = WindowClass_MODALTOP;
aDescriptor.WindowServiceName = OUString( RTL_CONSTASCII_USTRINGPARAM( "infobox" ));
aDescriptor.ParentIndex = -1;
aDescriptor.Parent = Reference< XWindowPeer > (xFrame->getContainerWindow(), UNO_QUERY );
aDescriptor.Bounds = Rectangle(300,200,300,200);
aDescriptor.WindowAttributes = WindowAttribute::BORDER | WindowAttribute::MOVEABLE | WindowAttribute::CLOSEABLE;
Reference< XWindowPeer > xPeer = xToolkit->createWindow( aDescriptor );
if ( xPeer.is() )
{
Reference< XMessageBox > xMsgBox( xPeer, UNO_QUERY );
if ( xMsgBox.is() )
{
xMsgBox->setCaptionText( aTitle );
xMsgBox->setMessageText( aMsgText );
endMsgbox = xMsgBox->execute();
}
}
}
}
The way to use this new feature is shown in the above listing :
[cpp]
//Listing 8 Using the Desktop Helper
// C++
DesktopHelper *aDesktop = new (DesktopHelper);
aDesktop->ShowMessageBox( OUString::createFromAscii("try"),
OUString::createFromAscii("Hello"));
while (! aDesktop->endMsgbox);
printf("That's all folks !\n");
where you see how to wait the MessageBox ending. This is why I have added this “endMsgbox” component in the class. Effectively, the problem with xMsgBox->execute() is this is a no-blocking instruction, I mean this instruction doesn't wait the MessageBox 's close. If you have no mean to wait, you will have a runtime error if your program finished befor this MessageBox is closed.
Reflection Helper
Presentation
The reflection helper goal is to provide Object informations on methods, interfaces, services and properties. We begin to give the ReflectionHelper.hpp file :
[cpp]
//Listing 11 Header file for reflection helper
// C++
// ReflectionHelper.hpp
- include <rtl/ustring.hxx>
- include <com/sun/star/uno/Sequence.hxx>
- include <com/sun/star/uno/Any.hxx>
- include <com/sun/star/lang/XMultiServiceFactory.hpp>
- include <com/sun/star/beans/XIntrospection.hpp>
- include <com/sun/star/beans/XIntrospectionAccess.hpp>
- include <com/sun/star/lang/XTypeProvider.hpp>
- include <com/sun/star/beans/MethodConcept.hpp>
- include <com/sun/star/reflection/XIdlMethod.hpp>
- include <com/sun/star/uno/Type.hxx>
- include <com/sun/star/beans/Property.hpp>
- include <com/sun/star/lang/XServiceInfo.hpp>
- include <com/sun/star/reflection/ParamMode.hpp>
using rtl::OUString;
using namespace com::sun::star::reflection;
using namespace com::sun::star::beans;
using namespace com::sun::star::lang;
using namespace com::sun::star::uno;
class ReflectionHelper {
public:
ReflectionHelper(Any any,Reference< XMultiServiceFactory > oSVM);
Sequence < OUString > getMethods(),
getTypes(),
getServices(),
getPropertiesWithoutValues(),
getPropertiesWithValues();
and the implementation
private:
Any toInspect;
Reference< XMultiServiceFactory > xServiceManager;
Reference< XIntrospection >xIntrospection;
Reference< XIntrospectionAccess > xIntrospec;
Reference< XTypeProvider > xTypeProvider;
OUString getValueName(Any object);
OUString getParamMode(ParamMode paramMode);
// methods
Sequence< Reference< XIdlMethod > > mMethods;
// Interfaces
Sequence< Type > types;
// Services
Reference< XServiceInfo > xServiceInfo;
// Sequence< OUString > services;
// Properties
Sequence< Property > Properties;
};
[cpp]
//Listing 12 Implementation of the reflection helper
// C++
// with help of <OpenOffice1.1_SDK>/examples/java/Inspector
// and Bernard Marcelly XRay tool
// version 0.1 (22 Dec 2004)
// To do : Exception Handling, to go further with properties values
- include "/home/smoutou/OpenOffice.org1.1_SDK/examples/DevelopersGuide/ProfUNO/CppBinding/ReflectionHelper.hpp"
- include <com/sun/star/reflection/XIdlClass.hpp>
- include <com/sun/star/beans/PropertyConcept.hpp>
- include <com/sun/star/beans/XPropertySet.hpp>
//#include <com/sun/star/reflection/ParamMode.hpp> done in ReflectionHelper.hpp
// constructor
ReflectionHelper::ReflectionHelper(Any any,Reference< XMultiServiceFactory > oSVM)
: toInspect(any), xServiceManager(oSVM){
xIntrospection = Reference< XIntrospection >( xServiceManager->createInstance(
OUString( RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.beans.Introspection" ))), UNO_QUERY );
xIntrospec = xIntrospection->inspect(toInspect);
mMethods = xIntrospec -> getMethods(MethodConcept::ALL);
xTypeProvider = Reference< XTypeProvider> (toInspect,UNO_QUERY);
types = xTypeProvider->getTypes();
xServiceInfo = Reference< XServiceInfo>(toInspect,UNO_QUERY);
Properties = xIntrospec -> getProperties(PropertyConcept::ALL);
}
Sequence < OUString > ReflectionHelper::getServices() {
return xServiceInfo->getSupportedServiceNames();
}
Sequence < OUString > ReflectionHelper::getMethods(){
Sequence< OUString > methods(mMethods.getLength());
for (int i=0;i<mMethods.getLength();i++){
OUString params;
params=OUString::createFromAscii("(");
Sequence< ParamInfo > ParamInfos = mMethods[i]->getParameterInfos();
if (ParamInfos.getLength() > 0) {
for (int j=0;j<ParamInfos.getLength();j++){
Reference< XIdlClass > xIdlClass = ParamInfos[j].aType;
if (j == 0)
// first parameter has no leading comma
params += OUString::createFromAscii("[") + getParamMode(ParamInfos[j].aMode)+
OUString::createFromAscii("]") +
xIdlClass->getName();
else
params += OUString::createFromAscii(",[") + getParamMode(ParamInfos[j].aMode)+
OUString::createFromAscii("]")+
xIdlClass->getName();
}
}
params += OUString::createFromAscii(")");
methods[i] = mMethods[i]->getReturnType()->getName()+OUString::createFromAscii(" ")+
mMethods[i]->getName()+params;
}
return methods;
}
Sequence < OUString > ReflectionHelper::getTypes(){
Sequence< OUString > interfaces(types.getLength());
for (int i=0;i<types.getLength();i++){
interfaces[i] = types[i].getTypeName();
}
return interfaces;
}
// to improve : change all the tests with getCppuType : probably quicker than a string test
OUString ReflectionHelper::getValueName(Any object){
OUString OUStr;
OUStr = OUString::createFromAscii("!! No computed value !!");
if (object.hasValue()) {
if (object.isExtractableTo(getCppuBooleanType())){
sal_Bool MyBool;
object >>= MyBool;
return OUStr.valueOf((sal_Bool) MyBool);
} else
if (object.getValueTypeName() == OUString::createFromAscii("string")) {
OUString *MyOUStr;
MyOUStr = (OUString *) object.getValue();
OUStr = OUString::createFromAscii("\"");
return OUStr + *MyOUStr + OUString::createFromAscii("\"");
} else
if (object.getValueTypeName() == OUString::createFromAscii("long")) {
sal_Int32 *MyLong;
MyLong = (sal_Int32*) object.getValue();
return OUStr.valueOf((sal_Int32) *MyLong);
} else
if (object.getValueTypeName() == OUString::createFromAscii("short")) {
sal_Int16 *MyShort;
MyShort = (sal_Int16*) object.getValue();
return OUStr.valueOf((sal_Int32) *MyShort);
} else
if (object.getValueTypeName() == OUString::createFromAscii("[]byte")) {
Sequence< sal_Int8 > SeqByte;
object >>= SeqByte;
OUStr = OUString::createFromAscii("Length:");
OUStr=OUStr.concat(OUStr.valueOf((sal_Int32) SeqByte.getLength()));
for (sal_Int32 i=0; i<SeqByte.getLength(); i++){
OUStr=OUStr.concat(OUStr.valueOf((sal_Int32) SeqByte[i]));
OUStr=OUStr.concat(OUString::createFromAscii(" "));
}
return OUStr;
} else
if (object.getValueTypeName() == OUString::createFromAscii("[]string")) {
Sequence< OUString > SeqOUStr;
object >>= SeqOUStr;
OUStr = OUString::createFromAscii("Length:");
OUStr=OUStr.concat(OUStr.valueOf((sal_Int32) SeqOUStr.getLength())+
OUString::createFromAscii(" : "));
for (sal_Int32 i=0; i<SeqOUStr.getLength(); i++){
OUStr=OUStr.concat(OUString::createFromAscii("\"")
+SeqOUStr[i]
+ OUString::createFromAscii("\""));
}
return OUStr;
} else return OUStr;
} else return OUStr;
}
// Get properties with values : only those computed in getValueName
Sequence < OUString > ReflectionHelper::getPropertiesWithValues(){
Sequence< OUString > propWithVal(Properties.getLength());
for (int i=0;i<Properties.getLength();i++){
Type typ = getCppuType( (const Reference< XPropertySet > *)0);
Reference< XPropertySet > rPropertySet(xIntrospec->queryAdapter(typ),UNO_QUERY);
Reference< XPropertySetInfo > rPropertySetInfo=rPropertySet->getPropertySetInfo();
Any object; if (rPropertySetInfo->hasPropertyByName(Properties[i].Name)){
object <<= rPropertySet->getPropertyValue(Properties[i].Name);
//if (object.hasValue()) printf("Valeur trouvee : \n");
propWithVal[i] = Properties[i].Name + OUString::createFromAscii(" = (")+
Properties[i].Type.getTypeName() + OUString::createFromAscii(") ")
+ getValueName(object);
}
}
return propWithVal;
}
// Get properties without values but types
Sequence < OUString > ReflectionHelper::getPropertiesWithoutValues(){
Sequence< OUString > propWithVal(Properties.getLength());
for (int i=0;i<Properties.getLength();i++){
Type typ = getCppuType( (const Reference< XPropertySet > *)0);
Reference< XPropertySet > xPropertySet(xIntrospec->queryAdapter(typ),UNO_QUERY);
Reference< XPropertySetInfo > xPropertySetInfo=xPropertySet->getPropertySetInfo();
if (xPropertySetInfo->hasPropertyByName(Properties[i].Name)){
propWithVal[i] = Properties[i].Name + OUString::createFromAscii(" = (")+
Properties[i].Type.getTypeName() + OUString::createFromAscii(")");
}
}
return propWithVal;
}
// Don't forget to add : #include <com/sun/star/reflection/ParamMode.hpp>
// Don't forget to add "com.sun.star.reflection.ParamMode \" in the makefile
OUString ReflectionHelper::getParamMode(ParamMode paramMode) {
OUString toReturn;
toReturn = OUString::createFromAscii("");
if (paramMode == ParamMode_IN) toReturn = OUString::createFromAscii("IN"); else
if (paramMode == ParamMode_OUT) toReturn = OUString::createFromAscii("OUT"); else
if (paramMode == ParamMode_INOUT) toReturn = OUString::createFromAscii("INOUT");
return toReturn;
}
Obtaining properties with values is a difficult task. We give again a schematic explanation :