Files
libreoffice/stoc/source/invocation/invocation.cxx

1155 lines
38 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2012-06-28 21:09:53 +01:00
/*
* 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 .
*/
2000-09-18 14:29:57 +00:00
#include <osl/mutex.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <cppuhelper/exc_hlp.hxx>
2000-09-18 14:29:57 +00:00
#include <cppuhelper/weak.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/supportsservice.hxx>
2000-09-18 14:29:57 +00:00
#include <cppuhelper/typeprovider.hxx>
#include <cppuhelper/implbase.hxx>
2000-09-18 14:29:57 +00:00
#include <com/sun/star/script/CannotConvertException.hpp>
2000-09-18 14:29:57 +00:00
#include <com/sun/star/script/XTypeConverter.hpp>
#include <com/sun/star/script/XInvocation.hpp>
#include <com/sun/star/script/XInvocation2.hpp>
#include <com/sun/star/reflection/XIdlReflection.hpp>
#include <com/sun/star/reflection/theCoreReflection.hpp>
2000-09-18 14:29:57 +00:00
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/beans/XExactName.hpp>
#include <com/sun/star/beans/XMaterialHolder.hpp>
#include <com/sun/star/beans/theIntrospection.hpp>
2000-09-18 14:29:57 +00:00
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/beans/MethodConcept.hpp>
#include <com/sun/star/beans/PropertyConcept.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XTypeProvider.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <memory>
2000-09-18 14:29:57 +00:00
#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#define SERVICENAME "com.sun.star.script.Invocation"
#define IMPLNAME "com.sun.star.comp.stoc.Invocation"
2000-09-18 14:29:57 +00:00
using namespace css::uno;
using namespace css::lang;
using namespace css::script;
using namespace css::reflection;
using namespace css::beans;
using namespace css::registry;
using namespace css::container;
2000-09-18 14:29:57 +00:00
using namespace cppu;
using namespace osl;
namespace stoc_inv
{
static Sequence< OUString > inv_getSupportedServiceNames()
{
Sequence< OUString > seqNames { SERVICENAME };
2011-06-01 15:34:41 +01:00
return seqNames;
}
static OUString inv_getImplementationName()
{
return OUString(IMPLNAME);
}
2000-09-18 14:29:57 +00:00
// TODO: Implement centrally
2000-09-18 14:29:57 +00:00
inline Reference<XIdlClass> TypeToIdlClass( const Type& rType, const Reference< XIdlReflection > & xRefl )
{
return xRefl->forName( rType.getTypeName() );
}
class Invocation_Impl
: public OWeakObject
, public XInvocation2
, public XNameContainer
, public XIndexContainer
, public XEnumerationAccess
, public XExactName
, public XMaterialHolder
, public XTypeProvider
{
public:
Invocation_Impl( const Any & rAdapted, const Reference<XTypeConverter> &,
const Reference<XIntrospection> &,
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
const Reference<XIdlReflection> &,
bool bFromOLE );
2000-09-18 14:29:57 +00:00
// XInterface
virtual Any SAL_CALL queryInterface( const Type & aType) override;
virtual void SAL_CALL acquire() throw() override { OWeakObject::acquire(); }
virtual void SAL_CALL release() throw() override { OWeakObject::release(); }
2000-09-18 14:29:57 +00:00
// XTypeProvider
virtual Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
2000-09-18 14:29:57 +00:00
// XMaterialHolder
virtual Any SAL_CALL getMaterial() override;
2000-09-18 14:29:57 +00:00
// XInvocation
virtual Reference<XIntrospectionAccess> SAL_CALL getIntrospection() override;
virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) override;
virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) override;
virtual Any SAL_CALL getValue(const OUString& PropertyName) override;
virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) override;
virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) override;
2000-09-18 14:29:57 +00:00
// XInvocation2
virtual Sequence< OUString > SAL_CALL getMemberNames( ) override;
virtual Sequence< InvocationInfo > SAL_CALL getInfo( ) override;
virtual InvocationInfo SAL_CALL getInfoForName( const OUString& aName, sal_Bool bExact ) override;
2000-09-18 14:29:57 +00:00
// All Access and Container methods are not thread safe
2000-09-18 14:29:57 +00:00
// XElementAccess
virtual Type SAL_CALL getElementType() override
2000-09-18 14:29:57 +00:00
{ return _xElementAccess->getElementType(); }
virtual sal_Bool SAL_CALL hasElements() override
2000-09-18 14:29:57 +00:00
{ return _xElementAccess->hasElements(); }
// XNameContainer
virtual void SAL_CALL insertByName( const OUString& Name, const Any& Element ) override
2000-09-18 14:29:57 +00:00
{ _xNameContainer->insertByName( Name, Element ); }
virtual void SAL_CALL removeByName( const OUString& Name ) override
2000-09-18 14:29:57 +00:00
{ _xNameContainer->removeByName( Name ); }
// XNameReplace
virtual void SAL_CALL replaceByName( const OUString& Name, const Any& Element ) override
{ _xNameReplace->replaceByName( Name, Element ); }
2000-09-18 14:29:57 +00:00
// XNameAccess
virtual Any SAL_CALL getByName( const OUString& Name ) override
2000-09-18 14:29:57 +00:00
{ return _xNameAccess->getByName( Name ); }
virtual Sequence<OUString> SAL_CALL getElementNames() override
2000-09-18 14:29:57 +00:00
{ return _xNameAccess->getElementNames(); }
virtual sal_Bool SAL_CALL hasByName( const OUString& Name ) override
2000-09-18 14:29:57 +00:00
{ return _xNameAccess->hasByName( Name ); }
// XIndexContainer
virtual void SAL_CALL insertByIndex( sal_Int32 Index, const Any& Element ) override
2000-09-18 14:29:57 +00:00
{ _xIndexContainer->insertByIndex( Index, Element ); }
virtual void SAL_CALL removeByIndex( sal_Int32 Index ) override
2000-09-18 14:29:57 +00:00
{ _xIndexContainer->removeByIndex( Index ); }
// XIndexReplace
virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const Any& Element ) override
{ _xIndexReplace->replaceByIndex( Index, Element ); }
2000-09-18 14:29:57 +00:00
// XIndexAccess
virtual sal_Int32 SAL_CALL getCount() override
2000-09-18 14:29:57 +00:00
{ return _xIndexAccess->getCount(); }
virtual Any SAL_CALL getByIndex( sal_Int32 Index ) override
2000-09-18 14:29:57 +00:00
{ return _xIndexAccess->getByIndex( Index ); }
// XEnumerationAccess
virtual Reference<XEnumeration> SAL_CALL createEnumeration() override
2000-09-18 14:29:57 +00:00
{ return _xEnumerationAccess->createEnumeration(); }
// XExactName
virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) override;
2000-09-18 14:29:57 +00:00
private:
void setMaterial( const Any& rMaterial );
2000-09-18 14:29:57 +00:00
void getInfoSequenceImpl( Sequence< OUString >* pStringSeq, Sequence< InvocationInfo >* pInfoSeq );
void fillInfoForNameAccess( InvocationInfo& rInfo, const OUString& aName );
static void fillInfoForProperty( InvocationInfo& rInfo, const Property& rProp );
static void fillInfoForMethod( InvocationInfo& rInfo, const Reference< XIdlMethod >& xMethod );
2000-09-18 14:29:57 +00:00
Reference<XTypeConverter> xTypeConverter;
Reference<XIntrospection> xIntrospection;
Reference<XIdlReflection> xCoreReflection;
Any _aMaterial;
// _xDirect and (_xIntrospectionAccess, xPropertySet) are exclusive
Reference<XInvocation> _xDirect;
Reference<XInvocation2> _xDirect2;
Reference<XPropertySet> _xPropertySet;
Reference<XIntrospectionAccess> _xIntrospectionAccess;
// supplied Interfaces
Reference<XNameContainer> _xNameContainer;
Reference<XNameReplace> _xNameReplace;
2000-09-18 14:29:57 +00:00
Reference<XNameAccess> _xNameAccess;
Reference<XIndexContainer> _xIndexContainer;
Reference<XIndexReplace> _xIndexReplace;
2000-09-18 14:29:57 +00:00
Reference<XIndexAccess> _xIndexAccess;
Reference<XEnumerationAccess> _xEnumerationAccess;
Reference<XElementAccess> _xElementAccess;
Reference<XExactName> _xENDirect, _xENIntrospection;
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
bool mbFromOLE;
2000-09-18 14:29:57 +00:00
};
Invocation_Impl::Invocation_Impl
(
const Any & rAdapted,
const Reference<XTypeConverter> & rTC,
const Reference<XIntrospection> & rI,
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
const Reference<XIdlReflection> & rCR,
bool bFromOLE
2000-09-18 14:29:57 +00:00
)
: xTypeConverter( rTC )
, xIntrospection( rI )
2000-09-18 14:29:57 +00:00
, xCoreReflection( rCR )
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
, mbFromOLE( bFromOLE )
2000-09-18 14:29:57 +00:00
{
setMaterial( rAdapted );
}
//### INTERFACE IMPLEMENTATIONS ####################################################################
2000-09-18 14:29:57 +00:00
Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType )
{
// PropertySet implementation
2000-09-18 14:29:57 +00:00
Any a = ::cppu::queryInterface( aType,
static_cast< XInvocation* >(this),
static_cast< XMaterialHolder* >(this),
static_cast< XTypeProvider * >(this) );
2000-09-18 14:29:57 +00:00
if( a.hasValue() )
{
return a;
}
if( aType == cppu::UnoType<XExactName>::get())
2000-09-18 14:29:57 +00:00
{
// Invocation does not support XExactName, if direct object supports
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
// XInvocation, but not XExactName. Except when called from OLE Automation.
if (mbFromOLE ||
(_xDirect.is() && _xENDirect.is()) ||
(!_xDirect.is() && _xENIntrospection.is()))
2000-09-18 14:29:57 +00:00
{
return makeAny( Reference< XExactName >( static_cast< XExactName* >(this) ) );
2000-09-18 14:29:57 +00:00
}
}
else if ( aType == cppu::UnoType<XNameContainer>::get())
2000-09-18 14:29:57 +00:00
{
if( _xNameContainer.is() )
return makeAny( Reference< XNameContainer >( static_cast< XNameContainer* >(this) ) );
2000-09-18 14:29:57 +00:00
}
else if ( aType == cppu::UnoType<XNameReplace>::get())
{
if( _xNameReplace.is() )
return makeAny( Reference< XNameReplace >( static_cast< XNameReplace* >(this) ) );
}
else if ( aType == cppu::UnoType<XNameAccess>::get())
2000-09-18 14:29:57 +00:00
{
if( _xNameAccess.is() )
return makeAny( Reference< XNameAccess >( static_cast< XNameAccess* >(this) ) );
2000-09-18 14:29:57 +00:00
}
else if ( aType == cppu::UnoType<XIndexContainer>::get())
2000-09-18 14:29:57 +00:00
{
if (_xIndexContainer.is())
return makeAny( Reference< XIndexContainer >( static_cast< XIndexContainer* >(this) ) );
2000-09-18 14:29:57 +00:00
}
else if ( aType == cppu::UnoType<XIndexReplace>::get())
{
if (_xIndexReplace.is())
return makeAny( Reference< XIndexReplace >( static_cast< XIndexReplace* >(this) ) );
}
else if ( aType == cppu::UnoType<XIndexAccess>::get())
2000-09-18 14:29:57 +00:00
{
if (_xIndexAccess.is())
return makeAny( Reference< XIndexAccess >( static_cast< XIndexAccess* >(this) ) );
2000-09-18 14:29:57 +00:00
}
else if ( aType == cppu::UnoType<XEnumerationAccess>::get())
2000-09-18 14:29:57 +00:00
{
if (_xEnumerationAccess.is())
return makeAny( Reference< XEnumerationAccess >( static_cast< XEnumerationAccess* >(this) ) );
2000-09-18 14:29:57 +00:00
}
else if ( aType == cppu::UnoType<XElementAccess>::get())
2000-09-18 14:29:57 +00:00
{
if (_xElementAccess.is())
{
2001-06-29 14:00:31 +00:00
return makeAny( Reference< XElementAccess >(
static_cast< XElementAccess* >(static_cast< XNameContainer* >(this)) ) );
2000-09-18 14:29:57 +00:00
}
}
else if ( aType == cppu::UnoType<XInvocation2>::get())
2000-09-18 14:29:57 +00:00
{
// Invocation does not support XInvocation2, if direct object supports
// XInvocation, but not XInvocation2.
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
if ( mbFromOLE ||
( _xDirect.is() && _xDirect2.is()) ||
2000-09-18 14:29:57 +00:00
(!_xDirect.is() && _xIntrospectionAccess.is() ) )
{
return makeAny( Reference< XInvocation2 >( static_cast< XInvocation2* >(this) ) );
2000-09-18 14:29:57 +00:00
}
}
return OWeakObject::queryInterface( aType );
}
Any Invocation_Impl::getMaterial()
2000-09-18 14:29:57 +00:00
{
// AB, 12.2.1999 Make sure that the material is taken when possible
// from the direct Invocation of the Introspection, otherwise structs
// are not handled correctly
2000-09-18 14:29:57 +00:00
Reference<XMaterialHolder> xMaterialHolder;
if( _xDirect.is() )
{
xMaterialHolder.set( _xDirect, UNO_QUERY );
2000-09-18 14:29:57 +00:00
//_xDirect->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
}
else if( _xIntrospectionAccess.is() )
{
xMaterialHolder.set( _xIntrospectionAccess, UNO_QUERY );
2000-09-18 14:29:57 +00:00
//_xIntrospectionAccess->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder );
}
if( xMaterialHolder.is() )
{
return xMaterialHolder->getMaterial();
}
return _aMaterial;
}
2000-09-18 14:29:57 +00:00
void Invocation_Impl::setMaterial( const Any& rMaterial )
{
// set the material first and only once
_aMaterial = rMaterial;
// First do this outside the guard
_xDirect.set( rMaterial, UNO_QUERY );
2000-09-18 14:29:57 +00:00
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
if( !mbFromOLE && _xDirect.is() )
2000-09-18 14:29:57 +00:00
{
// Consult object directly
_xElementAccess.set( _xDirect, UNO_QUERY );
_xEnumerationAccess.set( _xDirect, UNO_QUERY );
_xIndexAccess.set( _xDirect, UNO_QUERY );
_xIndexReplace.set( _xDirect, UNO_QUERY );
_xIndexContainer.set( _xDirect, UNO_QUERY );
_xNameAccess.set( _xDirect, UNO_QUERY );
_xNameReplace.set( _xDirect, UNO_QUERY );
_xNameContainer.set( _xDirect, UNO_QUERY );
_xENDirect.set( _xDirect, UNO_QUERY );
_xDirect2.set( _xDirect, UNO_QUERY );
2000-09-18 14:29:57 +00:00
}
else
{
// Make Invocation on the Introspection
2000-09-18 14:29:57 +00:00
if (xIntrospection.is())
{
_xIntrospectionAccess = xIntrospection->inspect( _aMaterial );
if( _xIntrospectionAccess.is() )
{
_xElementAccess.set(
2000-09-18 14:29:57 +00:00
_xIntrospectionAccess->queryAdapter(
cppu::UnoType<XElementAccess>::get()), UNO_QUERY );
2000-09-18 14:29:57 +00:00
if( _xElementAccess.is() )
{
_xEnumerationAccess.set(
_xIntrospectionAccess->queryAdapter(
cppu::UnoType<XEnumerationAccess>::get()), UNO_QUERY );
2000-09-18 14:29:57 +00:00
_xIndexAccess.set(
_xIntrospectionAccess->queryAdapter(
cppu::UnoType<XIndexAccess>::get()), UNO_QUERY );
2000-09-18 14:29:57 +00:00
if( _xIndexAccess.is() )
{
_xIndexReplace.set(
_xIntrospectionAccess->queryAdapter(
cppu::UnoType<XIndexReplace>::get()), UNO_QUERY );
_xIndexContainer.set(
_xIntrospectionAccess->queryAdapter(
cppu::UnoType<XIndexContainer>::get()), UNO_QUERY );
}
2000-09-18 14:29:57 +00:00
_xNameAccess.set(
_xIntrospectionAccess->queryAdapter(
cppu::UnoType<XNameAccess>::get()), UNO_QUERY );
2000-09-18 14:29:57 +00:00
if( _xNameAccess.is() )
{
_xNameReplace.set(
_xIntrospectionAccess->queryAdapter(
cppu::UnoType<XNameReplace>::get()), UNO_QUERY );
_xNameContainer.set(
_xIntrospectionAccess->queryAdapter(
cppu::UnoType<XNameContainer>::get()), UNO_QUERY );
}
}
2000-09-18 14:29:57 +00:00
_xPropertySet.set( _xIntrospectionAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()),
UNO_QUERY );
2000-09-18 14:29:57 +00:00
_xENIntrospection.set( _xIntrospectionAccess, UNO_QUERY );
2000-09-18 14:29:57 +00:00
}
}
}
}
2000-09-18 14:29:57 +00:00
OUString Invocation_Impl::getExactName( const OUString& rApproximateName )
{
if (_xENDirect.is())
return _xENDirect->getExactName( rApproximateName );
OUString aRet;
if (_xENIntrospection.is())
aRet = _xENIntrospection->getExactName( rApproximateName );
return aRet;
}
Reference<XIntrospectionAccess> Invocation_Impl::getIntrospection()
2000-09-18 14:29:57 +00:00
{
if( _xDirect.is() )
return _xDirect->getIntrospection();
else
return _xIntrospectionAccess;
}
2000-09-18 14:29:57 +00:00
sal_Bool Invocation_Impl::hasMethod( const OUString& Name )
{
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
if (!mbFromOLE && _xDirect.is())
2000-09-18 14:29:57 +00:00
return _xDirect->hasMethod( Name );
if( _xIntrospectionAccess.is() )
return _xIntrospectionAccess->hasMethod( Name, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
return false;
2000-09-18 14:29:57 +00:00
}
2000-09-18 14:29:57 +00:00
sal_Bool Invocation_Impl::hasProperty( const OUString& Name )
{
if (_xDirect.is())
{
bool bRet = _xDirect->hasProperty( Name );
if (bRet || !mbFromOLE)
return bRet;
}
2000-09-18 14:29:57 +00:00
// PropertySet
if( _xIntrospectionAccess.is()
&& _xIntrospectionAccess->hasProperty( Name, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
return true;
2000-09-18 14:29:57 +00:00
// NameAccess
if( _xNameAccess.is() )
return _xNameAccess->hasByName( Name );
return false;
2000-09-18 14:29:57 +00:00
}
2000-09-18 14:29:57 +00:00
Any Invocation_Impl::getValue( const OUString& PropertyName )
{
try
{
if (_xDirect.is())
return _xDirect->getValue( PropertyName );
}
catch (RuntimeException &)
{
if (!mbFromOLE)
throw;
}
try
{
// PropertySet
if( _xIntrospectionAccess.is() && _xPropertySet.is()
&& _xIntrospectionAccess->hasProperty
( PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
{
return _xPropertySet->getPropertyValue( PropertyName );
}
// NameAccess
if( _xNameAccess.is() && _xNameAccess->hasByName( PropertyName ) )
return _xNameAccess->getByName( PropertyName );
}
catch (UnknownPropertyException &)
{
throw;
}
catch (RuntimeException &)
{
throw;
}
catch (Exception &)
2000-09-18 14:29:57 +00:00
{
}
throw UnknownPropertyException( "cannot get value " + PropertyName );
2000-09-18 14:29:57 +00:00
}
2000-09-18 14:29:57 +00:00
void Invocation_Impl::setValue( const OUString& PropertyName, const Any& Value )
{
if (_xDirect.is())
_xDirect->setValue( PropertyName, Value );
else
{
try
2000-09-18 14:29:57 +00:00
{
// Properties
if( _xIntrospectionAccess.is() && _xPropertySet.is()
&& _xIntrospectionAccess->hasProperty(
PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
{
Property aProp = _xIntrospectionAccess->getProperty(
PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
Reference < XIdlClass > r = TypeToIdlClass( aProp.Type, xCoreReflection );
if( r->isAssignableFrom( TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
_xPropertySet->setPropertyValue( PropertyName, Value );
else if( xTypeConverter.is() )
_xPropertySet->setPropertyValue(
PropertyName, xTypeConverter->convertTo( Value, aProp.Type ) );
else
throw RuntimeException( "no type converter service!" );
}
// NameContainer
else if( _xNameContainer.is() )
{
// Note: This misfeature deliberately not adapted to apply to objects which
// have XNameReplace but not XNameContainer
Any aConv;
Reference < XIdlClass > r =
TypeToIdlClass( _xNameContainer->getElementType(), xCoreReflection );
if( r->isAssignableFrom(TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) )
aConv = Value;
else if( xTypeConverter.is() )
aConv = xTypeConverter->convertTo( Value, _xNameContainer->getElementType() );
else
throw RuntimeException( "no type converter service!" );
// Replace if present, otherwise insert
if (_xNameContainer->hasByName( PropertyName ))
_xNameContainer->replaceByName( PropertyName, aConv );
else
_xNameContainer->insertByName( PropertyName, aConv );
}
2000-09-18 14:29:57 +00:00
else
throw UnknownPropertyException( "no introspection nor name container!" );
2000-09-18 14:29:57 +00:00
}
catch (UnknownPropertyException &)
2000-09-18 14:29:57 +00:00
{
throw;
}
catch (CannotConvertException &)
{
throw;
}
catch (InvocationTargetException &)
{
throw;
}
catch (RuntimeException &)
{
throw;
}
2011-12-27 00:12:38 +09:00
catch (const Exception & exc)
{
css::uno::Any anyEx = cppu::getCaughtException();
throw InvocationTargetException(
"exception occurred in setValue(): " + exc.Message,
Reference< XInterface >(), anyEx );
2000-09-18 14:29:57 +00:00
}
}
}
2000-09-18 14:29:57 +00:00
Any Invocation_Impl::invoke( const OUString& FunctionName, const Sequence<Any>& InParams,
Sequence<sal_Int16>& OutIndices, Sequence<Any>& OutParams )
2000-09-18 14:29:57 +00:00
{
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
if (!mbFromOLE && _xDirect.is())
return _xDirect->invoke( FunctionName, InParams, OutIndices, OutParams );
2000-09-18 14:29:57 +00:00
if (_xIntrospectionAccess.is())
{
// throw NoSuchMethodException if not exist
2000-10-06 13:25:14 +00:00
Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod(
FunctionName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
2000-09-18 14:29:57 +00:00
// ParameterInfos
Sequence<ParamInfo> aFParams = xMethod->getParameterInfos();
const ParamInfo* pFParams = aFParams.getConstArray();
sal_Int32 nFParamsLen = aFParams.getLength();
if (nFParamsLen != InParams.getLength())
{
throw IllegalArgumentException(
"incorrect number of parameters passed invoking function " + FunctionName +
": expected " + OUString::number(nFParamsLen) + ", got " + OUString::number(InParams.getLength()),
static_cast<OWeakObject *>(this), sal_Int16(1) );
}
2000-09-18 14:29:57 +00:00
// IN Parameter
const Any* pInParams = InParams.getConstArray();
// Introspection Invoke Parameter
Sequence<Any> aInvokeParams( nFParamsLen );
Any* pInvokeParams = aInvokeParams.getArray();
// OUT Indices
OutIndices.realloc( nFParamsLen );
sal_Int16* pOutIndices = OutIndices.getArray();
2000-09-18 14:29:57 +00:00
sal_uInt32 nOutIndex = 0;
for ( sal_Int32 nPos = 0; nPos < nFParamsLen; ++nPos )
2000-09-18 14:29:57 +00:00
{
try
2000-09-18 14:29:57 +00:00
{
const ParamInfo& rFParam = pFParams[nPos];
const Reference<XIdlClass>& rDestType = rFParam.aType;
// is IN/INOUT parameter?
if (rFParam.aMode != ParamMode_OUT)
{
2000-10-06 13:25:14 +00:00
if (rDestType->isAssignableFrom( TypeToIdlClass( pInParams[nPos].getValueType(), xCoreReflection ) ))
{
pInvokeParams[nPos] = pInParams[nPos];
}
2000-09-18 14:29:57 +00:00
else if (xTypeConverter.is())
{
Type aDestType( rDestType->getTypeClass(), rDestType->getName() );
2000-10-06 13:25:14 +00:00
pInvokeParams[nPos] = xTypeConverter->convertTo( pInParams[nPos], aDestType );
2000-09-18 14:29:57 +00:00
}
else
2000-10-06 13:25:14 +00:00
{
CannotConvertException aExc;
aExc.Context = *this;
aExc.Message = "invocation type mismatch!";
2000-10-06 13:25:14 +00:00
throw aExc;
}
2000-09-18 14:29:57 +00:00
}
// is OUT/INOUT parameter?
if (rFParam.aMode != ParamMode_IN)
{
pOutIndices[nOutIndex] = static_cast<sal_Int16>(nPos);
2000-09-18 14:29:57 +00:00
if (rFParam.aMode == ParamMode_OUT)
rDestType->createObject( pInvokeParams[nPos] ); // default init
++nOutIndex;
}
}
catch( CannotConvertException& rExc )
2000-10-06 13:25:14 +00:00
{
rExc.ArgumentIndex = nPos; // Add optional parameter index
2011-08-10 23:04:54 +02:00
throw;
2000-10-06 13:25:14 +00:00
}
2000-09-18 14:29:57 +00:00
}
// execute Method
Any aRet = xMethod->invoke( _aMaterial, aInvokeParams );
// OUT Params
OutIndices.realloc( nOutIndex );
pOutIndices = OutIndices.getArray();
OutParams.realloc( nOutIndex );
Any* pOutParams = OutParams.getArray();
while (nOutIndex--)
2000-09-18 14:29:57 +00:00
{
pOutParams[nOutIndex] = pInvokeParams[ pOutIndices[nOutIndex] ];
2000-09-18 14:29:57 +00:00
}
return aRet;
2000-09-18 14:29:57 +00:00
}
2000-10-06 13:25:14 +00:00
RuntimeException aExc;
aExc.Context = *this;
aExc.Message = "invocation lacking of introspection access!";
2000-10-06 13:25:14 +00:00
throw aExc;
2000-09-18 14:29:57 +00:00
}
2000-09-18 14:29:57 +00:00
// Struct to optimize sorting
struct MemberItem
{
OUString aName;
// Defines where the member comes from
enum Mode { NAMEACCESS, PROPERTYSET, METHOD } eMode;
2000-09-18 14:29:57 +00:00
// Index to respective sequence
// (Index to NameAccess sequence for eMode==NAMEACCESS etc.)
sal_Int32 nIndex;
};
// Implementation of getting name or info
// String sequence will be filled when pStringSeq != NULL
// Info sequence will be filled when pInfoSeq != NULL
void Invocation_Impl::getInfoSequenceImpl
(
Sequence< OUString >* pStringSeq,
Sequence< InvocationInfo >* pInfoSeq
)
{
//Sequence< OUString > aStrSeq;
//if( !pStringSeq )
//pStringSeq = &aStrSeq;
// Get all needed sequences
Sequence<OUString> aNameAccessNames;
Sequence<Property> aPropertySeq;
Sequence< Reference< XIdlMethod > > aMethodSeq;
if( _xNameAccess.is() )
{
aNameAccessNames = _xNameAccess->getElementNames();
}
if( _xIntrospectionAccess.is() )
{
aPropertySeq = _xIntrospectionAccess->getProperties
( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
aMethodSeq = _xIntrospectionAccess->getMethods
( MethodConcept::ALL - MethodConcept::DANGEROUS );
}
sal_Int32 nNameAccessCount = aNameAccessNames.getLength();
sal_Int32 nPropertyCount = aPropertySeq.getLength();
sal_Int32 nMethodCount = aMethodSeq.getLength();
sal_Int32 nTotalCount = nNameAccessCount + nPropertyCount + nMethodCount;
// Create and fill array of MemberItems
std::unique_ptr< MemberItem []> pItems( new MemberItem[ nTotalCount ] );
2000-09-18 14:29:57 +00:00
const OUString* pStrings = aNameAccessNames.getConstArray();
const Property* pProps = aPropertySeq.getConstArray();
const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
// Fill array of MemberItems
sal_Int32 i, iTotal = 0;
// Name Access
for( i = 0 ; i < nNameAccessCount ; i++, iTotal++ )
{
MemberItem& rItem = pItems[ iTotal ];
rItem.aName = pStrings[ i ];
rItem.eMode = MemberItem::NAMEACCESS;
rItem.nIndex = i;
}
// Property set
for( i = 0 ; i < nPropertyCount ; i++, iTotal++ )
{
MemberItem& rItem = pItems[ iTotal ];
rItem.aName = pProps[ i ].Name;
rItem.eMode = MemberItem::PROPERTYSET;
rItem.nIndex = i;
}
// Methods
for( i = 0 ; i < nMethodCount ; i++, iTotal++ )
{
MemberItem& rItem = pItems[ iTotal ];
Reference< XIdlMethod > xMethod = pMethods[ i ];
rItem.aName = xMethod->getName();
rItem.eMode = MemberItem::METHOD;
rItem.nIndex = i;
}
// Setting up result sequences
OUString* pRetStrings = nullptr;
2000-09-18 14:29:57 +00:00
if( pStringSeq )
{
pStringSeq->realloc( nTotalCount );
pRetStrings = pStringSeq->getArray();
}
InvocationInfo* pRetInfos = nullptr;
2000-09-18 14:29:57 +00:00
if( pInfoSeq )
{
pInfoSeq->realloc( nTotalCount );
pRetInfos = pInfoSeq->getArray();
}
// Fill result sequences in the correct order of members
for( iTotal = 0 ; iTotal < nTotalCount ; iTotal++ )
{
MemberItem& rItem = pItems[ iTotal ];
if( pRetStrings )
{
pRetStrings[ iTotal ] = rItem.aName;
}
if( pRetInfos )
{
if( rItem.eMode == MemberItem::NAMEACCESS )
{
fillInfoForNameAccess( pRetInfos[ iTotal ], rItem.aName );
}
else if( rItem.eMode == MemberItem::PROPERTYSET )
{
fillInfoForProperty( pRetInfos[ iTotal ], pProps[ rItem.nIndex ] );
}
else if( rItem.eMode == MemberItem::METHOD )
{
fillInfoForMethod( pRetInfos[ iTotal ], pMethods[ rItem.nIndex ] );
}
}
}
}
// XInvocation2
Sequence< OUString > SAL_CALL Invocation_Impl::getMemberNames( )
{
if( _xDirect2.is() )
{
return _xDirect2->getMemberNames();
}
Sequence< OUString > aRetSeq;
getInfoSequenceImpl( &aRetSeq, nullptr );
2000-09-18 14:29:57 +00:00
return aRetSeq;
}
Sequence< InvocationInfo > SAL_CALL Invocation_Impl::getInfo( )
{
if( _xDirect2.is() )
{
return _xDirect2->getInfo();
}
Sequence< InvocationInfo > aRetSeq;
getInfoSequenceImpl( nullptr, &aRetSeq );
2000-09-18 14:29:57 +00:00
return aRetSeq;
}
InvocationInfo SAL_CALL Invocation_Impl::getInfoForName( const OUString& aName, sal_Bool bExact )
{
if( _xDirect2.is() )
{
return _xDirect2->getInfoForName( aName, bExact );
}
bool bFound = false;
2000-09-18 14:29:57 +00:00
OUString aExactName = aName;
InvocationInfo aRetInfo;
if( bExact )
aExactName = getExactName( aName );
if( !aExactName.isEmpty() )
2000-09-18 14:29:57 +00:00
{
if( _xIntrospectionAccess->hasMethod( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ) )
{
Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod
( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
fillInfoForMethod( aRetInfo, xMethod );
bFound = true;
2000-09-18 14:29:57 +00:00
}
else
{
if( _xIntrospectionAccess.is() && _xIntrospectionAccess->hasProperty
( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) )
{
Property aProp = _xIntrospectionAccess->getProperty
( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS );
fillInfoForProperty( aRetInfo, aProp );
bFound = true;
2000-09-18 14:29:57 +00:00
}
// NameAccess
else if( _xNameAccess.is() && _xNameAccess->hasByName( aExactName ) )
{
fillInfoForNameAccess( aRetInfo, aExactName );
bFound = true;
2000-09-18 14:29:57 +00:00
}
}
}
if( !bFound )
{
throw IllegalArgumentException(
"getExactName(), Unknown name " + aName,
static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
2000-09-18 14:29:57 +00:00
}
return aRetInfo;
}
// Helper functions to fill InvocationInfo for XNameAccess
void Invocation_Impl::fillInfoForNameAccess
(
InvocationInfo& rInfo,
const OUString& aName
)
{
rInfo.aName = aName;
rInfo.eMemberType = MemberType_PROPERTY;
rInfo.PropertyAttribute = 0;
if( !_xNameContainer.is() )
{
rInfo.PropertyAttribute = PropertyAttribute::READONLY;
}
rInfo.aType = _xNameAccess->getElementType();
}
void Invocation_Impl::fillInfoForProperty
(
InvocationInfo& rInfo,
const Property& rProp
)
{
rInfo.aName = rProp.Name;
rInfo.eMemberType = MemberType_PROPERTY;
rInfo.PropertyAttribute = rProp.Attributes;
rInfo.aType = rProp.Type;
}
void Invocation_Impl::fillInfoForMethod
(
InvocationInfo& rInfo,
const Reference< XIdlMethod >& xMethod
2000-09-18 14:29:57 +00:00
)
{
rInfo.aName = xMethod->getName();
rInfo.eMemberType = MemberType_METHOD;
Reference< XIdlClass > xReturnClass = xMethod->getReturnType();
Type aReturnType( xReturnClass->getTypeClass(), xReturnClass->getName() );
rInfo.aType = aReturnType;
Sequence<ParamInfo> aParamInfos = xMethod->getParameterInfos();
sal_Int32 nParamCount = aParamInfos.getLength();
if( nParamCount > 0 )
{
const ParamInfo* pInfo = aParamInfos.getConstArray();
2000-09-18 14:29:57 +00:00
rInfo.aParamTypes.realloc( nParamCount );
Type* pParamTypes = rInfo.aParamTypes.getArray();
rInfo.aParamModes.realloc( nParamCount );
ParamMode* pParamModes = rInfo.aParamModes.getArray();
for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
{
Reference< XIdlClass > xParamClass = pInfo[i].aType;
2000-09-18 14:29:57 +00:00
Type aParamType( xParamClass->getTypeClass(), xParamClass->getName() );
pParamTypes[ i ] = aParamType;
pParamModes[ i ] = pInfo[i].aMode;
2000-09-18 14:29:57 +00:00
}
}
}
// XTypeProvider
Sequence< Type > SAL_CALL Invocation_Impl::getTypes()
2000-09-18 14:29:57 +00:00
{
static Sequence< Type > const * s_pTypes = nullptr;
2001-06-29 14:00:31 +00:00
if (! s_pTypes)
{
Sequence< Type > types( 4 + 10 );
2001-06-29 14:00:31 +00:00
Type * pTypes = types.getArray();
sal_Int32 n = 0;
pTypes[ n++ ] = cppu::UnoType<XTypeProvider>::get();
pTypes[ n++ ] = cppu::UnoType<XWeak>::get();
pTypes[ n++ ] = cppu::UnoType<XInvocation>::get();
pTypes[ n++ ] = cppu::UnoType<XMaterialHolder>::get();
2001-06-29 14:00:31 +00:00
// Invocation does not support XExactName if direct object supports
2001-06-29 14:00:31 +00:00
// XInvocation, but not XExactName.
if ((_xDirect.is() && _xENDirect.is()) ||
(!_xDirect.is() && _xENIntrospection.is()))
2001-06-29 14:00:31 +00:00
{
pTypes[ n++ ] = cppu::UnoType<XExactName>::get();
2001-06-29 14:00:31 +00:00
}
if( _xNameContainer.is() )
{
pTypes[ n++ ] = cppu::UnoType<XNameContainer>::get();
2001-06-29 14:00:31 +00:00
}
if( _xNameReplace.is() )
{
pTypes[ n++ ] = cppu::UnoType<XNameReplace>::get();
}
2001-06-29 14:00:31 +00:00
if( _xNameAccess.is() )
{
pTypes[ n++ ] = cppu::UnoType<XNameAccess>::get();
2001-06-29 14:00:31 +00:00
}
if (_xIndexContainer.is())
{
pTypes[ n++ ] = cppu::UnoType<XIndexContainer>::get();
2001-06-29 14:00:31 +00:00
}
if (_xIndexReplace.is())
{
pTypes[ n++ ] = cppu::UnoType<XIndexReplace>::get();
}
2001-06-29 14:00:31 +00:00
if (_xIndexAccess.is())
{
pTypes[ n++ ] = cppu::UnoType<XIndexAccess>::get();
2001-06-29 14:00:31 +00:00
}
if (_xEnumerationAccess.is())
{
pTypes[ n++ ] = cppu::UnoType<XEnumerationAccess>::get();
2001-06-29 14:00:31 +00:00
}
if (_xElementAccess.is())
{
pTypes[ n++ ] = cppu::UnoType<XElementAccess>::get();
2001-06-29 14:00:31 +00:00
}
// Invocation does not support XInvocation2, if direct object supports
// XInvocation, but not XInvocation2.
if ( ( _xDirect.is() && _xDirect2.is()) ||
(!_xDirect.is() && _xIntrospectionAccess.is() ) )
{
pTypes[ n++ ] = cppu::UnoType<XInvocation2>::get();
2001-06-29 14:00:31 +00:00
}
types.realloc( n );
2000-09-18 14:29:57 +00:00
2001-06-29 14:00:31 +00:00
// store types
MutexGuard guard( Mutex::getGlobalMutex() );
if (! s_pTypes)
{
static Sequence< Type > s_types( types );
s_pTypes = &s_types;
}
}
return *s_pTypes;
2000-09-18 14:29:57 +00:00
}
Sequence< sal_Int8 > SAL_CALL Invocation_Impl::getImplementationId( )
2000-09-18 14:29:57 +00:00
{
return css::uno::Sequence<sal_Int8>();
2000-09-18 14:29:57 +00:00
}
2000-09-18 14:29:57 +00:00
class InvocationService
: public WeakImplHelper< XSingleServiceFactory, XServiceInfo >
2000-09-18 14:29:57 +00:00
{
public:
explicit InvocationService( const Reference<XComponentContext> & xCtx );
2000-09-18 14:29:57 +00:00
// XServiceInfo
OUString SAL_CALL getImplementationName() override;
sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
2000-09-18 14:29:57 +00:00
// XSingleServiceFactory
Reference<XInterface> SAL_CALL createInstance() override;
2000-09-18 14:29:57 +00:00
Reference<XInterface> SAL_CALL createInstanceWithArguments(
const Sequence<Any>& rArguments ) override;
2000-09-18 14:29:57 +00:00
private:
Reference<XComponentContext> mxCtx;
Reference<XMultiComponentFactory> mxSMgr;
2000-09-18 14:29:57 +00:00
Reference<XTypeConverter> xTypeConverter;
Reference<XIntrospection> xIntrospection;
Reference<XIdlReflection> xCoreReflection;
};
InvocationService::InvocationService( const Reference<XComponentContext> & xCtx )
: mxCtx( xCtx )
, mxSMgr( xCtx->getServiceManager() )
, xCoreReflection( css::reflection::theCoreReflection::get(mxCtx) )
{
xTypeConverter.set(
mxSMgr->createInstanceWithContext( "com.sun.star.script.Converter", xCtx ),
UNO_QUERY );
xIntrospection = theIntrospection::get(xCtx);
}
2000-09-18 14:29:57 +00:00
// XServiceInfo
OUString InvocationService::getImplementationName()
2000-09-18 14:29:57 +00:00
{
return inv_getImplementationName();
2000-09-18 14:29:57 +00:00
}
// XServiceInfo
sal_Bool InvocationService::supportsService(const OUString& ServiceName)
2000-09-18 14:29:57 +00:00
{
return cppu::supportsService(this, ServiceName);
2000-09-18 14:29:57 +00:00
}
// XServiceInfo
Sequence< OUString > InvocationService::getSupportedServiceNames()
2000-09-18 14:29:57 +00:00
{
return inv_getSupportedServiceNames();
2000-09-18 14:29:57 +00:00
}
Reference<XInterface> InvocationService::createInstance()
2000-09-18 14:29:57 +00:00
{
//TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
2000-09-18 14:29:57 +00:00
return Reference<XInterface>(); // dummy
}
2000-09-18 14:29:57 +00:00
Reference<XInterface> InvocationService::createInstanceWithArguments(
const Sequence<Any>& rArguments )
2000-09-18 14:29:57 +00:00
{
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
if (rArguments.getLength() == 2)
{
OUString aArg1;
if ((rArguments[1] >>= aArg1) &&
aArg1 == "FromOLE")
{
return Reference< XInterface >
( *new Invocation_Impl( *rArguments.getConstArray(),
xTypeConverter, xIntrospection, xCoreReflection, true ) );
}
}
2000-09-18 14:29:57 +00:00
if (rArguments.getLength() == 1)
{
return Reference< XInterface >
( *new Invocation_Impl( *rArguments.getConstArray(),
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
xTypeConverter, xIntrospection, xCoreReflection, false ) );
2000-09-18 14:29:57 +00:00
}
Hack to make properties work better from Automation clients There were a couple of problems apparent at this stage when using the ooovbaapi things from a test Automation client (written in VBScript, to be precise). Accessing for instance the ActiveDocument property of an ooo::vba::word::XGlobals instance worked fine. But properties of other objects, like instances of ooo::vba::word::XDocument, did not work. When attempting to access any property of an ooo::vba::word::XDocument, the code ended up calling the hasProperty() of SwVbaDocuemnt. That function is for checking a totally different kind of "properties", namely named form controls. Why form controls are con-fused with oovbaapi properties I don't know. Maybe it is intentional and as expected when using the oovbaapi from the built-in Basic interpreter in LibreOffice. Or then just an accident in history. Still, surely it can't be changed, that would break Basic scripts embedded in existing ODF documents. Anyway, from an OLE Automation client, for instance when asking for the Content property of an ooo::vba::word::XDocument object, we definitely don't want any form control that happens to have the name "Content". We want an object with two integer properties, Start and End. Make this work by always creating an invocation factory instead of using the object itself. Pass the invocation factory's createInstanceWithArguments() function an extra argument indicating this is the case of use from OLE Automation. In the Invocation_Impl class in the stoc module, when this extra argument is noticed, set a new mbFromOLE flag. Modify the behaviour slightly when that is true. I am not at all sure that this will work in all cases, but let's see, at least for simple tests so far it had the intended effect. Another issue was that looking up these properties was case sensitive. This is wrong at least from languages like VBScript. Use the mbFromOLE flag also to affect the case sensitivity behaviour. Maybe I should simply make sure that _xDirect is null in the Automation case? _Direct (a reference to an XInvocation) being non-null probably means that we are using the document interface's own implementation of XInvocation, which is probably always wrong in the OLE Automation case. (Just see the SwVbaDocument implementations of hasProperty() and invoke(), for instance.) Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567 Reviewed-on: https://gerrit.libreoffice.org/55023 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
2018-02-14 22:17:57 +02:00
//TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
return Reference<XInterface>();
2000-09-18 14:29:57 +00:00
}
/// @throws RuntimeException
Reference<XInterface> InvocationService_CreateInstance( const Reference<XComponentContext> & xCtx )
2000-09-18 14:29:57 +00:00
{
Reference<XInterface> xService( *new InvocationService( xCtx ) );
2000-09-18 14:29:57 +00:00
return xService;
}
}
using namespace stoc_inv;
static const struct ImplementationEntry g_entries[] =
{
{
InvocationService_CreateInstance, inv_getImplementationName,
inv_getSupportedServiceNames, createSingleComponentFactory,
nullptr, 0
},
{ nullptr, nullptr, nullptr, nullptr, nullptr, 0 }
};
extern "C" SAL_DLLPUBLIC_EXPORT void * invocation_component_getFactory(
2000-09-18 14:29:57 +00:00
const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
2000-09-18 14:29:57 +00:00
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */